summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-01-11 15:19:56 +0100
committerChristian Grothoff <christian@grothoff.org>2020-01-11 15:20:17 +0100
commit9443c10d7feb0d91323869dd08ec61ca781564f4 (patch)
treefd617ea56cc1d2ea370ce7e5467574a536b52d28 /src
parent554da10133eb491b352a106b98ebeaed797133bb (diff)
downloadexchange-9443c10d7feb0d91323869dd08ec61ca781564f4.tar.gz
exchange-9443c10d7feb0d91323869dd08ec61ca781564f4.tar.bz2
exchange-9443c10d7feb0d91323869dd08ec61ca781564f4.zip
major refactoring, eliminating wire-plugins and moving towards new bank API. main code compiles, testcases known to fail, code sure not to fully work yet
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/auditor/Makefile.am2
-rw-r--r--src/auditor/taler-auditor.c110
-rw-r--r--src/auditor/taler-wire-auditor.c411
-rw-r--r--src/auditordb/plugin_auditordb_postgres.c72
-rw-r--r--src/bank-lib/Makefile.am13
-rw-r--r--src/bank-lib/bank_api_admin.c71
-rw-r--r--src/bank-lib/bank_api_common.c86
-rw-r--r--src/bank-lib/bank_api_common.h12
-rw-r--r--src/bank-lib/bank_api_credit.c315
-rw-r--r--src/bank-lib/bank_api_debit.c (renamed from src/bank-lib/bank_api_history.c)256
-rw-r--r--src/bank-lib/bank_api_parse.c54
-rw-r--r--src/bank-lib/bank_api_reject.c242
-rw-r--r--src/bank-lib/bank_api_transaction.c368
-rw-r--r--src/bank-lib/fakebank.c728
-rw-r--r--src/bank-lib/fakebank.h283
-rw-r--r--src/bank-lib/fakebank_history.c204
-rw-r--r--src/bank-lib/taler-bank-transfer.c55
-rw-r--r--src/bank-lib/test_bank_api.c2
-rw-r--r--src/bank-lib/testing_api_cmd_history_credit.c (renamed from src/bank-lib/testing_api_cmd_history.c)484
-rw-r--r--src/bank-lib/testing_api_cmd_history_debit.c758
-rw-r--r--src/bank-lib/testing_api_cmd_reject.c223
-rw-r--r--src/benchmark/taler-exchange-benchmark.c69
-rw-r--r--src/exchange-tools/Makefile.am4
-rw-r--r--src/exchange-tools/taler-exchange-keyup.c23
-rw-r--r--src/exchange-tools/taler-wire.c268
-rw-r--r--src/exchange/Makefile.am5
-rw-r--r--src/exchange/taler-exchange-aggregator.c448
-rw-r--r--src/exchange/taler-exchange-httpd_deposit.c13
-rw-r--r--src/exchange/taler-exchange-httpd_validation.c142
-rw-r--r--src/exchange/taler-exchange-wirewatch.c271
-rw-r--r--src/exchangedb/exchangedb_accounts.c12
-rw-r--r--src/exchangedb/exchangedb_fees.c8
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c31
-rw-r--r--src/exchangedb/test_exchangedb.c32
-rw-r--r--src/include/Makefile.am2
-rw-r--r--src/include/taler_auditordb_plugin.h18
-rw-r--r--src/include/taler_bank_service.h313
-rw-r--r--src/include/taler_exchangedb_lib.h9
-rw-r--r--src/include/taler_exchangedb_plugin.h18
-rw-r--r--src/include/taler_fakebank_lib.h25
-rw-r--r--src/include/taler_mhd_lib.h2
-rw-r--r--src/include/taler_testing_bank_lib.h44
-rw-r--r--src/include/taler_testing_lib.h159
-rw-r--r--src/include/taler_wire_lib.h59
-rw-r--r--src/include/taler_wire_plugin.h259
-rw-r--r--src/lib/Makefile.am1
-rw-r--r--src/lib/exchange_api_handle.c2
-rw-r--r--src/lib/testing_api_cmd_bank_check.c69
-rw-r--r--src/lib/testing_api_cmd_fakebank_transfer.c402
-rw-r--r--src/lib/testing_api_cmd_status.c36
-rw-r--r--src/lib/testing_api_cmd_track.c21
-rw-r--r--src/lib/testing_api_trait_reserve_pub.c77
-rw-r--r--src/lib/testing_api_trait_string.c29
-rw-r--r--src/wire-plugins/Makefile.am81
-rw-r--r--src/wire-plugins/plugin_wire_taler-bank.c1306
-rw-r--r--src/wire-plugins/plugin_wire_template.c384
-rw-r--r--src/wire-plugins/test_wire_plugin.c189
-rw-r--r--src/wire-plugins/test_wire_plugin.conf25
-rw-r--r--src/wire-plugins/test_wire_plugin_transactions_taler-bank.c365
-rw-r--r--src/wire-plugins/test_wire_plugin_transactions_taler-bank.conf12
-rw-r--r--src/wire/Makefile.am1
-rw-r--r--src/wire/payto.c104
-rw-r--r--src/wire/wire.c149
-rw-r--r--src/wire/wire_helper.c56
65 files changed, 3771 insertions, 6523 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 761b9c33..cc749e27 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,7 +22,7 @@ pkgcfg_DATA = \
EXTRA_DIST = \
taler.conf
-SUBDIRS = include util wire json curl $(PQ_DIR) mhd $(BANK_LIB) wire-plugins exchangedb exchange exchange-tools auditordb auditor
+SUBDIRS = include util wire json curl $(PQ_DIR) mhd $(BANK_LIB) exchangedb exchange exchange-tools auditordb auditor
if HAVE_LIBCURL
SUBDIRS += lib benchmark
else
diff --git a/src/auditor/Makefile.am b/src/auditor/Makefile.am
index b942076f..d5d7669b 100644
--- a/src/auditor/Makefile.am
+++ b/src/auditor/Makefile.am
@@ -73,10 +73,12 @@ taler_wire_auditor_LDADD = \
$(top_builddir)/src/util/libtalerutil.la \
$(top_builddir)/src/json/libtalerjson.la \
$(top_builddir)/src/wire/libtalerwire.la \
+ $(top_builddir)/src/bank-lib/libtalerbank.la \
$(top_builddir)/src/exchangedb/libtalerexchangedb.la \
$(top_builddir)/src/auditordb/libtalerauditordb.la \
-ljansson \
-lgnunetjson \
+ -lgnunetcurl \
-lgnunetutil
taler_auditor_sign_SOURCES = \
diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c
index 0cc2868f..bb769fd6 100644
--- a/src/auditor/taler-auditor.c
+++ b/src/auditor/taler-auditor.c
@@ -1010,8 +1010,7 @@ struct ReserveContext
* @param reserve_pub public key of the reserve (also the WTID)
* @param credit amount that was received
* @param sender_account_details information about the sender's bank account
- * @param wire_reference unique reference identifying the wire transfer (binary blob)
- * @param wire_reference_size number of bytes in @a wire_reference
+ * @param wire_reference unique reference identifying the wire transfer
* @param execution_date when did we receive the funds
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
@@ -1021,8 +1020,7 @@ handle_reserve_in (void *cls,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *credit,
const char *sender_account_details,
- const void *wire_reference,
- size_t wire_reference_size,
+ uint64_t wire_reference,
struct GNUNET_TIME_Absolute execution_date)
{
struct ReserveContext *rc = cls;
@@ -2032,35 +2030,6 @@ analyze_reserves (void *cls)
/**
- * Information we keep per loaded wire plugin.
- */
-struct WirePlugin
-{
-
- /**
- * Kept in a DLL.
- */
- struct WirePlugin *next;
-
- /**
- * Kept in a DLL.
- */
- struct WirePlugin *prev;
-
- /**
- * Name of the wire method.
- */
- char *type;
-
- /**
- * Handle to the wire plugin.
- */
- struct TALER_WIRE_Plugin *plugin;
-
-};
-
-
-/**
* Information about wire fees charged by the exchange.
*/
struct WireFeeInfo
@@ -2106,16 +2075,6 @@ struct AggregationContext
{
/**
- * DLL of wire plugins encountered.
- */
- struct WirePlugin *wire_head;
-
- /**
- * DLL of wire plugins encountered.
- */
- struct WirePlugin *wire_tail;
-
- /**
* DLL of wire fees charged by the exchange.
*/
struct WireFeeInfo *fee_head;
@@ -2133,46 +2092,6 @@ struct AggregationContext
/**
- * Find the relevant wire plugin.
- *
- * @param ac context to search
- * @param type type of the wire plugin to load; it
- * will be used _as is_ from the dynamic loader.
- * @return NULL on error
- */
-static struct TALER_WIRE_Plugin *
-get_wire_plugin (struct AggregationContext *ac,
- const char *type)
-{
- struct WirePlugin *wp;
- struct TALER_WIRE_Plugin *plugin;
-
- for (wp = ac->wire_head; NULL != wp; wp = wp->next)
- if (0 == strcmp (type,
- wp->type))
- return wp->plugin;
-
- /* Wants the exact *plugin name* (!= method) */
- plugin = TALER_WIRE_plugin_load (cfg,
- type);
- if (NULL == plugin)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to locate wire plugin for `%s'\n",
- type);
- return NULL;
- }
- wp = GNUNET_new (struct WirePlugin);
- wp->type = GNUNET_strdup (type);
- wp->plugin = plugin;
- GNUNET_CONTAINER_DLL_insert (ac->wire_head,
- ac->wire_tail,
- wp);
- return plugin;
-}
-
-
-/**
* Closure for #wire_transfer_information_cb.
*/
struct WireCheckContext
@@ -2884,7 +2803,6 @@ check_wire_out_cb
{
struct AggregationContext *ac = cls;
struct WireCheckContext wcc;
- struct TALER_WIRE_Plugin *plugin;
struct TALER_Amount final_amount;
struct TALER_Amount exchange_gain;
enum GNUNET_DB_QueryStatus qs;
@@ -2976,19 +2894,7 @@ check_wire_out_cb
}
/* Round down to amount supported by wire method */
- plugin = get_wire_plugin
- (ac,
- TALER_WIRE_get_plugin_from_method (method));
- if (NULL == plugin)
- {
- GNUNET_break (0);
- GNUNET_free (method);
- return GNUNET_SYSERR;
- }
- GNUNET_free (method);
- GNUNET_break (GNUNET_SYSERR !=
- plugin->amount_round (plugin->cls,
- &final_amount));
+ GNUNET_break (TALER_WIRE_amount_round (&final_amount));
/* Calculate the exchange's gain as the fees plus rounding differences! */
if (GNUNET_OK !=
@@ -3071,7 +2977,6 @@ static enum GNUNET_DB_QueryStatus
analyze_aggregations (void *cls)
{
struct AggregationContext ac;
- struct WirePlugin *wc;
struct WireFeeInfo *wfi;
enum GNUNET_DB_QueryStatus qsx;
enum GNUNET_DB_QueryStatus qs;
@@ -3125,15 +3030,6 @@ analyze_aggregations (void *cls)
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
ac.qs = qs;
}
- while (NULL != (wc = ac.wire_head))
- {
- GNUNET_CONTAINER_DLL_remove (ac.wire_head,
- ac.wire_tail,
- wc);
- TALER_WIRE_plugin_unload (wc->plugin);
- GNUNET_free (wc->type);
- GNUNET_free (wc);
- }
while (NULL != (wfi = ac.fee_head))
{
GNUNET_CONTAINER_DLL_remove (ac.fee_head,
diff --git a/src/auditor/taler-wire-auditor.c b/src/auditor/taler-wire-auditor.c
index e66834a1..bd961746 100644
--- a/src/auditor/taler-wire-auditor.c
+++ b/src/auditor/taler-wire-auditor.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2017-2019 Taler Systems SA
+ Copyright (C) 2017-2020 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
@@ -27,9 +27,11 @@
*/
#include "platform.h"
#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
#include "taler_auditordb_plugin.h"
#include "taler_exchangedb_plugin.h"
#include "taler_json_lib.h"
+#include "taler_bank_service.h"
#include "taler_wire_lib.h"
#include "taler_signatures.h"
@@ -65,9 +67,14 @@ struct WireAccount
struct WireAccount *prev;
/**
- * Handle to the plugin.
+ * Authentication data for the account.
*/
- struct TALER_WIRE_Plugin *wire_plugin;
+ struct TALER_BANK_AuthenticationData auth;
+
+ /**
+ * Our bank account number.
+ */
+ struct TALER_Account account;
/**
* Name of the section that configures this account.
@@ -77,7 +84,12 @@ struct WireAccount
/**
* Active wire request for the transaction history.
*/
- struct TALER_WIRE_HistoryHandle *hh;
+ struct TALER_BANK_CreditHistoryHandle *chh;
+
+ /**
+ * Active wire request for the transaction history.
+ */
+ struct TALER_BANK_DebitHistoryHandle *dhh;
/**
* Progress point for this account.
@@ -92,17 +104,12 @@ struct WireAccount
/**
* Where we are in the inbound (CREDIT) transaction history.
*/
- void *in_wire_off;
+ uint64_t in_wire_off;
/**
* Where we are in the inbound (DEBIT) transaction history.
*/
- void *out_wire_off;
-
- /**
- * Number of bytes in #in_wire_off and #out_wire_off.
- */
- size_t wire_off_size;
+ uint64_t out_wire_off;
/**
* We should check for inbound transactions to this account.
@@ -341,6 +348,16 @@ static struct TALER_Amount total_wire_format_amount;
*/
static struct TALER_Amount zero;
+/**
+ * Handle to the context for interacting with the bank.
+ */
+static struct GNUNET_CURL_Context *ctx;
+
+/**
+ * Scheduler context for running the @e ctx.
+ */
+static struct GNUNET_CURL_RescheduleContext *rc;
+
/* ***************************** Shutdown **************************** */
@@ -357,14 +374,11 @@ struct ReserveInInfo
struct GNUNET_HashCode row_off_hash;
/**
- * Number of bytes in @e row_off.
- */
- size_t row_off_size;
-
- /**
* Expected details about the wire transfer.
+ * The member "account_url" is to be allocated
+ * at the end of this struct!
*/
- struct TALER_WIRE_TransferDetails details;
+ struct TALER_BANK_CreditDetails details;
/**
* RowID in reserves_in table.
@@ -389,7 +403,7 @@ struct ReserveOutInfo
/**
* Expected details about the wire transfer.
*/
- struct TALER_WIRE_TransferDetails details;
+ struct TALER_BANK_DebitDetails details;
};
@@ -427,8 +441,6 @@ free_rii (void *cls,
GNUNET_CONTAINER_multihashmap_remove (in_map,
key,
rii));
- GNUNET_free (rii->details.account_url);
- GNUNET_free_non_null (rii->details.wtid_s); /* field not used (yet) */
GNUNET_free (rii);
return GNUNET_OK;
}
@@ -453,8 +465,6 @@ free_roi (void *cls,
GNUNET_CONTAINER_multihashmap_remove (out_map,
key,
roi));
- GNUNET_free (roi->details.account_url);
- GNUNET_free_non_null (roi->details.wtid_s); /* field not used (yet) */
GNUNET_free (roi);
return GNUNET_OK;
}
@@ -495,6 +505,17 @@ do_shutdown (void *cls)
{
struct WireAccount *wa;
+ if (NULL != ctx)
+ {
+ GNUNET_CURL_fini (ctx);
+ ctx = NULL;
+ }
+ if (NULL != rc)
+ {
+ GNUNET_CURL_gnunet_rc_destroy (rc);
+ rc = NULL;
+ }
+
if (NULL != report_row_inconsistencies)
{
json_t *report;
@@ -617,21 +638,22 @@ do_shutdown (void *cls)
}
while (NULL != (wa = wa_head))
{
- if (NULL != wa->hh)
+ if (NULL != wa->dhh)
{
- struct TALER_WIRE_Plugin *wp = wa->wire_plugin;
-
- wp->get_history_cancel (wp->cls,
- wa->hh);
- wa->hh = NULL;
+ TALER_BANK_debit_history_cancel (wa->dhh);
+ wa->dhh = NULL;
+ }
+ if (NULL != wa->chh)
+ {
+ TALER_BANK_credit_history_cancel (wa->chh);
+ wa->chh = NULL;
}
GNUNET_CONTAINER_DLL_remove (wa_head,
wa_tail,
wa);
- TALER_WIRE_plugin_unload (wa->wire_plugin);
+ TALER_BANK_auth_free (&wa->auth);
+ TALER_WIRE_account_free (&wa->account);
GNUNET_free (wa->section_name);
- GNUNET_free_non_null (wa->in_wire_off);
- GNUNET_free_non_null (wa->out_wire_off);
GNUNET_free (wa);
}
if (NULL != adb)
@@ -787,8 +809,7 @@ commit (enum GNUNET_DB_QueryStatus qs)
wa->section_name,
&wa->pp,
wa->in_wire_off,
- wa->out_wire_off,
- wa->wire_off_size);
+ wa->out_wire_off);
else
qs = adb->insert_wire_auditor_account_progress (adb->cls,
asession,
@@ -796,8 +817,7 @@ commit (enum GNUNET_DB_QueryStatus qs)
wa->section_name,
&wa->pp,
wa->in_wire_off,
- wa->out_wire_off,
- wa->wire_off_size);
+ wa->out_wire_off);
if (0 >= qs)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -1250,9 +1270,7 @@ complain_out_not_found (void *cls,
"amount_wired", TALER_JSON_from_amount (
&roi->details.amount),
"amount_justified", TALER_JSON_from_amount (&zero),
- "wtid", (NULL == roi->details.wtid_s)
- ? GNUNET_JSON_from_data_auto (&roi->details.wtid)
- : json_string (roi->details.wtid_s),
+ "wtid", GNUNET_JSON_from_data_auto (&roi->details.wtid),
"timestamp", json_from_time_abs (
roi->details.execution_date),
"diagnostic",
@@ -1317,29 +1335,28 @@ check_exchange_wire_out (struct WireAccount *wa)
/**
* This function is called for all transactions that
- * are credited to the exchange's account (incoming
+ * are debited from the exchange's account (outgoing
* transactions).
*
* @param cls `struct WireAccount` with current wire account to process
+ * @param http_status_code http status of the request
* @param ec error code in case something went wrong
- * @param dir direction of the transfer
* @param row_off identification of the position at which we are querying
- * @param row_off_size number of bytes in @a row_off
* @param details details about the wire transfer
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/
static int
history_debit_cb (void *cls,
+ unsigned int http_status_code,
enum TALER_ErrorCode ec,
- enum TALER_BANK_Direction dir,
- const void *row_off,
- size_t row_off_size,
- const struct TALER_WIRE_TransferDetails *details)
+ uint64_t row_off,
+ const struct TALER_BANK_DebitDetails *details,
+ const json_t *json)
{
struct WireAccount *wa = cls;
struct ReserveOutInfo *roi;
- if (TALER_BANK_DIRECTION_NONE == dir)
+ if (NULL == details)
{
if (TALER_EC_NONE != ec)
{
@@ -1348,7 +1365,7 @@ history_debit_cb (void *cls,
"Error fetching history: %u!\n",
(unsigned int) ec);
}
- wa->hh = NULL;
+ wa->dhh = NULL;
check_exchange_wire_out (wa);
return GNUNET_OK;
}
@@ -1357,45 +1374,8 @@ history_debit_cb (void *cls,
GNUNET_STRINGS_absolute_time_to_string (details->execution_date),
TALER_amount2s (&details->amount),
TALER_B2S (&details->wtid));
- if (NULL != details->wtid_s)
- {
- char *diagnostic;
-
- GNUNET_asprintf (&diagnostic,
- "malformed subject `%s'",
- details->wtid_s);
- GNUNET_break (GNUNET_OK ==
- TALER_amount_add (&total_wire_format_amount,
- &total_wire_format_amount,
- &details->amount));
- report (report_wire_format_inconsistencies,
- json_pack ("{s:o, s:o, s:s}",
- "amount", TALER_JSON_from_amount (&details->amount),
- "wire_offset", GNUNET_JSON_from_data (row_off,
- row_off_size),
- "diagnostic", diagnostic));
- GNUNET_free (diagnostic);
- return GNUNET_OK;
- }
-
/* Update offset */
- if (NULL == wa->out_wire_off)
- {
- wa->wire_off_size = row_off_size;
- wa->out_wire_off = GNUNET_malloc (row_off_size);
- }
- if (wa->wire_off_size != row_off_size)
- {
- GNUNET_break (0);
- commit (GNUNET_DB_STATUS_HARD_ERROR);
- wa->hh = NULL;
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_SYSERR;
- }
- memcpy (wa->out_wire_off,
- row_off,
- row_off_size);
-
+ wa->out_wire_off = row_off;
roi = GNUNET_new (struct ReserveOutInfo);
GNUNET_CRYPTO_hash (&details->wtid,
sizeof (details->wtid),
@@ -1420,10 +1400,9 @@ history_debit_cb (void *cls,
&total_wire_format_amount,
&details->amount));
report (report_wire_format_inconsistencies,
- json_pack ("{s:o, s:o, s:s}",
+ json_pack ("{s:o, s:I, s:s}",
"amount", TALER_JSON_from_amount (&details->amount),
- "wire_offset", GNUNET_JSON_from_data (row_off,
- row_off_size),
+ "wire_offset", (json_int_t) row_off,
"diagnostic", diagnostic));
GNUNET_free (diagnostic);
return GNUNET_OK;
@@ -1443,7 +1422,6 @@ static void
process_debits (void *cls)
{
struct WireAccount *wa = cls;
- struct TALER_WIRE_Plugin *wp;
/* skip accounts where DEBIT is not enabled */
while ( (NULL != wa) &&
@@ -1459,17 +1437,16 @@ process_debits (void *cls)
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Checking bank DEBIT records of account `%s'\n",
wa->section_name);
- GNUNET_assert (NULL == wa->hh);
- wp = wa->wire_plugin;
- wa->hh = wp->get_history (wp->cls,
- wa->section_name,
- TALER_BANK_DIRECTION_DEBIT,
- wa->out_wire_off,
- wa->wire_off_size,
- INT64_MAX,
- &history_debit_cb,
- wa);
- if (NULL == wa->hh)
+ GNUNET_assert (NULL == wa->dhh);
+ wa->dhh = TALER_BANK_debit_history (ctx,
+ wa->account.details.x_taler_bank.
+ account_base_url,
+ &wa->auth,
+ wa->out_wire_off,
+ INT64_MAX,
+ &history_debit_cb,
+ wa);
+ if (NULL == wa->dhh)
{
fprintf (stderr,
"Failed to obtain bank transaction history for `%s'\n",
@@ -1519,24 +1496,25 @@ conclude_credit_history ()
* @param rowid unique serial ID for the entry in our DB
* @param reserve_pub public key of the reserve (also the WTID)
* @param credit amount that was received
- * @param sender_url payto://-URL of the sender's bank account
- * @param wire_reference unique identifier for the wire transfer (plugin-specific format)
- * @param wire_reference_size number of bytes in @a wire_reference
+ * @param sender_account_details payto://-URL of the sender's bank account
+ * @param wire_reference unique identifier for the wire transfer
* @param execution_date when did we receive the funds
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
static int
reserve_in_cb (void *cls,
uint64_t rowid,
- const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct
+ TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *credit,
- const char *sender_url,
- const void *wire_reference,
- size_t wire_reference_size,
- struct GNUNET_TIME_Absolute execution_date)
+ const char *sender_account_details,
+ uint64_t wire_reference,
+ struct GNUNET_TIME_Absolute
+ execution_date)
{
struct WireAccount *wa = cls;
struct ReserveInInfo *rii;
+ size_t slen;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Analyzing exchange wire IN (%llu) at %s of %s with reserve_pub %s\n",
@@ -1544,21 +1522,20 @@ reserve_in_cb (void *cls,
GNUNET_STRINGS_absolute_time_to_string (execution_date),
TALER_amount2s (credit),
TALER_B2S (reserve_pub));
- rii = GNUNET_new (struct ReserveInInfo);
- GNUNET_CRYPTO_hash (wire_reference,
- wire_reference_size,
- &rii->row_off_hash);
- rii->row_off_size = wire_reference_size;
+ 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;
- /* reserve public key should be the WTID */
- GNUNET_assert (sizeof (rii->details.wtid) ==
- sizeof (*reserve_pub));
- memcpy (&rii->details.wtid,
- reserve_pub,
- sizeof (*reserve_pub));
- rii->details.account_url = GNUNET_strdup (sender_url);
- rii->rowid = rowid;
+ rii->details.reserve_pub = *reserve_pub;
+ rii->details.account_url = (const char *) &rii[1];
+ memcpy (&rii[1],
+ sender_account_details,
+ slen);
+ GNUNET_CRYPTO_hash (&wire_reference,
+ sizeof (uint64_t),
+ &rii->row_off_hash);
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (in_map,
&rii->row_off_hash,
@@ -1572,8 +1549,6 @@ reserve_in_cb (void *cls,
"wire_offset_hash", GNUNET_JSON_from_data_auto (
&rii->row_off_hash),
"diagnostic", "duplicate wire offset"));
- GNUNET_free (rii->details.account_url);
- GNUNET_free_non_null (rii->details.wtid_s); /* field not used (yet) */
GNUNET_free (rii);
return GNUNET_OK;
}
@@ -1604,7 +1579,8 @@ complain_in_not_found (void *cls,
"amount_exchange_expected", TALER_JSON_from_amount (
&rii->details.amount),
"amount_wired", TALER_JSON_from_amount (&zero),
- "wtid", GNUNET_JSON_from_data_auto (&rii->details.wtid),
+ "reserve_pub", GNUNET_JSON_from_data_auto (
+ &rii->details.reserve_pub),
"timestamp", json_from_time_abs (
rii->details.execution_date),
"account", wa->section_name,
@@ -1635,25 +1611,24 @@ process_credits (void *cls);
*
* @param cls `struct WireAccount` we are processing
* @param ec error code in case something went wrong
- * @param dir direction of the transfer
* @param row_off identification of the position at which we are querying
- * @param row_off_size number of bytes in @a row_off
* @param details details about the wire transfer
+ * @param json raw response
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/
static int
history_credit_cb (void *cls,
+ unsigned int http_status,
enum TALER_ErrorCode ec,
- enum TALER_BANK_Direction dir,
- const void *row_off,
- size_t row_off_size,
- const struct TALER_WIRE_TransferDetails *details)
+ uint64_t row_off,
+ const struct TALER_BANK_CreditDetails *details,
+ const json_t *json)
{
struct WireAccount *wa = cls;
struct ReserveInInfo *rii;
struct GNUNET_HashCode key;
- if (TALER_BANK_DIRECTION_NONE == dir)
+ if (NULL == details)
{
if (TALER_EC_NONE != ec)
{
@@ -1663,7 +1638,7 @@ history_credit_cb (void *cls,
(unsigned int) ec);
}
/* end of operation */
- wa->hh = NULL;
+ wa->chh = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Reconciling CREDIT processing of account `%s'\n",
wa->section_name);
@@ -1678,12 +1653,12 @@ history_credit_cb (void *cls,
return GNUNET_OK;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Analyzing bank CREDIT at %s of %s with WTID %s\n",
+ "Analyzing bank CREDIT at %s of %s with Reserve-pub %s\n",
GNUNET_STRINGS_absolute_time_to_string (details->execution_date),
TALER_amount2s (&details->amount),
- TALER_B2S (&details->wtid));
- GNUNET_CRYPTO_hash (row_off,
- row_off_size,
+ TALER_B2S (&details->reserve_pub));
+ GNUNET_CRYPTO_hash (&row_off,
+ sizeof (row_off),
&key);
rii = GNUNET_CONTAINER_multihashmap_get (in_map,
&key);
@@ -1693,55 +1668,26 @@ history_credit_cb (void *cls,
"Failed to find wire transfer at `%s' in exchange database. Audit ends at this point in time.\n",
GNUNET_STRINGS_absolute_time_to_string (
details->execution_date));
- wa->hh = NULL;
+ wa->chh = NULL;
process_credits (wa->next);
return GNUNET_SYSERR; /* not an error, just end of processing */
}
/* Update offset */
- if (NULL == wa->in_wire_off)
- {
- wa->wire_off_size = row_off_size;
- wa->in_wire_off = GNUNET_malloc (row_off_size);
- }
- if (wa->wire_off_size != row_off_size)
- {
- GNUNET_break (0);
- commit (GNUNET_DB_STATUS_HARD_ERROR);
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_SYSERR;
- }
- memcpy (wa->in_wire_off,
- row_off,
- row_off_size);
-
-
+ wa->in_wire_off = row_off;
/* compare records with expected data */
- if (row_off_size != rii->row_off_size)
- {
- GNUNET_break (0);
- report (report_row_inconsistencies,
- json_pack ("{s:s, s:I, s:o, s:o, s:s}",
- "table", "reserves_in",
- "row", (json_int_t) rii->rowid,
- "raw_bank_row", GNUNET_JSON_from_data (row_off,
- row_off_size),
- "wire_offset_hash", GNUNET_JSON_from_data_auto (&key),
- "diagnostic", "wire reference size missmatch"));
- return GNUNET_OK;
- }
- if (0 != GNUNET_memcmp (&details->wtid,
- &rii->details.wtid))
+ if (0 != GNUNET_memcmp (&details->reserve_pub,
+ &rii->details.reserve_pub))
{
report (report_reserve_in_inconsistencies,
- json_pack ("{s:I, s:o, s:o, s:o, s:o, s:o, s:s}",
+ json_pack ("{s:I, s:I, s:o, s:o, s:o, s:o, s:s}",
"row", (json_int_t) rii->rowid,
- "raw_bank_row", GNUNET_JSON_from_data (row_off,
- row_off_size),
+ "bank_row", (json_int_t) row_off,
"amount_exchange_expected", TALER_JSON_from_amount (
&rii->details.amount),
"amount_wired", TALER_JSON_from_amount (&zero),
- "wtid", GNUNET_JSON_from_data_auto (&rii->details.wtid),
+ "reserve_pub", GNUNET_JSON_from_data_auto (
+ &rii->details.reserve_pub),
"timestamp", json_from_time_abs (
rii->details.execution_date),
"diagnostic", "wire subject does not match"));
@@ -1750,15 +1696,15 @@ history_credit_cb (void *cls,
&total_bad_amount_in_minus,
&rii->details.amount));
report (report_reserve_in_inconsistencies,
- json_pack ("{s:I, s:o, s:o, s:o, s:o, s:o, s:s}",
+ json_pack ("{s:I, s:I, s:o, s:o, s:o, s:o, s:s}",
"row", (json_int_t) rii->rowid,
- "raw_bank_row", GNUNET_JSON_from_data (row_off,
- row_off_size),
+ "bank_row", (json_int_t) row_off,
"amount_exchange_expected", TALER_JSON_from_amount (
&zero),
"amount_wired", TALER_JSON_from_amount (
&details->amount),
- "wtid", GNUNET_JSON_from_data_auto (&details->wtid),
+ "reserve_pub", GNUNET_JSON_from_data_auto (
+ &details->reserve_pub),
"timestamp", json_from_time_abs (
details->execution_date),
"diagnostic", "wire subject does not match"));
@@ -1773,15 +1719,15 @@ history_credit_cb (void *cls,
&details->amount))
{
report (report_reserve_in_inconsistencies,
- json_pack ("{s:I, s:o, s:o, s:o, s:o, s:o, s:s}",
+ json_pack ("{s:I, s:I, s:o, s:o, s:o, s:o, s:s}",
"row", (json_int_t) rii->rowid,
- "raw_bank_row", GNUNET_JSON_from_data (row_off,
- row_off_size),
+ "bank_row", (json_int_t) row_off,
"amount_exchange_expected", TALER_JSON_from_amount (
&rii->details.amount),
"amount_wired", TALER_JSON_from_amount (
&details->amount),
- "wtid", GNUNET_JSON_from_data_auto (&details->wtid),
+ "reserve_pub", GNUNET_JSON_from_data_auto (
+ &details->reserve_pub),
"timestamp", json_from_time_abs (
details->execution_date),
"diagnostic", "wire amount does not match"));
@@ -1820,13 +1766,12 @@ history_credit_cb (void *cls,
rii->details.account_url))
{
report (report_missattribution_in_inconsistencies,
- json_pack ("{s:o, s:I, s:o, s:o}",
+ json_pack ("{s:o, s:I, s:I, s:o}",
"amount", TALER_JSON_from_amount (&rii->details.amount),
"row", (json_int_t) rii->rowid,
- "raw_bank_row", GNUNET_JSON_from_data (row_off,
- row_off_size),
- "wtid", GNUNET_JSON_from_data_auto (
- &rii->details.wtid)));
+ "bank_row", (json_int_t) row_off,
+ "reserve_pub", GNUNET_JSON_from_data_auto (
+ &rii->details.reserve_pub)));
GNUNET_break (GNUNET_OK ==
TALER_amount_add (&total_missattribution_in,
&total_missattribution_in,
@@ -1836,11 +1781,10 @@ history_credit_cb (void *cls,
rii->details.execution_date.abs_value_us)
{
report (report_row_minor_inconsistencies,
- json_pack ("{s:s, s:I, s:o, s:s}",
+ json_pack ("{s:s, s:I, s:I, s:s}",
"table", "reserves_in",
"row", (json_int_t) rii->rowid,
- "raw_bank_row", GNUNET_JSON_from_data (row_off,
- row_off_size),
+ "bank_row", (json_int_t) row_off,
"diagnostic", "execution date missmatch"));
}
cleanup:
@@ -1865,7 +1809,6 @@ static void
process_credits (void *cls)
{
struct WireAccount *wa = cls;
- struct TALER_WIRE_Plugin *wp;
enum GNUNET_DB_QueryStatus qs;
/* skip accounts where CREDIT is not enabled */
@@ -1899,16 +1842,15 @@ process_credits (void *cls)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Starting bank CREDIT history of account `%s'\n",
wa->section_name);
- wp = wa->wire_plugin;
- wa->hh = wp->get_history (wp->cls,
- wa->section_name,
- TALER_BANK_DIRECTION_CREDIT,
- wa->in_wire_off,
- wa->wire_off_size,
- INT64_MAX,
- &history_credit_cb,
- wa);
- if (NULL == wa->hh)
+ wa->chh = TALER_BANK_credit_history (ctx,
+ wa->account.details.x_taler_bank.
+ account_base_url,
+ &wa->auth,
+ wa->in_wire_off,
+ INT64_MAX,
+ &history_credit_cb,
+ wa);
+ if (NULL == wa->chh)
{
fprintf (stderr,
"Failed to obtain bank transaction history\n");
@@ -2037,8 +1979,7 @@ begin_transaction ()
wa->section_name,
&wa->pp,
&wa->in_wire_off,
- &wa->out_wire_off,
- &wa->wire_off_size);
+ &wa->out_wire_off);
if (0 > qsx)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsx);
@@ -2096,30 +2037,62 @@ process_account_cb (void *cls,
const struct TALER_EXCHANGEDB_AccountInfo *ai)
{
struct WireAccount *wa;
- struct TALER_WIRE_Plugin *wp;
if ( (GNUNET_NO == ai->debit_enabled) &&
(GNUNET_NO == ai->credit_enabled) )
return; /* not an active exchange account */
- wp = TALER_WIRE_plugin_load (cfg,
- ai->plugin_name);
- if (NULL == wp)
- {
- fprintf (stderr,
- "Failed to load wire plugin `%s'\n",
- ai->plugin_name);
- global_ret = 1;
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Found exchange account `%s'\n",
ai->section_name);
wa = GNUNET_new (struct WireAccount);
- wa->wire_plugin = wp;
wa->section_name = GNUNET_strdup (ai->section_name);
wa->watch_debit = ai->debit_enabled;
wa->watch_credit = ai->credit_enabled;
+ if (GNUNET_OK !=
+ TALER_BANK_auth_parse_cfg (cfg,
+ ai->section_name,
+ &wa->auth))
+ {
+ GNUNET_break (0);
+ GNUNET_free (wa->section_name);
+ GNUNET_free (wa);
+ fprintf (stderr,
+ "Failed to access bank account `%s'\n",
+ wa->section_name);
+ global_ret = 1;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_OK !=
+ TALER_BANK_account_parse_cfg (cfg,
+ wa->section_name,
+ &wa->account))
+ {
+ GNUNET_break (0);
+ TALER_BANK_auth_free (&wa->auth);
+ GNUNET_free (wa->section_name);
+ GNUNET_free (wa);
+ fprintf (stderr,
+ "Failed to access bank account `%s'\n",
+ wa->section_name);
+ global_ret = 1;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (TALER_PAC_X_TALER_BANK != wa->account.type)
+ {
+ GNUNET_break (0);
+ TALER_WIRE_account_free (&wa->account);
+ TALER_BANK_auth_free (&wa->auth);
+ GNUNET_free (wa->section_name);
+ GNUNET_free (wa);
+ fprintf (stderr,
+ "Need x-taler-bank account URL in `%s'\n",
+ wa->section_name);
+ global_ret = 1;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
GNUNET_CONTAINER_DLL_insert (wa_head,
wa_tail,
wa);
@@ -2258,6 +2231,14 @@ run (void *cls,
}
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
NULL);
+ ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+ &rc);
+ rc = GNUNET_CURL_gnunet_rc_create (ctx);
+ if (NULL == ctx)
+ {
+ GNUNET_break (0);
+ return;
+ }
esession = edb->get_session (edb->cls);
if (NULL == esession)
{
diff --git a/src/auditordb/plugin_auditordb_postgres.c b/src/auditordb/plugin_auditordb_postgres.c
index 060e745d..7360258a 100644
--- a/src/auditordb/plugin_auditordb_postgres.c
+++ b/src/auditordb/plugin_auditordb_postgres.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2018 GNUnet e.V.
+ Copyright (C) 2014-2020 GNUnet e.V.
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
@@ -241,8 +241,8 @@ postgres_create_tables (void *cls)
",account_name TEXT NOT NULL"
",last_wire_reserve_in_serial_id INT8 NOT NULL DEFAULT 0"
",last_wire_wire_out_serial_id INT8 NOT NULL DEFAULT 0"
- ",wire_in_off BYTEA"
- ",wire_out_off BYTEA"
+ ",wire_in_off INT8"
+ ",wire_out_off INT8"
")"),
GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS wire_auditor_progress"
"(master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES auditor_exchanges(master_pub) ON DELETE CASCADE"
@@ -2135,23 +2135,16 @@ postgres_insert_wire_auditor_account_progress (void *cls,
const struct
TALER_AUDITORDB_WireAccountProgressPoint
*pp,
- const void *in_wire_off,
- const void *out_wire_off,
- size_t wire_off_size)
+ uint64_t in_wire_off,
+ uint64_t out_wire_off)
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (master_pub),
GNUNET_PQ_query_param_string (account_name),
GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_wire_out_serial_id),
- GNUNET_PQ_query_param_fixed_size (in_wire_off,
- NULL == in_wire_off
- ? 0
- : wire_off_size),
- GNUNET_PQ_query_param_fixed_size (out_wire_off,
- NULL == out_wire_off
- ? 0
- : wire_off_size),
+ GNUNET_PQ_query_param_uint64 (&in_wire_off),
+ GNUNET_PQ_query_param_uint64 (&out_wire_off),
GNUNET_PQ_query_param_end
};
@@ -2182,21 +2175,14 @@ postgres_update_wire_auditor_account_progress (void *cls,
const struct
TALER_AUDITORDB_WireAccountProgressPoint
*pp,
- const void *in_wire_off,
- const void *out_wire_off,
- size_t wire_off_size)
+ uint64_t in_wire_off,
+ uint64_t out_wire_off)
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_wire_out_serial_id),
- GNUNET_PQ_query_param_fixed_size (in_wire_off,
- NULL == in_wire_off
- ? 0
- : wire_off_size),
- GNUNET_PQ_query_param_fixed_size (out_wire_off,
- NULL == out_wire_off
- ? 0
- : wire_off_size),
+ GNUNET_PQ_query_param_uint64 (&in_wire_off),
+ GNUNET_PQ_query_param_uint64 (&out_wire_off),
GNUNET_PQ_query_param_auto_from_type (master_pub),
GNUNET_PQ_query_param_string (account_name),
GNUNET_PQ_query_param_end
@@ -2231,12 +2217,9 @@ postgres_get_wire_auditor_account_progress (void *cls,
struct
TALER_AUDITORDB_WireAccountProgressPoint
*pp,
- void **in_wire_off,
- void **out_wire_off,
- size_t *wire_off_size)
+ uint64_t *in_wire_off,
+ uint64_t *out_wire_off)
{
- size_t xsize;
- enum GNUNET_DB_QueryStatus qs;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (master_pub),
GNUNET_PQ_query_param_string (account_name),
@@ -2247,30 +2230,17 @@ postgres_get_wire_auditor_account_progress (void *cls,
&pp->last_reserve_in_serial_id),
GNUNET_PQ_result_spec_uint64 ("last_wire_wire_out_serial_id",
&pp->last_wire_out_serial_id),
- GNUNET_PQ_result_spec_variable_size ("wire_in_off",
- in_wire_off,
- wire_off_size),
- GNUNET_PQ_result_spec_variable_size ("wire_out_off",
- out_wire_off,
- &xsize),
+ GNUNET_PQ_result_spec_uint64 ("wire_in_off",
+ in_wire_off),
+ GNUNET_PQ_result_spec_uint64 ("wire_out_off",
+ out_wire_off),
GNUNET_PQ_result_spec_end
};
- qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn,
- "wire_auditor_account_progress_select",
- params,
- rs);
- if (qs <= 0)
- {
- *wire_off_size = 0;
- xsize = 0;
- }
- if ( (0 != xsize) &&
- (0 != *wire_off_size) )
- {
- GNUNET_assert (xsize == *wire_off_size);
- }
- return qs;
+ return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+ "wire_auditor_account_progress_select",
+ params,
+ rs);
}
diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am
index 3bb86323..371f5e6d 100644
--- a/src/bank-lib/Makefile.am
+++ b/src/bank-lib/Makefile.am
@@ -39,8 +39,9 @@ libtalerbank_la_LDFLAGS = \
libtalerbank_la_SOURCES = \
bank_api_admin.c \
bank_api_common.c bank_api_common.h \
- bank_api_history.c \
- bank_api_reject.c \
+ bank_api_credit.c \
+ bank_api_debit.c \
+ bank_api_transaction.c \
bank_api_parse.c
libtalerbank_la_LIBADD = \
$(top_builddir)/src/json/libtalerjson.la \
@@ -55,10 +56,10 @@ libtalerfakebank_la_LDFLAGS = \
-version-info 0:0:0 \
-no-undefined
libtalerfakebank_la_SOURCES = \
- fakebank_history.c \
- fakebank.c fakebank.h
+ fakebank.c
libtalerfakebank_la_LIBADD = \
$(top_builddir)/src/json/libtalerjson.la \
+ $(top_builddir)/src/mhd/libtalermhd.la \
-lgnunetjson \
-lgnunetutil \
-ljansson \
@@ -69,8 +70,8 @@ libtalerbanktesting_la_LDFLAGS = \
-version-info 0:0:0 \
-no-undefined
libtalerbanktesting_la_SOURCES = \
- testing_api_cmd_history.c \
- testing_api_cmd_reject.c \
+ testing_api_cmd_history_credit.c \
+ testing_api_cmd_history_debit.c \
testing_api_helpers.c
libtalerbanktesting_la_LIBADD = \
$(top_builddir)/src/json/libtalerjson.la \
diff --git a/src/bank-lib/bank_api_admin.c b/src/bank-lib/bank_api_admin.c
index 5240a372..068fd0e0 100644
--- a/src/bank-lib/bank_api_admin.c
+++ b/src/bank-lib/bank_api_admin.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2015, 2016, 2017 Taler Systems SA
+ Copyright (C) 2015--2020 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
@@ -166,13 +166,11 @@ handle_admin_add_incoming_finished (void *cls,
* to the operators of the bank.
*
* @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this request)
+ * @param account_base_url URL of the bank (used to execute this request)
* @param auth authentication data to send to the bank
- * @param exchange_base_url base URL of the exchange (for tracking)
- * @param subject wire transfer subject for the transfer
+ * @param reserve_pub wire transfer subject for the transfer
* @param amount amount that was deposited
- * @param debit_account_no account number to withdraw from (53 bits at most)
- * @param credit_account_no account number to deposit into (53 bits at most)
+ * @param credit_account account to deposit into (payto)
* @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
@@ -181,13 +179,12 @@ handle_admin_add_incoming_finished (void *cls,
*/
struct TALER_BANK_AdminAddIncomingHandle *
TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context *ctx,
- const char *bank_base_url,
+ const char *account_base_url,
const struct TALER_BANK_AuthenticationData *auth,
- const char *exchange_base_url,
- const char *subject,
+ const struct
+ TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *amount,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
+ const char *credit_account,
TALER_BANK_AdminAddIncomingResultCallback res_cb,
void *res_cb_cls)
{
@@ -195,18 +192,10 @@ TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context *ctx,
json_t *admin_obj;
CURL *eh;
- if (NULL == exchange_base_url)
- {
- GNUNET_break (0);
- return NULL;
- }
- admin_obj = json_pack ("{s:{s:s}, s:s, s:s, s:o, s:I, s:I}",
- "auth", "type", "basic",
- "exchange_url", exchange_base_url,
- "subject", subject,
+ admin_obj = json_pack ("{s:o, s:o, s:s}",
+ "subject", GNUNET_JSON_from_data_auto (reserve_pub),
"amount", TALER_JSON_from_amount (amount),
- "debit_account", (json_int_t) debit_account_no,
- "credit_account", (json_int_t) credit_account_no);
+ "credit_account", credit_account);
if (NULL == admin_obj)
{
GNUNET_break (0);
@@ -215,27 +204,33 @@ TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context *ctx,
aai = GNUNET_new (struct TALER_BANK_AdminAddIncomingHandle);
aai->cb = res_cb;
aai->cb_cls = res_cb_cls;
- aai->request_url = TALER_BANK_path_to_url_ (bank_base_url,
+ aai->request_url = TALER_BANK_path_to_url_ (account_base_url,
"/admin/add/incoming");
- aai->post_ctx.headers = TALER_BANK_make_auth_header_ (auth);
-
- GNUNET_assert
- (NULL != (aai->post_ctx.headers = curl_slist_append
- (aai->post_ctx.headers,
- "Content-Type: application/json")));
+ aai->post_ctx.headers = curl_slist_append
+ (aai->post_ctx.headers,
+ "Content-Type: application/json");
eh = curl_easy_init ();
-
- GNUNET_assert (GNUNET_OK ==
- TALER_curl_easy_post (&aai->post_ctx, eh, admin_obj));
-
+ if ( (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_incoming_cancel (aai);
+ curl_easy_cleanup (eh);
+ json_decref (admin_obj);
+ return NULL;
+ }
json_decref (admin_obj);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- aai->request_url));
-
aai->job = GNUNET_CURL_job_add2 (ctx,
eh,
aai->post_ctx.headers,
diff --git a/src/bank-lib/bank_api_common.c b/src/bank-lib/bank_api_common.c
index 50769dae..8a8f4289 100644
--- a/src/bank-lib/bank_api_common.c
+++ b/src/bank-lib/bank_api_common.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2015, 2016, 2017 GNUnet e.V.
+ Copyright (C) 2015-2020 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
@@ -24,67 +24,47 @@
/**
- * Append HTTP key-value pair to curl header list.
+ * Set authentication data in @a easy from @a auth.
+ * The API currently specifies the use of HTTP basic
+ * authentication.
*
- * @param hdr list to append to, can be NULL
- * @param key key to append
- * @param value value to append
- * @return new list, NULL on error
+ * @param easy curl handle to setup for authentication
+ * @param auth authentication data to use
+ * @return #GNUNET_OK in success
*/
-static struct curl_slist *
-append (struct curl_slist *hdr,
- const char *key,
- const char *value)
+int
+TALER_BANK_setup_auth_ (CURL *easy,
+ const struct TALER_BANK_AuthenticationData *auth)
{
- char *str;
- struct curl_slist *ret;
-
- GNUNET_asprintf (&str,
- "%s: %s",
- key,
- value);
- ret = curl_slist_append (hdr,
- str);
- GNUNET_free (str);
- if (NULL == ret)
- {
- GNUNET_break (0);
- curl_slist_free_all (hdr);
- return NULL;
- }
- return ret;
-}
-
-
-/**
- * Build authentication header from @a auth.
- *
- * @param auth authentication data to use.
- *
- * @return NULL on error, otherwise curl headers to use.
- */
-struct curl_slist *
-TALER_BANK_make_auth_header_
- (const struct TALER_BANK_AuthenticationData *auth)
-{
- struct curl_slist *authh;
+ int ret;
+ ret = GNUNET_OK;
switch (auth->method)
{
case TALER_BANK_AUTH_NONE:
- return NULL;
+ return GNUNET_OK;
case TALER_BANK_AUTH_BASIC:
- authh = append (NULL,
- "X-Taler-Bank-Username",
- auth->details.basic.username);
- if (NULL == authh)
- return NULL;
- authh = append (authh,
- "X-Taler-Bank-Password",
- auth->details.basic.password);
- return authh;
+ {
+ char *up;
+
+ GNUNET_asprintf (&up,
+ "%s:%s",
+ auth->details.basic.username,
+ auth->details.basic.password);
+ if ( (CURLE_OK !=
+ curl_easy_setopt (easy,
+ CURLOPT_HTTPAUTH,
+ CURLAUTH_BASIC)) ||
+ (CURLE_OK !=
+ curl_easy_setopt (easy,
+ CURLOPT_USERPWD,
+ up)) )
+ ret = GNUNET_SYSERR;
+ GNUNET_free (up);
+ break;
+ }
}
- return NULL;
+ return ret;
}
diff --git a/src/bank-lib/bank_api_common.h b/src/bank-lib/bank_api_common.h
index fcf2029d..1120ed94 100644
--- a/src/bank-lib/bank_api_common.h
+++ b/src/bank-lib/bank_api_common.h
@@ -40,6 +40,18 @@ TALER_BANK_make_auth_header_ (const struct TALER_BANK_AuthenticationData *auth);
/**
+ * Set authentication data in @a easy from @a auth.
+ *
+ * @param easy curl handle to setup for authentication
+ * @param auth authentication data to use
+ * @return #GNUNET_OK in success
+ */
+int
+TALER_BANK_setup_auth_ (CURL *easy,
+ const struct TALER_BANK_AuthenticationData *auth);
+
+
+/**
* Obtain the URL to use for an API request.
*
* @param u base URL of the bank
diff --git a/src/bank-lib/bank_api_credit.c b/src/bank-lib/bank_api_credit.c
new file mode 100644
index 00000000..ed0a1e2a
--- /dev/null
+++ b/src/bank-lib/bank_api_credit.c
@@ -0,0 +1,315 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2017--2020 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_history.c
+ * @brief Implementation of the /history[-range]
+ * requests of the bank's HTTP API.
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include "bank_api_common.h"
+#include <microhttpd.h> /* just for HTTP status codes */
+#include "taler_signatures.h"
+
+
+/**
+ * @brief A /history Handle
+ */
+struct TALER_BANK_CreditHistoryHandle
+{
+
+ /**
+ * The url for this request.
+ */
+ char *request_url;
+
+ /**
+ * The base URL of the bank.
+ */
+ char *bank_base_url;
+
+ /**
+ * Handle for the request.
+ */
+ struct GNUNET_CURL_Job *job;
+
+ /**
+ * Function to call with the result.
+ */
+ TALER_BANK_CreditResultCallback hcb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *hcb_cls;
+};
+
+
+/**
+ * Parse history given in JSON format and invoke the callback on each item.
+ *
+ * @param hh handle to the account history request
+ * @param history JSON array with the history
+ * @return #GNUNET_OK if history was valid and @a rhistory and @a balance
+ * were set,
+ * #GNUNET_SYSERR if there was a protocol violation in @a history
+ */
+static int
+parse_account_history (struct TALER_BANK_CreditHistoryHandle *hh,
+ const json_t *history)
+{
+ json_t *history_array;
+
+ if (NULL == (history_array = json_object_get (history,
+ "data")))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if (! json_is_array (history_array))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ for (unsigned int i = 0; i<json_array_size (history_array); i++)
+ {
+ struct TALER_BANK_CreditDetails td;
+ uint64_t row_id;
+ struct GNUNET_JSON_Specification hist_spec[] = {
+ TALER_JSON_spec_amount ("amount",
+ &td.amount),
+ GNUNET_JSON_spec_absolute_time ("date",
+ &td.execution_date),
+ GNUNET_JSON_spec_uint64 ("row_id",
+ &row_id),
+ GNUNET_JSON_spec_fixed_auto ("reserve_pub",
+ &td.reserve_pub),
+ GNUNET_JSON_spec_string ("counterpart",
+ &td.account_url),
+ GNUNET_JSON_spec_end ()
+ };
+ json_t *transaction = json_array_get (history_array,
+ i);
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (transaction,
+ hist_spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ hh->hcb (hh->hcb_cls,
+ MHD_HTTP_OK,
+ TALER_EC_NONE,
+ row_id,
+ &td,
+ transaction);
+ GNUNET_JSON_parse_free (hist_spec);
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP /history request.
+ *
+ * @param cls the `struct TALER_BANK_CreditHistoryHandle`
+ * @param response_code HTTP response code, 0 on error
+ * @param response parsed JSON result, NULL on error
+ */
+static void
+handle_history_finished (void *cls,
+ long response_code,
+ const void *response)
+{
+ struct TALER_BANK_CreditHistoryHandle *hh = cls;
+ enum TALER_ErrorCode ec;
+ const json_t *j = response;
+
+ hh->job = NULL;
+ switch (response_code)
+ {
+ case 0:
+ ec = TALER_EC_INVALID_RESPONSE;
+ break;
+ case MHD_HTTP_OK:
+ if (GNUNET_OK !=
+ parse_account_history (hh,
+ j))
+ {
+ GNUNET_break_op (0);
+ response_code = 0;
+ ec = TALER_EC_INVALID_RESPONSE;
+ break;
+ }
+ response_code = MHD_HTTP_NO_CONTENT; /* signal end of list */
+ ec = TALER_EC_NONE;
+ break;
+ case MHD_HTTP_NO_CONTENT:
+ ec = TALER_EC_NONE;
+ 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 */
+ ec = TALER_BANK_parse_ec_ (j);
+ break;
+ case MHD_HTTP_FORBIDDEN:
+ /* Access denied */
+ ec = TALER_BANK_parse_ec_ (j);
+ break;
+ case MHD_HTTP_UNAUTHORIZED:
+ /* Nothing really to verify, bank says one of the signatures is
+ invalid; as we checked them, this should never happen, we
+ should pass the JSON reply to the application */
+ ec = TALER_BANK_parse_ec_ (j);
+ break;
+ case MHD_HTTP_NOT_FOUND:
+ /* Nothing really to verify, this should never
+ happen, we should pass the JSON reply to the application */
+ ec = TALER_BANK_parse_ec_ (j);
+ break;
+ case MHD_HTTP_INTERNAL_SERVER_ERROR:
+ /* Server had an internal issue; we should retry, but this API
+ leaves this to the application */
+ ec = TALER_BANK_parse_ec_ (j);
+ break;
+ default:
+ /* unexpected response code */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u\n",
+ (unsigned int) response_code);
+ GNUNET_break (0);
+ ec = TALER_BANK_parse_ec_ (j);
+ response_code = 0;
+ break;
+ }
+ hh->hcb (hh->hcb_cls,
+ response_code,
+ ec,
+ 0LLU,
+ NULL,
+ j);
+ TALER_BANK_credit_history_cancel (hh);
+}
+
+
+/**
+ * Request the credit history of the exchange's bank account.
+ *
+ * @param ctx curl context for the event loop
+ * @param bank_base_url URL of the base INCLUDING account number
+ * @param auth authentication data to use
+ * @param start_row from which row on do we want to get results,
+ * use UINT64_MAX for the latest; exclusive
+ * @param num_results how many results do we want;
+ * negative numbers to go into the past, positive numbers
+ * to go into the future starting at @a start_row;
+ * must not be zero.
+ * @param hres_cb the callback to call with the transaction
+ * history
+ * @param hres_cb_cls closure for the above callback
+ * @return NULL if the inputs are invalid (i.e. zero value for
+ * @e num_results). In this case, the callback is not
+ * called.
+ */
+struct TALER_BANK_CreditHistoryHandle *
+TALER_BANK_credit_history (struct GNUNET_CURL_Context *ctx,
+ const char *bank_base_url,
+ const struct TALER_BANK_AuthenticationData *auth,
+ uint64_t start_row,
+ int64_t num_results,
+ TALER_BANK_CreditResultCallback hres_cb,
+ void *hres_cb_cls)
+{
+ char *url;
+ struct TALER_BANK_CreditHistoryHandle *hh;
+ CURL *eh;
+
+ if (0 == num_results)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+
+ if (UINT64_MAX == start_row)
+ GNUNET_asprintf (&url,
+ "/history&delta=%lld",
+ (long long) num_results);
+ else
+ GNUNET_asprintf (&url,
+ "/history&delta=%lld&start=%llu",
+ (long long) num_results,
+ start_row);
+ hh = GNUNET_new (struct TALER_BANK_CreditHistoryHandle);
+ hh->hcb = hres_cb;
+ hh->hcb_cls = hres_cb_cls;
+ hh->bank_base_url = GNUNET_strdup (bank_base_url);
+ hh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
+ url);
+
+ eh = curl_easy_init ();
+ if ( (GNUNET_OK !=
+ TALER_BANK_setup_auth_ (eh,
+ auth)) ||
+ (CURLE_OK !=
+ curl_easy_setopt (eh,
+ CURLOPT_URL,
+ hh->request_url)) )
+ {
+ GNUNET_break (0);
+ TALER_BANK_credit_history_cancel (hh);
+ curl_easy_cleanup (eh);
+ GNUNET_free (url);
+ return NULL;
+ }
+ hh->job = GNUNET_CURL_job_add2 (ctx,
+ eh,
+ NULL,
+ &handle_history_finished,
+ hh);
+ GNUNET_free (url);
+ return hh;
+}
+
+
+/**
+ * Cancel a history request. This function cannot be
+ * used on a request handle if a response is already
+ * served for it.
+ *
+ * @param hh the history request handle
+ */
+void
+TALER_BANK_credit_history_cancel (struct TALER_BANK_CreditHistoryHandle *hh)
+{
+ if (NULL != hh->job)
+ {
+ GNUNET_CURL_job_cancel (hh->job);
+ hh->job = NULL;
+ }
+ GNUNET_free (hh->request_url);
+ GNUNET_free (hh->bank_base_url);
+ GNUNET_free (hh);
+}
+
+
+/* end of bank_api_credit.c */
diff --git a/src/bank-lib/bank_api_history.c b/src/bank-lib/bank_api_debit.c
index f5013b85..84836243 100644
--- a/src/bank-lib/bank_api_history.c
+++ b/src/bank-lib/bank_api_debit.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2017 GNUnet e.V. & Inria
+ Copyright (C) 2017--2020 Taler Systems SA
TALER is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -32,7 +32,7 @@
/**
* @brief A /history Handle
*/
-struct TALER_BANK_HistoryHandle
+struct TALER_BANK_DebitHistoryHandle
{
/**
@@ -51,14 +51,9 @@ struct TALER_BANK_HistoryHandle
struct GNUNET_CURL_Job *job;
/**
- * HTTP authentication-related headers for the request.
- */
- struct curl_slist *authh;
-
- /**
* Function to call with the result.
*/
- TALER_BANK_HistoryResultCallback hcb;
+ TALER_BANK_DebitResultCallback hcb;
/**
* Closure for @a cb.
@@ -77,37 +72,39 @@ struct TALER_BANK_HistoryHandle
* #GNUNET_SYSERR if there was a protocol violation in @a history
*/
static int
-parse_account_history (struct TALER_BANK_HistoryHandle *hh,
+parse_account_history (struct TALER_BANK_DebitHistoryHandle *hh,
const json_t *history)
{
json_t *history_array;
- char *bank_hostname;
- if (NULL == (history_array = json_object_get (history, "data")))
+ if (NULL == (history_array = json_object_get (history,
+ "data")))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if (! json_is_array (history_array))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
for (unsigned int i = 0; i<json_array_size (history_array); i++)
{
- struct TALER_BANK_TransferDetails td;
- const char *sign;
- uint64_t other_account;
+ struct TALER_BANK_DebitDetails td;
uint64_t row_id;
- enum TALER_BANK_Direction direction;
struct GNUNET_JSON_Specification hist_spec[] = {
- GNUNET_JSON_spec_string ("sign",
- &sign),
TALER_JSON_spec_amount ("amount",
&td.amount),
GNUNET_JSON_spec_absolute_time ("date",
&td.execution_date),
GNUNET_JSON_spec_uint64 ("row_id",
&row_id),
- GNUNET_JSON_spec_string ("wt_subject",
- (const char **) &td.wire_transfer_subject),
- GNUNET_JSON_spec_uint64 ("counterpart",
- &other_account),
+ GNUNET_JSON_spec_fixed_auto ("wtid",
+ &td.wtid),
+ GNUNET_JSON_spec_string ("counterpart",
+ &td.account_url),
+ GNUNET_JSON_spec_string ("exchange_base_url",
+ &td.exchange_base_url),
GNUNET_JSON_spec_end ()
};
json_t *transaction = json_array_get (history_array,
@@ -121,45 +118,12 @@ parse_account_history (struct TALER_BANK_HistoryHandle *hh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
-
- if (0 == strcasecmp (sign,
- "+"))
- direction = TALER_BANK_DIRECTION_CREDIT;
- else if (0 == strcasecmp (sign,
- "-"))
- direction = TALER_BANK_DIRECTION_DEBIT;
- else if (0 == strcasecmp (sign,
- "cancel+"))
- direction = TALER_BANK_DIRECTION_CREDIT | TALER_BANK_DIRECTION_CANCEL;
- else if (0 == strcasecmp (sign,
- "cancel-"))
- direction = TALER_BANK_DIRECTION_DEBIT | TALER_BANK_DIRECTION_CANCEL;
- else
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (hist_spec);
- return GNUNET_SYSERR;
- }
- /* Note, bank_base_url has _always_ the protocol scheme
- * and it proved to be good at this point. */
- bank_hostname = strchr (hh->bank_base_url, ':');
- GNUNET_assert (NULL != bank_hostname);
- bank_hostname += 3;
-
- GNUNET_asprintf (&td.account_url,
- ('/' == bank_hostname[strlen (bank_hostname) - 1])
- ? "payto://x-taler-bank/%s%llu"
- : "payto://x-taler-bank/%s/%llu",
- bank_hostname,
- (unsigned long long) other_account);
hh->hcb (hh->hcb_cls,
MHD_HTTP_OK,
TALER_EC_NONE,
- direction,
row_id,
&td,
transaction);
- GNUNET_free (td.account_url);
GNUNET_JSON_parse_free (hist_spec);
}
return GNUNET_OK;
@@ -170,7 +134,7 @@ parse_account_history (struct TALER_BANK_HistoryHandle *hh,
* Function called when we're done processing the
* HTTP /history request.
*
- * @param cls the `struct TALER_BANK_HistoryHandle`
+ * @param cls the `struct TALER_BANK_DebitHistoryHandle`
* @param response_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error
*/
@@ -179,7 +143,7 @@ handle_history_finished (void *cls,
long response_code,
const void *response)
{
- struct TALER_BANK_HistoryHandle *hh = cls;
+ struct TALER_BANK_DebitHistoryHandle *hh = cls;
enum TALER_ErrorCode ec;
const json_t *j = response;
@@ -243,120 +207,19 @@ handle_history_finished (void *cls,
hh->hcb (hh->hcb_cls,
response_code,
ec,
- TALER_BANK_DIRECTION_NONE,
0LLU,
NULL,
j);
- TALER_BANK_history_cancel (hh);
-}
-
-
-/**
- * Backend of both the /history[-range] requests.
- *
- * @param ctx curl context for the event loop
- * @param bank_base_url base URL of the bank.
- * @param urlargs path + URL arguments.
- * @param auth authentication data to use
- * @param hres_cb the callback to call with the transaction
- * history
- * @param hres_cb_cls closure for the above callback
- * @return NULL if the inputs are invalid (i.e. zero value for
- * @e num_results). In this case, the callback is not
- * called.
- */
-static struct TALER_BANK_HistoryHandle *
-put_history_job (struct GNUNET_CURL_Context *ctx,
- const char *bank_base_url,
- const char *urlargs,
- const struct TALER_BANK_AuthenticationData *auth,
- TALER_BANK_HistoryResultCallback hres_cb,
- void *hres_cb_cls)
-{
- struct TALER_BANK_HistoryHandle *hh;
- CURL *eh;
-
- hh = GNUNET_new (struct TALER_BANK_HistoryHandle);
- hh->hcb = hres_cb;
- hh->hcb_cls = hres_cb_cls;
- hh->bank_base_url = GNUNET_strdup (bank_base_url);
- hh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
- urlargs);
-
- hh->authh = TALER_BANK_make_auth_header_ (auth);
- eh = curl_easy_init ();
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- hh->request_url));
- hh->job = GNUNET_CURL_job_add2 (ctx,
- eh,
- hh->authh,
- &handle_history_finished,
- hh);
- return hh;
+ TALER_BANK_debit_history_cancel (hh);
}
/**
- * Convert fixed value 'direction' into string.
- *
- * @param direction the value to convert.
- * @return string representation of @a direction. NULL on error
- */
-static const char *
-conv_direction (enum TALER_BANK_Direction direction)
-{
- if (TALER_BANK_DIRECTION_NONE == direction)
- {
- /* Should just never happen. */
- GNUNET_break (0);
- return NULL;
- }
- if (TALER_BANK_DIRECTION_BOTH ==
- (TALER_BANK_DIRECTION_BOTH & direction))
- return "both";
- else if (TALER_BANK_DIRECTION_CREDIT ==
- (TALER_BANK_DIRECTION_CREDIT & direction))
- return "credit";
- else if (TALER_BANK_DIRECTION_DEBIT ==
- (TALER_BANK_DIRECTION_BOTH & direction)) /*why use 'both' flag?*/
- return "debit";
- /* Should just never happen. */
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Convert fixed value 'direction' into string representation
- * of the "cancel" argument.
- *
- * @param direction the value to convert.
- * @return string representation of @a direction
- */
-static const char *
-conv_cancel (enum TALER_BANK_Direction direction)
-{
- if (TALER_BANK_DIRECTION_CANCEL ==
- (TALER_BANK_DIRECTION_CANCEL & direction))
- return "show";
- return "omit";
-}
-
-
-/**
- * Request the wire transfer history of a bank account.
+ * Request the debit history of the exchange's bank account.
*
* @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this
- * request)
+ * @param bank_base_url URL of the base INCLUDING account number
* @param auth authentication data to use
- * @param account_number which account number should we query
- * @param direction what kinds of wire transfers should be
- * returned
- * @param ascending if GNUNET_YES, history elements will
- * be returned in chronological order.
* @param start_row from which row on do we want to get results,
* use UINT64_MAX for the latest; exclusive
* @param num_results how many results do we want;
@@ -370,20 +233,18 @@ conv_cancel (enum TALER_BANK_Direction direction)
* @e num_results). In this case, the callback is not
* called.
*/
-struct TALER_BANK_HistoryHandle *
-TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
- const char *bank_base_url,
- const struct TALER_BANK_AuthenticationData *auth,
- uint64_t account_number,
- enum TALER_BANK_Direction direction,
- unsigned int ascending,
- uint64_t start_row,
- int64_t num_results,
- TALER_BANK_HistoryResultCallback hres_cb,
- void *hres_cb_cls)
+struct TALER_BANK_DebitHistoryHandle *
+TALER_BANK_debit_history (struct GNUNET_CURL_Context *ctx,
+ const char *bank_base_url,
+ const struct TALER_BANK_AuthenticationData *auth,
+ uint64_t start_row,
+ int64_t num_results,
+ TALER_BANK_DebitResultCallback hres_cb,
+ void *hres_cb_cls)
{
- struct TALER_BANK_HistoryHandle *hh;
char *url;
+ struct TALER_BANK_DebitHistoryHandle *hh;
+ CURL *eh;
if (0 == num_results)
{
@@ -393,28 +254,40 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
if (UINT64_MAX == start_row)
GNUNET_asprintf (&url,
- "/history?auth=basic&account_number=%llu&delta=%lld&direction=%s&cancelled=%s&ordering=%s",
- (unsigned long long) account_number,
- (long long) num_results,
- conv_direction (direction),
- conv_cancel (direction),
- (GNUNET_YES == ascending) ? "ascending" : "descending");
+ "/history&delta=%lld",
+ (long long) num_results);
else
GNUNET_asprintf (&url,
- "/history?auth=basic&account_number=%llu&delta=%lld&direction=%s&cancelled=%s&ordering=%s&start=%llu",
- (unsigned long long) account_number,
+ "/history&delta=%lld&start=%llu",
(long long) num_results,
- conv_direction (direction),
- conv_cancel (direction),
- (GNUNET_YES == ascending) ? "ascending" : "descending",
start_row);
- hh = put_history_job (ctx,
- bank_base_url,
- url,
- auth,
- hres_cb,
- hres_cb_cls);
+ hh = GNUNET_new (struct TALER_BANK_DebitHistoryHandle);
+ hh->hcb = hres_cb;
+ hh->hcb_cls = hres_cb_cls;
+ hh->bank_base_url = GNUNET_strdup (bank_base_url);
+ hh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
+ url);
+ eh = curl_easy_init ();
+ if ( (GNUNET_OK !=
+ TALER_BANK_setup_auth_ (eh,
+ auth)) ||
+ (CURLE_OK !=
+ curl_easy_setopt (eh,
+ CURLOPT_URL,
+ hh->request_url)) )
+ {
+ GNUNET_break (0);
+ TALER_BANK_debit_history_cancel (hh);
+ curl_easy_cleanup (eh);
+ GNUNET_free (url);
+ return NULL;
+ }
+ hh->job = GNUNET_CURL_job_add2 (ctx,
+ eh,
+ NULL,
+ &handle_history_finished,
+ hh);
GNUNET_free (url);
return hh;
}
@@ -428,18 +301,17 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
* @param hh the history request handle
*/
void
-TALER_BANK_history_cancel (struct TALER_BANK_HistoryHandle *hh)
+TALER_BANK_debit_history_cancel (struct TALER_BANK_DebitHistoryHandle *hh)
{
if (NULL != hh->job)
{
GNUNET_CURL_job_cancel (hh->job);
hh->job = NULL;
}
- curl_slist_free_all (hh->authh);
GNUNET_free (hh->request_url);
GNUNET_free (hh->bank_base_url);
GNUNET_free (hh);
}
-/* end of bank_api_history.c */
+/* end of bank_api_debit.c */
diff --git a/src/bank-lib/bank_api_parse.c b/src/bank-lib/bank_api_parse.c
index 582e2a7d..86288802 100644
--- a/src/bank-lib/bank_api_parse.c
+++ b/src/bank-lib/bank_api_parse.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
+ Copyright (C) 2018-2020 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
@@ -24,6 +24,58 @@
/**
+ * Convenience method for parsing configuration section with bank account data.
+ *
+ * @param cfg configuration to parse
+ * @param section the section with the configuration data
+ * @param acc[out] set to the account details
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_BANK_account_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *section,
+ struct TALER_Account *acc)
+{
+ char *account_url;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ section,
+ "URL",
+ &account_url))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "URL");
+ return GNUNET_SYSERR;
+ }
+ if (TALER_EC_NONE !=
+ TALER_WIRE_payto_to_account (account_url,
+ acc))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "URL",
+ "Malformed payto:// URL for x-taler-bank method");
+ GNUNET_free (account_url);
+ return GNUNET_SYSERR;
+ }
+ if (TALER_PAC_X_TALER_BANK != acc->type)
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "URL",
+ "Malformed payto:// URL for x-taler-bank method");
+ GNUNET_free (account_url);
+ TALER_WIRE_account_free (acc);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_free (account_url);
+ return GNUNET_OK;
+}
+
+
+/**
* Parse configuration section with bank authentication data.
*
* @param cfg configuration to parse
diff --git a/src/bank-lib/bank_api_reject.c b/src/bank-lib/bank_api_reject.c
deleted file mode 100644
index 3f181bc3..00000000
--- a/src/bank-lib/bank_api_reject.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2015, 2016, 2017 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_reject.c
- * @brief Implementation of the /reject request 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"
-
-
-/**
- * @brief A /reject Handle
- */
-struct TALER_BANK_RejectHandle
-{
-
- /**
- * The url for this request.
- */
- char *request_url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * HTTP authentication-related headers for the request.
- */
- struct curl_slist *authh;
-
- /**
- * Function to call with the result.
- */
- TALER_BANK_RejectResultCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
-};
-
-
-/**
- * Function called when we're done processing the
- * HTTP /reject request.
- *
- * @param cls the `struct TALER_BANK_RejectHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_reject_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_BANK_RejectHandle *rh = cls;
- enum TALER_ErrorCode ec;
- const json_t *j = response;
-
- rh->job = NULL;
- switch (response_code)
- {
- case 0:
- ec = TALER_EC_INVALID_RESPONSE;
- break;
- case MHD_HTTP_OK:
- GNUNET_break_op (0);
- response_code = 0;
- ec = TALER_EC_INVALID_RESPONSE;
- break;
- case MHD_HTTP_NO_CONTENT:
- ec = TALER_EC_NONE;
- 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 */
- ec = TALER_BANK_parse_ec_ (j);
- break;
- case MHD_HTTP_FORBIDDEN:
- /* Access denied */
- ec = TALER_BANK_parse_ec_ (j);
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, bank says one of the signatures is
- invalid; as we checked them, this should never happen, we
- should pass the JSON reply to the application */
- ec = TALER_BANK_parse_ec_ (j);
- break;
- case MHD_HTTP_NOT_FOUND:
- /* Nothing really to verify, this should never
- happen, we should pass the JSON reply to the application */
- ec = TALER_BANK_parse_ec_ (j);
- break;
- case MHD_HTTP_INTERNAL_SERVER_ERROR:
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
- ec = TALER_BANK_parse_ec_ (j);
- break;
- default:
- /* unexpected response code */
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
- ec = TALER_BANK_parse_ec_ (j);
- response_code = 0;
- break;
- }
- rh->cb (rh->cb_cls,
- response_code,
- ec);
- TALER_BANK_reject_cancel (rh);
-}
-
-
-/**
- * Request rejection of a wire transfer, marking it as cancelled and voiding
- * its effects.
- *
- * @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this request)
- * @param auth authentication data to use
- * @param account_number which account number should we query
- * @param rowid transfer to reject
- * @param rcb the callback to call with the operation result
- * @param rcb_cls closure for @a rcb
- * @return NULL
- * if the inputs are invalid.
- * In this case, the callback is not called.
- */
-struct TALER_BANK_RejectHandle *
-TALER_BANK_reject (struct GNUNET_CURL_Context *ctx,
- const char *bank_base_url,
- const struct TALER_BANK_AuthenticationData *auth,
- uint64_t account_number,
- uint64_t rowid,
- TALER_BANK_RejectResultCallback rcb,
- void *rcb_cls)
-{
- struct TALER_BANK_RejectHandle *rh;
- json_t *reject_obj;
- CURL *eh;
-
- reject_obj = json_pack ("{s:{s:s}, s:I, s:I}",
- "auth", "type", "basic",
- "row_id", (json_int_t) rowid,
- "account_number", (json_int_t) account_number);
- if (NULL == reject_obj)
- {
- GNUNET_break (0);
- return NULL;
- }
- rh = GNUNET_new (struct TALER_BANK_RejectHandle);
- rh->cb = rcb;
- rh->cb_cls = rcb_cls;
- rh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
- "/reject");
- rh->authh = TALER_BANK_make_auth_header_ (auth);
- /* Append content type header here, can't do it in GNUNET_CURL_job_add
- as that would override the CURLOPT_HTTPHEADER instead of appending. */
- {
- struct curl_slist *ext;
-
- ext = curl_slist_append (rh->authh,
- "Content-Type: application/json");
- if (NULL == ext)
- GNUNET_break (0);
- else
- rh->authh = ext;
- }
- eh = curl_easy_init ();
- GNUNET_assert (NULL != (rh->json_enc =
- json_dumps (reject_obj,
- JSON_COMPACT)));
- json_decref (reject_obj);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- rh->request_url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDS,
- rh->json_enc));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDSIZE,
- strlen (rh->json_enc)));
- rh->job = GNUNET_CURL_job_add2 (ctx,
- eh,
- rh->authh,
- &handle_reject_finished,
- rh);
- return rh;
-}
-
-
-/**
- * Cancel an reject request. This function cannot be used on a request
- * handle if the response was is already served for it.
- *
- * @param rh the reject request handle
- */
-void
-TALER_BANK_reject_cancel (struct TALER_BANK_RejectHandle *rh)
-{
- if (NULL != rh->job)
- {
- GNUNET_CURL_job_cancel (rh->job);
- rh->job = NULL;
- }
- curl_slist_free_all (rh->authh);
- GNUNET_free (rh->request_url);
- GNUNET_free (rh->json_enc);
- GNUNET_free (rh);
-}
-
-
-/* end of bank_api_reject.c */
diff --git a/src/bank-lib/bank_api_transaction.c b/src/bank-lib/bank_api_transaction.c
new file mode 100644
index 00000000..17732848
--- /dev/null
+++ b/src/bank-lib/bank_api_transaction.c
@@ -0,0 +1,368 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2015--2020 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_transaction.c
+ * @brief Implementation of the /transaction/ 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"
+#include "taler_bank_service.h"
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Data structure serialized in the prepare stage.
+ */
+struct WirePackP
+{
+ /**
+ * Random unique identifier for the request.
+ */
+ struct GNUNET_HashCode request_uid;
+
+ /**
+ * Amount to be transferred.
+ */
+ struct TALER_AmountNBO amount;
+
+ /**
+ * Wire transfer identifier to use.
+ */
+ struct TALER_WireTransferIdentifierRawP wtid;
+
+ /**
+ * Length of the payto:// URL of the target account,
+ * including 0-terminator, in network byte order.
+ */
+ uint32_t account_len GNUNET_PACKED;
+
+ /**
+ * Length of the exchange's base URL,
+ * including 0-terminator, in network byte order.
+ */
+ uint32_t exchange_url_len GNUNET_PACKED;
+
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+/**
+ * Prepare for exeuction of a wire transfer.
+ *
+ * @param destination_account_url payto:// URL identifying where to send the money
+ * @param amount amount to transfer, already rounded
+ * @param exchange_base_url base URL of this exchange (included in subject
+ * to facilitate use of tracking API by merchant backend)
+ * @param wtid wire transfer identifier to use
+ * @param buf[out] set to transaction data to persist, NULL on error
+ * @param buf_size[out] set to number of bytes in @a buf, 0 on error
+ */
+void
+TALER_BANK_prepare_wire_transfer (const char *destination_account_url,
+ const struct TALER_Amount *amount,
+ const char *exchange_base_url,
+ const struct
+ TALER_WireTransferIdentifierRawP *wtid,
+ void **buf,
+ size_t *buf_size)
+{
+ struct WirePackP *wp;
+ size_t d_len = strlen (destination_account_url) + 1;
+ size_t u_len = strlen (exchange_base_url) + 1;
+ char *end;
+
+ *buf_size = sizeof (*wp) + d_len + u_len;
+ wp = GNUNET_malloc (*buf_size);
+ GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
+ &wp->request_uid);
+ TALER_amount_hton (&wp->amount,
+ amount);
+ wp->wtid = *wtid;
+ wp->account_len = htonl ((uint32_t) d_len);
+ wp->exchange_url_len = htonl ((uint32_t) u_len);
+ end = (char *) &wp[1];
+ memcpy (end,
+ destination_account_url,
+ d_len);
+ memcpy (end + d_len,
+ exchange_base_url,
+ u_len);
+ *buf = (char *) wp;
+}
+
+
+/**
+ * @brief An transaction Handle
+ */
+struct TALER_BANK_WireExecuteHandle
+{
+
+ /**
+ * The url for this request.
+ */
+ char *request_url;
+
+ /**
+ * POST context.
+ */
+ struct TEAH_PostContext post_ctx;
+
+ /**
+ * Handle for the request.
+ */
+ struct GNUNET_CURL_Job *job;
+
+ /**
+ * Function to call with the result.
+ */
+ TALER_BANK_ConfirmationCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+};
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP /transaction request.
+ *
+ * @param cls the `struct TALER_BANK_WireExecuteHandle`
+ * @param response_code HTTP response code, 0 on error
+ * @param response parsed JSON result, NULL on error
+ */
+static void
+handle_transaction_finished (void *cls,
+ long response_code,
+ const void *response)
+{
+ struct TALER_BANK_WireExecuteHandle *weh = cls;
+ uint64_t row_id = UINT64_MAX;
+ struct GNUNET_TIME_Absolute timestamp;
+ enum TALER_ErrorCode ec;
+ const json_t *j = response;
+
+ weh->job = NULL;
+ timestamp = GNUNET_TIME_UNIT_FOREVER_ABS;
+ switch (response_code)
+ {
+ case 0:
+ ec = TALER_EC_INVALID_RESPONSE;
+ break;
+ case MHD_HTTP_OK:
+ {
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_uint64 ("row_id",
+ &row_id),
+ GNUNET_JSON_spec_absolute_time ("timestamp",
+ &timestamp),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (j,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ response_code = 0;
+ ec = TALER_EC_INVALID_RESPONSE;
+ break;
+ }
+ ec = TALER_EC_NONE;
+ }
+ 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 */
+ ec = TALER_BANK_parse_ec_ (j);
+ break;
+ case MHD_HTTP_FORBIDDEN:
+ /* Access denied */
+ ec = TALER_BANK_parse_ec_ (j);
+ break;
+ case MHD_HTTP_UNAUTHORIZED:
+ /* Nothing really to verify, bank says one of the signatures is
+ invalid; as we checked them, this should never happen, we
+ should pass the JSON reply to the application */
+ ec = TALER_BANK_parse_ec_ (j);
+ break;
+ case MHD_HTTP_NOT_FOUND:
+ /* Nothing really to verify, this should never
+ happen, we should pass the JSON reply to the application */
+ ec = TALER_BANK_parse_ec_ (j);
+ break;
+ case MHD_HTTP_NOT_ACCEPTABLE:
+ /* Nothing really to verify, this should never
+ happen, we should pass the JSON reply to the application */
+ ec = TALER_BANK_parse_ec_ (j);
+ break;
+ case MHD_HTTP_INTERNAL_SERVER_ERROR:
+ /* Server had an internal issue; we should retry, but this API
+ leaves this to the application */
+ ec = TALER_BANK_parse_ec_ (j);
+ break;
+ default:
+ /* unexpected response code */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u\n",
+ (unsigned int) response_code);
+ GNUNET_break (0);
+ ec = TALER_BANK_parse_ec_ (j);
+ response_code = 0;
+ break;
+ }
+ weh->cb (weh->cb_cls,
+ response_code,
+ ec,
+ row_id,
+ timestamp);
+ TALER_BANK_execute_wire_transfer_cancel (weh);
+}
+
+
+/**
+ * Execute a wire transfer.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param buf buffer with the prepared execution details
+ * @param buf_size number of bytes in @a buf
+ * @param cc function to call upon success
+ * @param cc_cls closure for @a cc
+ * @return NULL on error
+ */
+struct TALER_BANK_WireExecuteHandle *
+TALER_BANK_execute_wire_transfer (struct GNUNET_CURL_Context *ctx,
+ const char *bank_base_url,
+ const struct
+ TALER_BANK_AuthenticationData *auth,
+ const void *buf,
+ size_t buf_size,
+ TALER_BANK_ConfirmationCallback cc,
+ void *cc_cls)
+{
+ struct TALER_BANK_WireExecuteHandle *weh;
+ json_t *transaction_obj;
+ CURL *eh;
+ const struct WirePackP *wp = buf;
+ uint32_t d_len;
+ uint32_t u_len;
+ const char *destination_account_url;
+ const char *exchange_base_url;
+ struct TALER_Amount amount;
+
+ if (sizeof (*wp) > buf_size)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ d_len = ntohl (wp->account_len);
+ u_len = ntohl (wp->exchange_url_len);
+ if (sizeof (*wp) + d_len + u_len != buf_size)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ destination_account_url = (const char *) &wp[1];
+ exchange_base_url = destination_account_url + d_len;
+ if (NULL == bank_base_url)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ TALER_amount_ntoh (&amount,
+ &wp->amount);
+ transaction_obj = json_pack ("{s:o, s:o, s:s, s:o, s:o, s:s}",
+ "request_uid", GNUNET_JSON_from_data_auto (
+ &wp->request_uid),
+ "amount", TALER_JSON_from_amount (&amount),
+ "exchange_url", exchange_base_url,
+ "wtid", GNUNET_JSON_from_data_auto (&wp->wtid),
+ "credit_account", destination_account_url);
+ if (NULL == transaction_obj)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ weh = GNUNET_new (struct TALER_BANK_WireExecuteHandle);
+ weh->cb = cc;
+ weh->cb_cls = cc_cls;
+ weh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
+ "/transaction");
+ weh->post_ctx.headers = curl_slist_append
+ (weh->post_ctx.headers,
+ "Content-Type: application/json");
+
+ eh = curl_easy_init ();
+ if ( (GNUNET_OK !=
+ TALER_BANK_setup_auth_ (eh,
+ auth)) ||
+ (CURLE_OK !=
+ curl_easy_setopt (eh,
+ CURLOPT_URL,
+ weh->request_url)) ||
+ (GNUNET_OK !=
+ TALER_curl_easy_post (&weh->post_ctx,
+ eh,
+ transaction_obj)) )
+ {
+ GNUNET_break (0);
+ TALER_BANK_execute_wire_transfer_cancel (weh);
+ curl_easy_cleanup (eh);
+ json_decref (transaction_obj);
+ return NULL;
+ }
+ json_decref (transaction_obj);
+
+ weh->job = GNUNET_CURL_job_add2 (ctx,
+ eh,
+ weh->post_ctx.headers,
+ &handle_transaction_finished,
+ weh);
+ return weh;
+}
+
+
+/**
+ * Cancel a wire transfer. This function cannot be used on a request handle
+ * if a response is already served for it.
+ *
+ * @param weh the wire transfer request handle
+ */
+void
+TALER_BANK_execute_wire_transfer_cancel (struct
+ TALER_BANK_WireExecuteHandle *weh)
+{
+ if (NULL != weh->job)
+ {
+ GNUNET_CURL_job_cancel (weh->job);
+ weh->job = NULL;
+ }
+ TALER_curl_easy_post_finished (&weh->post_ctx);
+ GNUNET_free (weh->request_url);
+ GNUNET_free (weh);
+}
+
+
+/* end of bank_api_transaction.c */
diff --git a/src/bank-lib/fakebank.c b/src/bank-lib/fakebank.c
index d8ea392b..1706ca8f 100644
--- a/src/bank-lib/fakebank.c
+++ b/src/bank-lib/fakebank.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2016, 2017, 2018 Inria and GNUnet e.V.
+ (C) 2016-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -25,7 +25,7 @@
#include "platform.h"
#include "taler_fakebank_lib.h"
#include "taler_bank_service.h"
-#include "fakebank.h"
+#include "taler_mhd_lib.h"
/**
* Maximum POST request size (for /admin/add/incoming)
@@ -34,6 +34,65 @@
/**
+ * Details about a transcation we (as the simulated bank) received.
+ */
+struct Transaction
+{
+ /**
+ * We store transactions in a DLL.
+ */
+ struct Transaction *next;
+
+ /**
+ * We store transactions in a DLL.
+ */
+ struct Transaction *prev;
+
+ /**
+ * Amount to be transferred.
+ */
+ struct TALER_Amount amount;
+
+ /**
+ * Account to debit.
+ */
+ char *debit_account;
+
+ /**
+ * Account to credit.
+ */
+ char *credit_account;
+
+ /**
+ * Subject of the transfer.
+ */
+ char *subject;
+
+ /**
+ * Base URL of the exchange.
+ */
+ char *exchange_base_url;
+
+ /**
+ * When did the transaction happen?
+ */
+ struct GNUNET_TIME_Absolute date;
+
+ /**
+ * Number of this transaction.
+ */
+ uint64_t row_id;
+
+ /**
+ * Has this transaction been subjected to #TALER_FAKEBANK_check()
+ * and should thus no longer be counted in
+ * #TALER_FAKEBANK_check_empty()?
+ */
+ int checked;
+};
+
+
+/**
* Handle for the fake bank.
*/
struct TALER_FAKEBANK_Handle
@@ -63,6 +122,11 @@ struct TALER_FAKEBANK_Handle
*/
uint64_t serial_counter;
+ /**
+ * Our port number.
+ */
+ uint16_t port;
+
#if EPOLL_SUPPORT
/**
* Boxed @e mhd_fd.
@@ -95,8 +159,8 @@ struct TALER_FAKEBANK_Handle
int
TALER_FAKEBANK_check (struct TALER_FAKEBANK_Handle *h,
const struct TALER_Amount *want_amount,
- uint64_t want_debit,
- uint64_t want_credit,
+ const char *want_debit,
+ const char *want_credit,
const char *exchange_base_url,
char **subject)
{
@@ -151,8 +215,8 @@ TALER_FAKEBANK_check (struct TALER_FAKEBANK_Handle *h,
*/
uint64_t
TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
- uint64_t debit_account,
- uint64_t credit_account,
+ const char *debit_account,
+ const char *credit_account,
const struct TALER_Amount *amount,
const char *subject,
const char *exchange_base_url)
@@ -160,15 +224,15 @@ TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
struct Transaction *t;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Making transfer from %llu to %llu over %s and subject %s; for exchange: %s\n",
- (unsigned long long) debit_account,
- (unsigned long long) credit_account,
+ "Making transfer from %s to %s over %s and subject %s; for exchange: %s\n",
+ debit_account,
+ credit_account,
TALER_amount2s (amount),
subject,
exchange_base_url);
t = GNUNET_new (struct Transaction);
- t->debit_account = debit_account;
- t->credit_account = credit_account;
+ t->debit_account = GNUNET_strdup (debit_account);
+ t->credit_account = GNUNET_strdup (credit_account);
t->amount = *amount;
t->exchange_base_url = GNUNET_strdup (exchange_base_url);
t->row_id = ++h->serial_counter;
@@ -183,31 +247,6 @@ TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
/**
- * Reject incoming wire transfer to account @a credit_account
- * as identified by @a rowid.
- *
- * @param h fake bank handle
- * @param rowid identifies transfer to reject
- * @param credit_account account number of owner of credited account
- * @return #GNUNET_YES on success, #GNUNET_NO if the wire transfer was not found
- */
-int
-TALER_FAKEBANK_reject_transfer (struct TALER_FAKEBANK_Handle *h,
- uint64_t rowid,
- uint64_t credit_account)
-{
- for (struct Transaction *t = h->transactions_head; NULL != t; t = t->next)
- if ( (t->row_id == rowid) &&
- (t->credit_account == credit_account) )
- {
- t->rejected = GNUNET_YES;
- return GNUNET_YES;
- }
- return GNUNET_NO;
-}
-
-
-/**
* Check that no wire transfers were ordered (or at least none
* that have not been taken care of via #TALER_FAKEBANK_check()).
* If any transactions are onrecord, return #GNUNET_SYSERR.
@@ -223,8 +262,7 @@ TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle *h)
t = h->transactions_head;
while (NULL != t)
{
- if ( (GNUNET_YES != t->checked) &&
- (GNUNET_YES != t->rejected) )
+ if (GNUNET_YES != t->checked)
break;
t = t->next;
}
@@ -234,16 +272,15 @@ TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle *h)
"Expected empty transaction set, but I have:\n");
while (NULL != t)
{
- if ( (GNUNET_YES != t->checked) &&
- (GNUNET_YES != t->rejected) )
+ if (GNUNET_YES != t->checked)
{
char *s;
s = TALER_amount_to_string (&t->amount);
fprintf (stderr,
- "%llu -> %llu (%s) from %s\n",
- (unsigned long long) t->debit_account,
- (unsigned long long) t->credit_account,
+ "%s -> %s (%s) from %s\n",
+ t->debit_account,
+ t->credit_account,
s,
t->exchange_base_url);
GNUNET_free (s);
@@ -270,6 +307,8 @@ TALER_FAKEBANK_stop (struct TALER_FAKEBANK_Handle *h)
h->transactions_tail,
t);
GNUNET_free (t->subject);
+ GNUNET_free (t->debit_account);
+ GNUNET_free (t->credit_account);
GNUNET_free (t->exchange_base_url);
GNUNET_free (t);
}
@@ -291,62 +330,6 @@ TALER_FAKEBANK_stop (struct TALER_FAKEBANK_Handle *h)
/**
- * Create and queue a bank error message with the HTTP response
- * code @a response_code on connection @a connection.
- *
- * @param connection where to queue the reply
- * @param response_code http status code to use
- * @param ec taler error code to use
- * @param message human readable error message
- * @return MHD status code
- */
-static int
-create_bank_error (struct MHD_Connection *connection,
- unsigned int response_code,
- enum TALER_ErrorCode ec,
- const char *message)
-{
- json_t *json;
- struct MHD_Response *resp;
- void *json_str;
- size_t json_len;
- int ret;
-
- json = json_pack ("{s:s, s:I}",
- "error",
- message,
- "ec",
- (json_int_t) ec);
- json_str = json_dumps (json,
- JSON_INDENT (2));
- json_decref (json);
- if (NULL == json_str)
- {
- GNUNET_break (0);
- return MHD_NO;
- }
- json_len = strlen (json_str);
- resp = MHD_create_response_from_buffer (json_len,
- json_str,
- MHD_RESPMEM_MUST_FREE);
- if (NULL == resp)
- {
- GNUNET_break (0);
- free (json_str);
- return MHD_NO;
- }
- (void) MHD_add_response_header (resp,
- MHD_HTTP_HEADER_CONTENT_TYPE,
- "application/json");
- ret = MHD_queue_response (connection,
- response_code,
- resp);
- MHD_destroy_response (resp);
- return ret;
-}
-
-
-/**
* Function called whenever MHD is done with a request. If the
* request was a POST, we may have stored a `struct Buffer *` in the
* @a con_cls that might still need to be cleaned up. Call the
@@ -394,8 +377,6 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
{
enum GNUNET_JSON_PostResult pr;
json_t *json;
- struct MHD_Response *resp;
- int ret;
uint64_t row_id;
pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX,
@@ -422,15 +403,14 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
}
{
const char *subject;
- uint64_t debit_account;
- uint64_t credit_account;
+ const char *debit_account;
+ const char *credit_account;
const char *base_url;
struct TALER_Amount amount;
- char *amount_s;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("subject", &subject),
- GNUNET_JSON_spec_uint64 ("debit_account", &debit_account),
- GNUNET_JSON_spec_uint64 ("credit_account", &credit_account),
+ GNUNET_JSON_spec_string ("debit_account", &debit_account),
+ GNUNET_JSON_spec_string ("credit_account", &credit_account),
TALER_JSON_spec_amount ("amount", &amount),
GNUNET_JSON_spec_string ("exchange_url", &base_url),
GNUNET_JSON_spec_end ()
@@ -450,80 +430,49 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
&amount,
subject,
base_url);
- amount_s = TALER_amount_to_string (&amount);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Receiving incoming wire transfer: %llu->%llu, subject: %s, amount: %s, from %s\n",
- (unsigned long long) debit_account,
- (unsigned long long) credit_account,
+ "Receiving incoming wire transfer: %s->%s, subject: %s, amount: %s, from %s\n",
+ debit_account,
+ credit_account,
subject,
- amount_s,
+ TALER_amount2s (&amount),
base_url);
- GNUNET_free (amount_s);
}
json_decref (json);
/* Finally build response object */
- {
- void *json_str;
- size_t json_len;
-
- json = json_pack ("{s:I, s:o}",
- "row_id",
- (json_int_t) row_id,
- "timestamp", GNUNET_JSON_from_time_abs (GNUNET_TIME_UNIT_ZERO_ABS)); /*dummy tmp */
-
- json_str = json_dumps (json,
- JSON_INDENT (2));
- json_decref (json);
- if (NULL == json_str)
- {
- GNUNET_break (0);
- return MHD_NO;
- }
- json_len = strlen (json_str);
- resp = MHD_create_response_from_buffer (json_len,
- json_str,
- MHD_RESPMEM_MUST_FREE);
- if (NULL == resp)
- {
- GNUNET_break (0);
- free (json_str);
- return MHD_NO;
- }
- (void) MHD_add_response_header (resp,
- MHD_HTTP_HEADER_CONTENT_TYPE,
- "application/json");
- }
- ret = MHD_queue_response (connection,
- MHD_HTTP_OK,
- resp);
- MHD_destroy_response (resp);
- return ret;
+ return TALER_MHD_reply_json_pack (connection,
+ MHD_HTTP_OK,
+ "{s:I, s:o}",
+ "row_id",
+ (json_int_t) row_id,
+ "timestamp", GNUNET_JSON_from_time_abs (
+ GNUNET_TIME_UNIT_ZERO_ABS)); /*dummy tmp */
}
/**
- * Handle incoming HTTP request for /reject.
+ * Handle incoming HTTP request for /transaction.
*
* @param h the fakebank handle
* @param connection the connection
+ * @param account account making the transaction
* @param upload_data request data
* @param upload_data_size size of @a upload_data in bytes
* @param con_cls closure for request (a `struct Buffer *`)
* @return MHD result code
*/
static int
-handle_reject (struct TALER_FAKEBANK_Handle *h,
- struct MHD_Connection *connection,
- const char *upload_data,
- size_t *upload_data_size,
- void **con_cls)
+handle_transaction (struct TALER_FAKEBANK_Handle *h,
+ struct MHD_Connection *connection,
+ const char *account,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **con_cls)
{
enum GNUNET_JSON_PostResult pr;
json_t *json;
- struct MHD_Response *resp;
- int ret;
- int found;
+ uint64_t row_id;
pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX,
connection,
@@ -548,13 +497,25 @@ handle_reject (struct TALER_FAKEBANK_Handle *h,
break;
}
{
- uint64_t row_id;
- uint64_t credit_account;
+ struct GNUNET_HashCode uuid;
+ struct TALER_WireTransferIdentifierRawP wtid;
+ const char *credit_account;
+ const char *base_url;
+ struct TALER_Amount amount;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_uint64 ("row_id", &row_id),
- GNUNET_JSON_spec_uint64 ("account_number", &credit_account),
+ GNUNET_JSON_spec_fixed_auto ("request_uid",
+ &uuid),
+ TALER_JSON_spec_amount ("amount",
+ &amount),
+ GNUNET_JSON_spec_string ("exchange_base_url",
+ &base_url),
+ GNUNET_JSON_spec_fixed_auto ("wtid",
+ &wtid),
+ GNUNET_JSON_spec_string ("credit_account",
+ &credit_account),
GNUNET_JSON_spec_end ()
};
+
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
spec,
@@ -564,31 +525,38 @@ handle_reject (struct TALER_FAKEBANK_Handle *h,
json_decref (json);
return MHD_NO;
}
- found = TALER_FAKEBANK_reject_transfer (h,
- row_id,
- credit_account);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Rejected wire transfer #%llu (to %llu)\n",
- (unsigned long long) row_id,
- (unsigned long long) credit_account);
+ {
+ char *subject;
+
+ subject = GNUNET_STRINGS_data_to_string_alloc (&wtid,
+ sizeof (wtid));
+ // FIXME: use uuid here!!!
+ row_id = TALER_FAKEBANK_make_transfer (h,
+ account,
+ credit_account,
+ &amount,
+ subject,
+ base_url);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Receiving incoming wire transfer: %s->%s, subject: %s, amount: %s, from %s\n",
+ account,
+ credit_account,
+ subject,
+ TALER_amount2s (&amount),
+ base_url);
+ GNUNET_free (subject);
+ }
}
json_decref (json);
- if (GNUNET_OK != found)
- return create_bank_error
- (connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_BANK_TRANSACTION_NOT_FOUND,
- "transaction unknown");
- /* finally build regular response */
- resp = MHD_create_response_from_buffer (0,
- NULL,
- MHD_RESPMEM_PERSISTENT);
- ret = MHD_queue_response (connection,
- MHD_HTTP_NO_CONTENT,
- resp);
- MHD_destroy_response (resp);
- return ret;
+ /* Finally build response object */
+ return TALER_MHD_reply_json_pack (connection,
+ MHD_HTTP_OK,
+ "{s:I, s:o}",
+ "row_id",
+ (json_int_t) row_id,
+ "timestamp", GNUNET_JSON_from_time_abs (
+ GNUNET_TIME_UNIT_ZERO_ABS)); /*dummy tmp */
}
@@ -626,75 +594,245 @@ handle_home_page (struct TALER_FAKEBANK_Handle *h,
/**
- * Handle incoming HTTP request for /history
+ * This is the "base" structure for both the /history and the
+ * /history-range API calls.
+ */
+struct HistoryArgs
+{
+
+ /**
+ * Bank account number of the requesting client.
+ */
+ uint64_t account_number;
+
+ /**
+ * Index of the starting transaction.
+ */
+ uint64_t start_idx;
+
+ /**
+ * Requested number of results and order
+ * (positive: ascending, negative: descending)
+ */
+ int64_t delta;
+
+ /**
+ * Timeout for long polling.
+ */
+ struct GNUNET_TIME_Relative lp_timeout;
+
+ /**
+ * #GNUNET_YES if starting point was given.
+ */
+ int have_start;
+
+};
+
+
+/**
+ * Parse URL history arguments, of _both_ APIs:
+ * /history/incoming and /history/outgoing.
+ *
+ * @param connection MHD connection.
+ * @param function_name name of the caller.
+ * @param ha[out] will contain the parsed values.
+ * @return GNUNET_OK only if the parsing succeedes.
+ */
+static int
+parse_history_common_args (struct MHD_Connection *connection,
+ struct HistoryArgs *ha)
+{
+ const char *start;
+ const char *delta;
+ const char *long_poll_ms;
+ unsigned long long lp_timeout;
+ unsigned long long sval;
+ long long d;
+
+ start = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "start");
+ ha->have_start = (NULL != start);
+ delta = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "delta");
+ long_poll_ms = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "long_poll_ms");
+ lp_timeout = 0;
+ if ( (NULL == delta) ||
+ (1 != sscanf (delta,
+ "%lld",
+ &d)) ||
+ ( (NULL != long_poll_ms) &&
+ (1 != sscanf (long_poll_ms,
+ "%llu",
+ &lp_timeout)) ) ||
+ ( (NULL != start) &&
+ (1 != sscanf (start,
+ "%llu",
+ &sval)) ) )
+ {
+ /* Fail if one of the above failed. */
+ /* Invalid request, given that this is fakebank we impolitely
+ * just kill the connection instead of returning a nice error.
+ */
+ GNUNET_break (0);
+ return GNUNET_NO;
+ }
+ if (NULL == start)
+ ha->start_idx = (d > 0) ? 0 : UINT64_MAX;
+ else
+ ha->start_idx = (uint64_t) sval;
+ ha->delta = (int64_t) d;
+ ha->lp_timeout
+ = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+ lp_timeout);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Handle incoming HTTP request for /history/incoming
*
* @param h the fakebank handle
* @param connection the connection
- * @param con_cls place to store state, not used
+ * @param account which account the request is about
* @return MHD result code
*/
static int
-handle_history (struct TALER_FAKEBANK_Handle *h,
- struct MHD_Connection *connection,
- void **con_cls)
+handle_credit_history (struct TALER_FAKEBANK_Handle *h,
+ struct MHD_Connection *connection,
+ const char *account)
{
struct HistoryArgs ha;
- struct HistoryRangeIds hri;
- const char *start;
- const char *delta;
struct Transaction *pos;
+ json_t *history;
- (void) con_cls;
if (GNUNET_OK !=
- TFH_parse_history_common_args (connection,
- &ha))
+ parse_history_common_args (connection,
+ &ha))
{
GNUNET_break (0);
return MHD_NO;
}
- start = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "start");
- delta = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "delta");
- if ( ((NULL != start) && (1 != sscanf (start,
- "%llu",
- &hri.start))) ||
- (NULL == delta) || (1 != sscanf (delta,
- "%lld",
- &hri.count)) )
+ if (! ha.have_start)
+ {
+ pos = (0 > ha.delta)
+ ? h->transactions_tail
+ : h->transactions_head;
+ }
+ else if (NULL != h->transactions_head)
+ {
+ for (pos = h->transactions_head;
+ NULL != pos;
+ pos = pos->next)
+ if (pos->row_id == ha.start_idx)
+ break;
+ if (NULL == pos)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid start specified, transaction %llu not known!\n",
+ (unsigned long long) ha.start_idx);
+ return MHD_NO;
+ }
+ /* range is exclusive, skip the matching entry */
+ if (ha.delta > 0)
+ pos = pos->next;
+ if (ha.delta < 0)
+ pos = pos->prev;
+ }
+ else
+ {
+ /* list is empty */
+ pos = NULL;
+ }
+ history = json_array ();
+ while ( (0 != ha.delta) &&
+ (NULL != pos) )
+ {
+ if (0 == strcasecmp (pos->credit_account,
+ account))
+ {
+ json_t *trans;
+
+ trans = json_pack
+ ("{s:I, s:o, s:o, s:s, s:s, s:s}",
+ "row_id", (json_int_t) pos->row_id,
+ "date", GNUNET_JSON_from_time_abs (pos->date),
+ "amount", TALER_JSON_from_amount (&pos->amount),
+ "credit_account", account,
+ "debit_account", pos->debit_account,
+ "wtid", pos->subject /* we "know" it is OK */);
+ GNUNET_assert (0 ==
+ json_array_append_new (history,
+ trans));
+ if (ha.delta > 0)
+ ha.delta--;
+ else
+ ha.delta++;
+ }
+ if (ha.delta > 0)
+ pos = pos->prev;
+ else
+ pos = pos->next;
+ }
+ return TALER_MHD_reply_json (connection,
+ history,
+ MHD_HTTP_OK);
+}
+
+
+/**
+ * Handle incoming HTTP request for /history/incoming
+ *
+ * @param h the fakebank handle
+ * @param connection the connection
+ * @param account which account the request is about
+ * @return MHD result code
+ */
+static int
+handle_debit_history (struct TALER_FAKEBANK_Handle *h,
+ struct MHD_Connection *connection,
+ const char *account)
+{
+ struct HistoryArgs ha;
+ struct Transaction *pos;
+ json_t *history;
+
+ if (GNUNET_OK !=
+ parse_history_common_args (connection,
+ &ha))
{
GNUNET_break (0);
return MHD_NO;
}
- ha.range = &hri;
- if (NULL == start)
+ if (! ha.have_start)
{
- pos = 0 > hri.count ?
- h->transactions_tail : h->transactions_head;
+ pos = (0 > ha.delta)
+ ? h->transactions_tail
+ : h->transactions_head;
}
else if (NULL != h->transactions_head)
{
for (pos = h->transactions_head;
NULL != pos;
pos = pos->next)
- if (pos->row_id == hri.start)
+ if (pos->row_id == ha.start_idx)
break;
if (NULL == pos)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Invalid range specified,"
- " transaction %llu not known!\n",
- (unsigned long long) hri.start);
+ "Invalid start specified, transaction %llu not known!\n",
+ (unsigned long long) ha.start_idx);
return MHD_NO;
}
/* range is exclusive, skip the matching entry */
- if (hri.count > 0)
+ if (ha.delta > 0)
pos = pos->next;
- if (hri.count < 0)
+ if (ha.delta < 0)
pos = pos->prev;
}
else
@@ -702,56 +840,77 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
/* list is empty */
pos = NULL;
}
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "/history, start row (0 == no transactions exist): %llu\n",
- NULL != pos ? pos->row_id : 0LL);
- return TFH_build_history_response (connection,
- pos,
- &ha,
- &TFH_handle_history_skip,
- &TFH_handle_history_step,
- &TFH_handle_history_advance);
+ history = json_array ();
+ while ( (0 != ha.delta) &&
+ (NULL != pos) )
+ {
+ if (0 == strcasecmp (pos->debit_account,
+ account))
+ {
+ json_t *trans;
+
+ trans = json_pack
+ ("{s:I, s:o, s:o, s:s, s:s, s:s}",
+ "row_id", (json_int_t) pos->row_id,
+ "date", GNUNET_JSON_from_time_abs (pos->date),
+ "amount", TALER_JSON_from_amount (&pos->amount),
+ "credit_account", pos->credit_account,
+ "debit_account", account,
+ "reserve_pub", pos->subject /* we "know" it is OK */);
+ GNUNET_assert (0 ==
+ json_array_append_new (history,
+ trans));
+ if (ha.delta > 0)
+ ha.delta--;
+ else
+ ha.delta++;
+ }
+ if (ha.delta > 0)
+ pos = pos->prev;
+ else
+ pos = pos->next;
+ }
+ return TALER_MHD_reply_json (connection,
+ history,
+ MHD_HTTP_OK);
}
/**
* Handle incoming HTTP request.
*
- * @param cls a `struct TALER_FAKEBANK_Handle`
+ * @param h our handle
* @param connection the connection
* @param url the requested url
* @param method the method (POST, GET, ...)
- * @param version HTTP version (ignored)
+ * @param account which account should process the request
* @param upload_data request data
* @param upload_data_size size of @a upload_data in bytes
* @param con_cls closure for request (a `struct Buffer *`)
* @return MHD result code
*/
static int
-handle_mhd_request (void *cls,
- struct MHD_Connection *connection,
- const char *url,
- const char *method,
- const char *version,
- const char *upload_data,
- size_t *upload_data_size,
- void **con_cls)
+serve (struct TALER_FAKEBANK_Handle *h,
+ struct MHD_Connection *connection,
+ const char *account,
+ const char *url,
+ const char *method,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **con_cls)
{
- struct TALER_FAKEBANK_Handle *h = cls;
-
- (void) version;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Fakebank, serving: %s\n",
url);
- if ( (0 == strcasecmp (url,
- "/")) &&
+ if ( (0 == strcmp (url,
+ "/")) &&
(0 == strcasecmp (method,
MHD_HTTP_METHOD_GET)) )
return handle_home_page (h,
connection,
con_cls);
- if ( (0 == strcasecmp (url,
- "/admin/add/incoming")) &&
+ if ( (0 == strcmp (url,
+ "/admin/add/incoming")) &&
(0 == strcasecmp (method,
MHD_HTTP_METHOD_POST)) )
return handle_admin_add_incoming (h,
@@ -759,22 +918,33 @@ handle_mhd_request (void *cls,
upload_data,
upload_data_size,
con_cls);
- if ( (0 == strcasecmp (url,
- "/reject")) &&
+ if ( (0 == strcmp (url,
+ "/transaction")) &&
+ (NULL != account) &&
(0 == strcasecmp (method,
MHD_HTTP_METHOD_POST)) )
- return handle_reject (h,
- connection,
- upload_data,
- upload_data_size,
- con_cls);
- if ( (0 == strcasecmp (url,
- "/history")) &&
+ return handle_transaction (h,
+ connection,
+ account,
+ upload_data,
+ upload_data_size,
+ con_cls);
+ if ( (0 == strcmp (url,
+ "/history/incoming")) &&
+ (NULL != account) &&
+ (0 == strcasecmp (method,
+ MHD_HTTP_METHOD_GET)) )
+ return handle_credit_history (h,
+ connection,
+ account);
+ if ( (0 == strcmp (url,
+ "/history/outgoing")) &&
+ (NULL != account) &&
(0 == strcasecmp (method,
MHD_HTTP_METHOD_GET)) )
- return handle_history (h,
- connection,
- con_cls);
+ return handle_debit_history (h,
+ connection,
+ account);
/* Unexpected URL path, just close the connection. */
/* we're rather impolite here, but it's a testcase. */
@@ -786,6 +956,55 @@ handle_mhd_request (void *cls,
/**
+ * Handle incoming HTTP request.
+ *
+ * @param cls a `struct TALER_FAKEBANK_Handle`
+ * @param connection the connection
+ * @param url the requested url
+ * @param method the method (POST, GET, ...)
+ * @param version HTTP version (ignored)
+ * @param upload_data request data
+ * @param upload_data_size size of @a upload_data in bytes
+ * @param con_cls closure for request (a `struct Buffer *`)
+ * @return MHD result code
+ */
+static int
+handle_mhd_request (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **con_cls)
+{
+ struct TALER_FAKEBANK_Handle *h = cls;
+ char *account = NULL;
+ char *end;
+ int ret;
+
+ (void) version;
+ if ( (strlen (url) > 1) &&
+ (NULL != (end = strchr (url + 1, '/'))) )
+ {
+ account = GNUNET_strndup (url + 1,
+ end - url - 1);
+ url = end;
+ }
+ ret = serve (h,
+ connection,
+ account,
+ url,
+ method,
+ upload_data,
+ upload_data_size,
+ con_cls);
+ GNUNET_free_non_null (account);
+ return ret;
+}
+
+
+/**
* Task run whenever HTTP server operations are pending.
*
* @param cls the `struct TALER_FAKEBANK_Handle`
@@ -918,6 +1137,7 @@ TALER_FAKEBANK_start (uint16_t port)
struct TALER_FAKEBANK_Handle *h;
h = GNUNET_new (struct TALER_FAKEBANK_Handle);
+ h->port = port;
h->mhd_bank = MHD_start_daemon (MHD_USE_DEBUG
#if EPOLL_SUPPORT
| MHD_USE_EPOLL_INTERNAL_THREAD
diff --git a/src/bank-lib/fakebank.h b/src/bank-lib/fakebank.h
index cc235901..c52902f1 100644
--- a/src/bank-lib/fakebank.h
+++ b/src/bank-lib/fakebank.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2016, 2017, 2018 Inria and GNUnet e.V.
+ (C) 2016-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -19,7 +19,7 @@
/**
* @file bank-lib/fakebank.h
- * @brief definitions for the "/history[-range]" layer.
+ * @brief definitions for the "/history" layer.
* @author Marcello Stanisci <stanisci.m@gmail.com>
*/
@@ -29,283 +29,4 @@
#include <gnunet/gnunet_util_lib.h>
#include "taler_bank_service.h"
-/**
- * Details about a transcation we (as the simulated bank) received.
- */
-struct Transaction
-{
- /**
- * We store transactions in a DLL.
- */
- struct Transaction *next;
-
- /**
- * We store transactions in a DLL.
- */
- struct Transaction *prev;
-
- /**
- * Amount to be transferred.
- */
- struct TALER_Amount amount;
-
- /**
- * Account to debit.
- */
- uint64_t debit_account;
-
- /**
- * Account to credit.
- */
- uint64_t credit_account;
-
- /**
- * Subject of the transfer.
- */
- char *subject;
-
- /**
- * Base URL of the exchange.
- */
- char *exchange_base_url;
-
- /**
- * When did the transaction happen?
- */
- struct GNUNET_TIME_Absolute date;
-
- /**
- * Number of this transaction.
- */
- long long unsigned int row_id;
-
- /**
- * Flag set if the transfer was rejected.
- */
- int rejected;
-
- /**
- * Has this transaction been subjected to #TALER_FAKEBANK_check()
- * and should thus no longer be counted in
- * #TALER_FAKEBANK_check_empty()?
- */
- int checked;
-};
-
-
-/******************************************
- * Definitions for "/history" start here. *
- ******************************************/
-
-/**
- * Needed to implement ascending/descending ordering
- * of /history results.
- */
-struct HistoryElement
-{
-
- /**
- * History JSON element.
- */
- json_t *element;
-
- /**
- * Previous element.
- */
- struct HistoryElement *prev;
-
- /**
- * Next element.
- */
- struct HistoryElement *next;
-};
-
-
-/**
- * Values to implement the "/history-range" range.
- */
-struct HistoryRangeDates
-{
- /**
- * Oldest row in the results.
- */
- struct GNUNET_TIME_Absolute start;
-
- /**
- * Youngest row in the results.
- */
- struct GNUNET_TIME_Absolute end;
-};
-
-/**
- * Values to implement the "/history" range.
- */
-struct HistoryRangeIds
-{
-
- /**
- * (Exclusive) row ID for the result set.
- */
- unsigned long long start;
-
- /**
- * How many transactions we want in the result set. If
- * negative/positive, @a start will be strictly younger/older
- * of any element in the result set.
- */
- long long count;
-};
-
-
-/**
- * This is the "base" structure for both the /history and the
- * /history-range API calls.
- */
-struct HistoryArgs
-{
-
- /**
- * Direction asked by the client: CREDIT / DEBIT / BOTH / CANCEL.
- */
- enum TALER_BANK_Direction direction;
-
- /**
- * Bank account number of the requesting client.
- */
- unsigned long long account_number;
-
- /**
- * Ordering of the results.
- */
- unsigned int ascending;
-
- /**
- * Overloaded type that indicates the "range" to be returned
- * in the results; this can be either a date range, or a
- * starting row id + the count.
- */
- void *range;
-};
-
-
-/**
- * Type for a function that decides whether or not
- * the history-building loop should iterate once again.
- * Typically called from inside the 'while' condition.
- *
- * @param ha history argument.
- * @param pos current position.
- * @return GNUNET_YES if the iteration shuold go on.
- */
-typedef int (*CheckAdvance)(const struct HistoryArgs *ha,
- const struct Transaction *pos);
-
-/**
- * Type for a function that steps over the next element
- * in the list of all transactions, after the current @a pos
- * _got_ included in the result.
- */
-typedef struct Transaction * (*Step)(const struct HistoryArgs *ha,
- const struct Transaction *pos);
-
-/*
- * Type for a function that steps over the next element
- * in the list of all transactions, after the current @a pos
- * did _not_ get included in the result.
- */
-typedef struct Transaction * (*Skip)(const struct HistoryArgs *ha,
- const struct Transaction *pos);
-
-/**
- * Actual history response builder.
- *
- * @param pos first (included) element in the result set.
- * @param ha history arguments.
- * @param caller_name which function is building the history.
- * @return MHD_YES / MHD_NO, after having enqueued the response
- * object into MHD.
- */
-int
-TFH_build_history_response (struct MHD_Connection *connection,
- struct Transaction *pos,
- struct HistoryArgs *ha,
- Skip skip,
- Step step,
- CheckAdvance advance);
-
-
-/**
- * Parse URL history arguments, of _both_ APIs:
- * /history and /history-range.
- *
- * @param connection MHD connection.
- * @param function_name name of the caller.
- * @param ha[out] will contain the parsed values.
- * @return GNUNET_OK only if the parsing succeedes.
- */
-int
-TFH_parse_history_common_args (struct MHD_Connection *connection,
- struct HistoryArgs *ha);
-
-
-/**
- * Decides whether the history builder will advance or not
- * to the next element.
- *
- * @param ha history args
- * @return GNUNET_YES/NO to advance/not-advance.
- */
-int
-TFH_handle_history_advance (const struct HistoryArgs *ha,
- const struct Transaction *pos);
-
-/**
- * Iterates on the "next" element to be processed. To
- * be used when the current element does not get inserted in
- * the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-struct Transaction *
-TFH_handle_history_skip (const struct HistoryArgs *ha,
- const struct Transaction *pos);
-
-/**
- * Iterates on the "next" element to be processed. To
- * be used when the current element _gets_ inserted in the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-struct Transaction *
-TFH_handle_history_step (const struct HistoryArgs *ha,
- const struct Transaction *pos);
-
-/**
- * Decides whether the history builder will advance or not
- * to the next element.
- *
- * @param ha history args
- * @return GNUNET_YES/NO to advance/not-advance.
- */
-int
-TFH_handle_history_range_advance (const struct HistoryArgs *ha,
- const struct Transaction *pos);
-
-/**
- * Iterates towards the "next" element to be processed. To
- * be used when the current element does not get inserted in
- * the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-struct Transaction *
-TFH_handle_history_range_skip (const struct HistoryArgs *ha,
- const struct Transaction *pos);
-
#endif
diff --git a/src/bank-lib/fakebank_history.c b/src/bank-lib/fakebank_history.c
index f4c615c5..2781cdca 100644
--- a/src/bank-lib/fakebank_history.c
+++ b/src/bank-lib/fakebank_history.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2016, 2017, 2018 Inria and GNUnet e.V.
+ (C) 2016-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -19,92 +19,15 @@
/**
* @file bank-lib/fakebank_history.c
- * @brief definitions for the "/history[-range]" layer.
+ * @brief definitions for the "/history" layer.
* @author Marcello Stanisci <stanisci.m@gmail.com>
*/
-
#include "platform.h"
#include <gnunet/gnunet_util_lib.h>
#include "taler_json_lib.h"
#include "fakebank.h"
-/**
- * Decides whether the history builder will advance or not
- * to the next element.
- *
- * @param ha history args
- * @return GNUNET_YES/NO to advance/not-advance.
- */
-int
-TFH_handle_history_advance (const struct HistoryArgs *ha,
- const struct Transaction *pos)
-{
- const struct HistoryRangeIds *hri = ha->range;
-
- return (NULL != pos) && (0 != hri->count);
-}
-
-
-/**
- * Iterates on the "next" element to be processed. To
- * be used when the current element does not get inserted in
- * the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-struct Transaction *
-TFH_handle_history_skip (const struct HistoryArgs *ha,
- const struct Transaction *pos)
-{
- const struct HistoryRangeIds *hri = ha->range;
-
- if (hri->count > 0)
- return pos->next;
- if (hri->count < 0)
- return pos->prev;
- return NULL;
-}
-
-
-/**
- * Iterates on the "next" element to be processed. To
- * be used when the current element _gets_ inserted in the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-struct Transaction *
-TFH_handle_history_step (const struct HistoryArgs *ha,
- const struct Transaction *pos)
-{
- struct HistoryRangeIds *hri = ha->range;
-
- if (hri->count > 0)
- {
- hri->count--;
- return pos->next;
- }
- if (hri->count < 0)
- {
- hri->count++;
- return pos->prev;
- }
- return NULL;
-}
-
-/**
- * Actual history response builder.
- *
- * @param pos first (included) element in the result set, NULL if history is empty
- * @param ha history arguments.
- * @param caller_name which function is building the history.
- * @return MHD_YES / MHD_NO, after having enqueued the response
- * object into MHD.
- */
int
TFH_build_history_response (struct MHD_Connection *connection,
struct Transaction *pos,
@@ -257,126 +180,3 @@ TFH_build_history_response (struct MHD_Connection *connection,
}
return ret;
}
-
-
-/**
- * Parse URL history arguments, of _both_ APIs:
- * /history and /history-range.
- *
- * @param connection MHD connection.
- * @param function_name name of the caller.
- * @param ha[out] will contain the parsed values.
- * @return GNUNET_OK only if the parsing succeedes.
- */
-int
-TFH_parse_history_common_args (struct MHD_Connection *connection,
- struct HistoryArgs *ha)
-{
- /**
- * @variable
- * Just check if given and == "basic", no need to keep around.
- */
- const char *auth;
-
- /**
- * All those will go into the structure, after parsing.
- */
- const char *direction;
- const char *cancelled;
- const char *ordering;
- const char *account_number;
-
-
- auth = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "auth");
- direction = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "direction");
- cancelled = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "cancelled");
- ordering = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "ordering");
- account_number = MHD_lookup_connection_value
- (connection,
- MHD_GET_ARGUMENT_KIND,
- "account_number");
-
- /* Fail if one of the above failed. */
- if ( (NULL == direction) ||
- (NULL == cancelled) ||
- ( (0 != strcasecmp (cancelled,
- "OMIT")) &&
- (0 != strcasecmp (cancelled,
- "SHOW")) ) ||
- ( (0 != strcasecmp (direction,
- "BOTH")) &&
- (0 != strcasecmp (direction,
- "CREDIT")) &&
- (0 != strcasecmp (direction,
- "DEBIT")) ) ||
- (1 != sscanf (account_number,
- "%llu",
- &ha->account_number)) ||
- ( (NULL == auth) || (0 != strcasecmp (auth,
- "basic")) ) )
- {
- /* Invalid request, given that this is fakebank we impolitely
- * just kill the connection instead of returning a nice error.
- */
- GNUNET_break (0);
- return GNUNET_NO;
- }
-
- if (0 == strcasecmp (direction,
- "CREDIT"))
- {
- ha->direction = TALER_BANK_DIRECTION_CREDIT;
- }
- else if (0 == strcasecmp (direction,
- "DEBIT"))
- {
- ha->direction = TALER_BANK_DIRECTION_DEBIT;
- }
- else if (0 == strcasecmp (direction,
- "BOTH"))
- {
- ha->direction = TALER_BANK_DIRECTION_BOTH;
- }
-
- /* Direction is invalid. */
- else
- {
- GNUNET_break (0);
- return GNUNET_NO;
- }
-
- if (0 == strcasecmp (cancelled,
- "OMIT"))
- {
- /* nothing */
- }
- else if (0 == strcasecmp (cancelled,
- "SHOW"))
- {
- ha->direction |= TALER_BANK_DIRECTION_CANCEL;
- }
-
- /* Cancel-showing policy is invalid. */
- else
- {
- GNUNET_break (0);
- return GNUNET_NO;
- }
-
- if ((NULL != ordering)
- && (0 == strcmp ("ascending",
- ordering)))
- ha->ascending = GNUNET_YES;
- else
- ha->ascending = GNUNET_NO;
-
- return GNUNET_OK;
-}
diff --git a/src/bank-lib/taler-bank-transfer.c b/src/bank-lib/taler-bank-transfer.c
index 625545b6..c52c4b38 100644
--- a/src/bank-lib/taler-bank-transfer.c
+++ b/src/bank-lib/taler-bank-transfer.c
@@ -25,9 +25,9 @@
#include "taler_bank_service.h"
/**
- * Bank URL.
+ * Account base URL.
*/
-static char *bank_url;
+static char *account_base_url;
/**
* Amount to transfer.
@@ -35,14 +35,9 @@ static char *bank_url;
static struct TALER_Amount amount;
/**
- * Debit account number.
+ * Credit account payto://-URI.
*/
-static unsigned long long debit_account_no;
-
-/**
- * Credit account number.
- */
-static unsigned long long credit_account_no;
+static char *credit_account;
/**
* Wire transfer subject.
@@ -168,11 +163,23 @@ run (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct TALER_BANK_AuthenticationData auth;
+ struct TALER_ReservePublicKeyP reserve_pub;
(void) cls;
(void) args;
(void) cfgfile;
(void) cfg;
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (subject,
+ strlen (subject),
+ &reserve_pub,
+ sizeof (reserve_pub)))
+ {
+ fprintf (stderr,
+ "Error: wire transfer subject must be a reserve public key\n");
+ return;
+ }
+
ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
&rc);
GNUNET_assert (NULL != ctx);
@@ -182,13 +189,11 @@ run (void *cls,
auth.details.basic.username = username;
auth.details.basic.password = password;
op = TALER_BANK_admin_add_incoming (ctx,
- bank_url,
+ account_base_url,
&auth,
- "https://exchange.com/legacy",
- subject,
+ &reserve_pub,
&amount,
- debit_account_no,
- credit_account_no,
+ credit_account,
&res_cb,
NULL);
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
@@ -219,26 +224,20 @@ main (int argc, char *const *argv)
(GNUNET_GETOPT_option_string ('b',
"bank",
"URL",
- "base URL of the bank",
- &bank_url)),
+ "base URL of the account at the bank",
+ &account_base_url)),
GNUNET_GETOPT_option_help ("Deposit funds into a Taler reserve"),
GNUNET_GETOPT_option_mandatory
- (GNUNET_GETOPT_option_ulong ('C',
- "credit",
- "ACCOUNT",
- "number of the bank account to credit",
- &credit_account_no)),
- GNUNET_GETOPT_option_mandatory
- (GNUNET_GETOPT_option_ulong ('D',
- "debit",
- "ACCOUNT",
- "number of the bank account to debit",
- &debit_account_no)),
+ (GNUNET_GETOPT_option_string ('C',
+ "credit",
+ "ACCOUNT",
+ "payto URL of the bank account to credit",
+ &credit_account)),
GNUNET_GETOPT_option_mandatory
(GNUNET_GETOPT_option_string ('s',
"subject",
"STRING",
- "specifies the wire transfer subject",
+ "specifies the wire transfer subject (must be a reserve public key)",
&subject)),
GNUNET_GETOPT_option_mandatory
(GNUNET_GETOPT_option_string ('u',
diff --git a/src/bank-lib/test_bank_api.c b/src/bank-lib/test_bank_api.c
index d15984a9..087e4484 100644
--- a/src/bank-lib/test_bank_api.c
+++ b/src/bank-lib/test_bank_api.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2016, 2017 GNUnet e.V.
+ Copyright (C) 2016-2020 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
diff --git a/src/bank-lib/testing_api_cmd_history.c b/src/bank-lib/testing_api_cmd_history_credit.c
index dc5cd2d9..5c2b34d0 100644
--- a/src/bank-lib/testing_api_cmd_history.c
+++ b/src/bank-lib/testing_api_cmd_history_credit.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
+ Copyright (C) 2018-2020 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
@@ -16,13 +16,11 @@
License along with TALER; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>
*/
-
/**
* @file bank-lib/testing_api_cmd_history.c
* @brief command to check the /history API from the bank.
* @author Marcello Stanisci
*/
-
#include "platform.h"
#include "taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
@@ -40,35 +38,26 @@
struct HistoryState
{
/**
- * Base URL of the bank offering the "history" operation.
- */
- const char *bank_url;
-
- /**
- * Account number to ask the history for.
- */
- uint64_t account_no;
-
- /**
- * Which type of records we are interested: in-transfers
- * / out-transfers / rejected transfers.
+ * Base URL of the account offering the "history" operation.
*/
- enum TALER_BANK_Direction direction;
+ char *account_url;
/**
- * First row number we want in the result.
+ * Reference to command defining the
+ * first row number we want in the result.
*/
const char *start_row_reference;
/**
- * How many rows we want in the result, _at most_.
+ * How many rows we want in the result, _at most_,
+ * and ascending/descending.
*/
- unsigned long long num_results;
+ long long num_results;
/**
* Handle to a pending "history" operation.
*/
- struct TALER_BANK_HistoryHandle *hh;
+ struct TALER_BANK_CreditHistoryHandle *hh;
/**
* Expected number of results (= rows).
@@ -81,34 +70,9 @@ struct HistoryState
*/
int failed;
- /**
- * If GNUNET_YES, this parameter will ask for results in
- * chronological order.
- */
- unsigned int ascending;
-
- /**********************************
- * Following defs are specific to *
- * the "/history-range" version. *
- **********************************/
-
- /**
- * Last row number we want in the result. Only used
- * as a trait source when using the /history-range API.
- */
- const char *end_row_reference;
-
- /**
- * Start date for /history-range.
- */
- struct GNUNET_TIME_Absolute start_date;
-
- /**
- * End date for /history-range.
- */
- struct GNUNET_TIME_Absolute end_date;
};
+
/**
* Item in the transaction history, as reconstructed from the
* command history.
@@ -119,7 +83,7 @@ struct History
/**
* Wire details.
*/
- struct TALER_BANK_TransferDetails details;
+ struct TALER_BANK_CreditDetails details;
/**
* Serial ID of the wire transfer.
@@ -127,20 +91,13 @@ struct History
uint64_t row_id;
/**
- * Direction of the transfer.
+ * URL to free.
*/
- enum TALER_BANK_Direction direction;
-
+ char *url;
};
/**
- * Array mapping bank account numbers to login credentials.
- */
-extern struct TALER_BANK_AuthenticationData AUTHS[];
-
-
-/**
* Offer internal data to other commands.
*
* @param cls closure.
@@ -167,51 +124,6 @@ history_traits (void *cls,
/**
- * Test if the CMD at offset @a off has been /rejected, and
- * is indeed a wire transfer CMD.
- *
- * @param is interpreter state (where we are right now)
- * @param off offset of the command to test for rejection.
- *
- * @return GNUNET_YES if the command at @a off was cancelled.
- */
-static int
-test_cancelled (struct TALER_TESTING_Interpreter *is,
- unsigned int off)
-{
- const char *rejected_reference;
- const struct TALER_TESTING_Command *current_cmd;
-
- current_cmd = &is->commands[off];
- TALER_LOG_INFO ("Is `%s' rejected?\n",
- current_cmd->label);
- for (int i = 0; i<is->ip; i++)
- {
- const struct TALER_TESTING_Command *c = &is->commands[i];
-
-
- /* XXX: Errors reported here are NOT fatal */
-
- /* Rejected wire transfers have a non-NULL reference to a
- * reject command to mark them as rejected. So errors
- * about "reject traits" not found are NOT fatal here */
- if (GNUNET_OK != TALER_TESTING_get_trait_rejected
- (c, 0, &rejected_reference))
- continue;
-
- TALER_LOG_INFO ("Command `%s' was rejected by `%s'.\n",
- current_cmd->label,
- c->label);
-
- if (0 == strcmp (rejected_reference,
- current_cmd->label))
- return GNUNET_YES;
- }
- return GNUNET_NO;
-}
-
-
-/**
* Free history @a h of length @a h_len.
*
* @param h history array to free.
@@ -222,10 +134,7 @@ free_history (struct History *h,
uint64_t h_len)
{
for (uint64_t off = 0; off<h_len; off++)
- {
- GNUNET_free (h[off].details.wire_transfer_subject);
- GNUNET_free (h[off].details.account_url);
- }
+ GNUNET_free (h[off].url);
GNUNET_free_non_null (h);
}
@@ -251,14 +160,12 @@ print_expected (struct History *h,
for (uint64_t i = 0; i<h_len; i++)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "H(%llu): %s%s (serial: %llu, subject: %s,"
+ "H(%llu): %s (serial: %llu, subject: %s,"
" counterpart: %s)\n",
(unsigned long long) i,
- (TALER_BANK_DIRECTION_CREDIT == h[i].direction) ?
- "+" : "-",
TALER_amount2s (&h[i].details.amount),
(unsigned long long) h[i].row_id,
- h[i].details.wire_transfer_subject,
+ TALER_B2S (&h[i].details.reserve_pub),
h[i].details.account_url);
}
}
@@ -280,20 +187,6 @@ build_history_hit_limit (uint64_t total,
const struct HistoryState *hs,
const struct TALER_TESTING_Command *pos)
{
- /* "/history-range" case. */
- if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
- hs->start_date.abs_value_us)
- {
- const struct GNUNET_TIME_Absolute *timestamp;
-
- GNUNET_assert (GNUNET_OK ==
- TALER_TESTING_get_trait_absolute_time (pos,
- 0,
- &timestamp));
- GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
- hs->end_date.abs_value_us);
- return timestamp->abs_value_us >= hs->end_date.abs_value_us;
- }
return total >= hs->num_results;
}
@@ -305,13 +198,6 @@ build_history_hit_limit (uint64_t total,
* to be allocated, and the second to actually populate every
* element.
*
- * This command has a limitation currently: it orders the history
- * list with descending elements if and only if the 'delta' was
- * given negative; and will order the list with ascending elements
- * if and only if the 'delta' was given positive. Therefore,
- * for now it is NOT possible to test such a "/history" request:
- * "/history?auth=basic&direction=both&delta=10&ordering=descending"
- *
* @param is interpreter state (supposedly having the
* current CMD pointing at a "history" CMD).
* @param[out] rh history array to initialize.
@@ -350,10 +236,7 @@ build_history (struct TALER_TESTING_Interpreter *is,
(add_incoming_cmd, 0, &row_id_start));
}
- GNUNET_assert ((0 != hs->num_results) || /* "/history" */
- (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != /* "/history-range" */
- hs->start_date.abs_value_us));
-
+ GNUNET_assert (0 != hs->num_results);
if (0 == is->ip)
{
TALER_LOG_DEBUG ("Checking history at first CMD..\n");
@@ -387,8 +270,9 @@ build_history (struct TALER_TESTING_Interpreter *is,
for (unsigned int off = start; off != end + inc; off += inc)
{
const struct TALER_TESTING_Command *pos = &is->commands[off];
- int cancelled;
const uint64_t *row_id;
+ const char *credit_account;
+ const char *debit_account;
/**
* The following command allows us to skip over those CMDs
@@ -411,28 +295,6 @@ build_history (struct TALER_TESTING_Interpreter *is,
}
}
- /* Seek "/history-range" starting row, _if_ that's the case */
- if ((GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
- hs->start_date.abs_value_us) && (GNUNET_YES != ok))
- {
- const struct GNUNET_TIME_Absolute *timestamp;
-
- TALER_TESTING_get_trait_absolute_time (pos,
- 0,
- &timestamp);
- TALER_LOG_DEBUG
- ("Seeking first row, start vs timestamp: %llu vs %llu\n",
- (long long unsigned int) hs->start_date.abs_value_us,
- (long long unsigned int) timestamp->abs_value_us);
-
- if (hs->start_date.abs_value_us <= timestamp->abs_value_us)
- {
- total = 0;
- ok = GNUNET_YES;
- continue;
- }
- }
-
/* when 'start' was _not_ given, then ok == GNUNET_YES */
if (GNUNET_NO == ok)
continue; /* skip until we find the marker */
@@ -447,37 +309,23 @@ build_history (struct TALER_TESTING_Interpreter *is,
break;
}
- cancelled = test_cancelled (is, off);
-
- if ( (GNUNET_YES == cancelled) &&
- (0 == (hs->direction & TALER_BANK_DIRECTION_CANCEL)) )
- {
- TALER_LOG_INFO ("Ignoring canceled wire"
- " transfer from history\n");
- continue;
- }
-
- const uint64_t *credit_account_no;
- const uint64_t *debit_account_no;
GNUNET_assert
(GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT
- (pos, &credit_account_no));
+ (pos, &credit_account));
GNUNET_assert
(GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT
- (pos, &debit_account_no));
+ (pos, &debit_account));
TALER_LOG_INFO ("Potential history element:"
- " %llu->%llu; my account: %llu\n",
- (unsigned long long) *debit_account_no,
- (unsigned long long) *credit_account_no,
- (unsigned long long) hs->account_no);
-
- if ( ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
- (hs->account_no == *credit_account_no)) ||
- ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
- (hs->account_no == *debit_account_no)) )
+ " %s->%s; my account: %s\n",
+ debit_account,
+ credit_account,
+ hs->account_url);
+
+ if (0 == strcasecmp (hs->account_url,
+ credit_account))
{
TALER_LOG_INFO ("+1 my history\n");
total++; /* found matching record */
@@ -508,11 +356,10 @@ build_history (struct TALER_TESTING_Interpreter *is,
for (unsigned int off = start; off != end + inc; off += inc)
{
const struct TALER_TESTING_Command *pos = &is->commands[off];
- int cancelled;
const uint64_t *row_id;
char *bank_hostname;
- const uint64_t *credit_account_no;
- const uint64_t *debit_account_no;
+ const char *credit_account;
+ const char *debit_account;
if (GNUNET_OK != TALER_TESTING_GET_TRAIT_ROW_ID
(pos, &row_id))
@@ -533,28 +380,6 @@ build_history (struct TALER_TESTING_Interpreter *is,
}
}
- /* Seek "/history-range" starting row, _if_ that's the case */
- if ((GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
- hs->start_date.abs_value_us) && (GNUNET_YES != ok))
- {
- const struct GNUNET_TIME_Absolute *timestamp;
-
- TALER_TESTING_get_trait_absolute_time (pos,
- 0,
- &timestamp);
- TALER_LOG_DEBUG
- ("Seeking first row, start vs timestamp (2): %llu vs %llu\n",
- (long long unsigned int) hs->start_date.abs_value_us,
- (long long unsigned int) timestamp->abs_value_us);
-
- if (hs->start_date.abs_value_us <= timestamp->abs_value_us)
- {
- total = 0;
- ok = GNUNET_YES;
- continue;
- }
- }
-
TALER_LOG_INFO ("Found first row (2)\n");
if (GNUNET_NO == ok)
@@ -574,43 +399,31 @@ build_history (struct TALER_TESTING_Interpreter *is,
GNUNET_assert
(GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT
- (pos, &credit_account_no));
+ (pos, &credit_account));
GNUNET_assert
(GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT
- (pos, &debit_account_no));
+ (pos, &debit_account));
TALER_LOG_INFO ("Potential history bit:"
- " %llu->%llu; my account: %llu\n",
- (unsigned long long) *debit_account_no,
- (unsigned long long) *credit_account_no,
- (unsigned long long) hs->account_no);
+ " %s->%s; my account: %s\n",
+ debit_account,
+ credit_account,
+ hs->account_url);
/**
* Discard transactions where the audited account played
* _both_ the credit and the debit roles, but _only if_
* the audit goes on both directions.. This needs more
* explaination!
- */if ( ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
- (hs->account_no == *credit_account_no)) &&
- ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
- (hs->account_no == *debit_account_no)) )
+ */if (0 == strcasecmp (hs->account_url,
+ credit_account))
{
GNUNET_break (0);
continue;
}
- cancelled = test_cancelled (is, off);
- if ( (GNUNET_YES == cancelled) &&
- (0 == (hs->direction & TALER_BANK_DIRECTION_CANCEL)) )
- {
- TALER_LOG_WARNING ("`%s' was cancelled\n",
- TALER_TESTING_interpreter_get_current_label
- (is));
- continue;
- }
-
- bank_hostname = strchr (hs->bank_url, ':');
+ bank_hostname = strchr (hs->account_url, ':');
GNUNET_assert (NULL != bank_hostname);
bank_hostname += 3;
@@ -618,68 +431,36 @@ build_history (struct TALER_TESTING_Interpreter *is,
* information. */
/* Asked for credit, and account got the credit. */
- if ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
- (hs->account_no == *credit_account_no))
- {
- h[total].direction = TALER_BANK_DIRECTION_CREDIT;
- if (GNUNET_YES == cancelled)
- h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
-
- GNUNET_asprintf
- (&h[total].details.account_url,
- ('/' == bank_hostname[strlen (bank_hostname) - 1])
- ? "payto://x-taler-bank/%s%llu"
- : "payto://x-taler-bank/%s/%llu",
- bank_hostname,
- (unsigned long long) *debit_account_no);
- }
-
- /* Asked for debit, and account got the debit. */
- if ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
- (hs->account_no == *debit_account_no))
+ if (0 == strcasecmp (hs->account_url,
+ credit_account))
{
- h[total].direction = TALER_BANK_DIRECTION_DEBIT;
- if (GNUNET_YES == cancelled)
- h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
-
- GNUNET_asprintf
- (&h[total].details.account_url,
- ('/' == bank_hostname[strlen (bank_hostname) - 1])
- ? "payto://x-taler-bank/%s%llu"
- : "payto://x-taler-bank/%s/%llu",
- bank_hostname,
- (unsigned long long) *credit_account_no);
+ h[total].url = GNUNET_strdup (debit_account);
+ h[total].details.account_url = h[total].url;
}
/* This block _completes_ the information of the current item,
* with amount / subject / exchange URL. */
- if ( ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
- (hs->account_no == *credit_account_no)) ||
- ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
- (hs->account_no == *debit_account_no)) )
+ if (0 == strcasecmp (hs->account_url,
+ credit_account))
{
const struct TALER_Amount *amount;
- const char *subject;
- const char *exchange_url;
-
- GNUNET_assert
- (GNUNET_OK == TALER_TESTING_get_trait_amount_obj
- (pos, 0, &amount));
-
- GNUNET_assert
- (GNUNET_OK == TALER_TESTING_get_trait_transfer_subject
- (pos, 0, &subject));
-
- GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_url
- (pos, 0, &exchange_url));
-
+ const struct TALER_ReservePublicKeyP *reserve_pub;
+ const char *account_url;
+
+ GNUNET_assert (GNUNET_OK ==
+ TALER_TESTING_get_trait_amount_obj
+ (pos, 0, &amount));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_TESTING_get_trait_reserve_pub
+ (pos, 0, &reserve_pub));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_TESTING_get_trait_url
+ (pos, 1,
+ &account_url));
h[total].details.amount = *amount;
-
h[total].row_id = *row_id;
- GNUNET_asprintf (&h[total].details.wire_transfer_subject,
- "%s %s",
- subject,
- exchange_url);
+ h[total].details.reserve_pub = *reserve_pub;
+ h[total].details.account_url = account_url;
TALER_LOG_INFO ("+1-bit of my history\n");
total++;
}
@@ -723,8 +504,7 @@ compute_result_count (struct TALER_TESTING_Interpreter *is)
static int
check_result (struct TALER_TESTING_Interpreter *is,
unsigned int off,
- enum TALER_BANK_Direction dir,
- const struct TALER_BANK_TransferDetails *details)
+ const struct TALER_BANK_CreditDetails *details)
{
uint64_t total;
struct History *h;
@@ -737,27 +517,22 @@ check_result (struct TALER_TESTING_Interpreter *is,
" results, but got result #%u to check\n",
(unsigned int) total,
off);
- print_expected (h, total, off);
- return GNUNET_SYSERR;
- }
- if (h[off].direction != dir)
- {
- GNUNET_break (0);
- print_expected (h, total, off);
- free_history (h,
- total);
+ print_expected (h,
+ total,
+ off);
return GNUNET_SYSERR;
}
-
- if ( (0 != strcmp (h[off].details.wire_transfer_subject,
- details->wire_transfer_subject)) ||
+ if ( (0 != GNUNET_memcmp (&h[off].details.reserve_pub,
+ &details->reserve_pub)) ||
(0 != TALER_amount_cmp (&h[off].details.amount,
&details->amount)) ||
(0 != strcasecmp (h[off].details.account_url,
details->account_url)) )
{
GNUNET_break (0);
- print_expected (h, total, off);
+ print_expected (h,
+ total,
+ off);
free_history (h,
total);
return GNUNET_SYSERR;
@@ -789,22 +564,30 @@ check_result (struct TALER_TESTING_Interpreter *is,
* @param details details about the wire transfer.
* @param json detailed response from the HTTPD, or NULL if
* reply was not in JSON.
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/
-static void
+static int
history_cb (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
- enum TALER_BANK_Direction dir,
uint64_t row_id,
- const struct TALER_BANK_TransferDetails *details,
+ const struct TALER_BANK_CreditDetails *details,
const json_t *json)
{
struct TALER_TESTING_Interpreter *is = cls;
struct HistoryState *hs = is->commands[is->ip].cls;
(void) row_id;
- /*NOTE: "204 No Content" is used to signal the end of results.*/
- if (MHD_HTTP_NO_CONTENT == http_status)
+ if (MHD_HTTP_OK != http_status)
+ {
+ hs->hh = NULL;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unwanted response code from /history: %u\n",
+ http_status);
+ TALER_TESTING_interpreter_fail (is);
+ return GNUNET_SYSERR;
+ }
+ if (NULL == details)
{
hs->hh = NULL;
if ( (hs->results_obtained != compute_result_count (is)) ||
@@ -829,47 +612,33 @@ history_cb (void *cls,
free_history (h,
total);
TALER_TESTING_interpreter_fail (is);
- return;
+ return GNUNET_SYSERR;
}
TALER_TESTING_interpreter_next (is);
- return;
- }
-
- if (MHD_HTTP_OK != http_status)
- {
- hs->hh = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unwanted response code from /history[-range]: %u\n",
- http_status);
- TALER_TESTING_interpreter_fail (is);
- return;
+ return GNUNET_OK;
}
/* check current element */
if (GNUNET_OK != check_result (is,
hs->results_obtained,
- dir,
details))
{
- GNUNET_break (0);
-
- {
- char *acc;
-
- acc = json_dumps (json,
- JSON_COMPACT);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Result %u was `%s'\n",
- (unsigned int) hs->results_obtained++,
- acc);
- if (NULL != acc)
- free (acc);
- }
+ char *acc;
+ GNUNET_break (0);
+ acc = json_dumps (json,
+ JSON_COMPACT);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Result %u was `%s'\n",
+ (unsigned int) hs->results_obtained++,
+ acc);
+ if (NULL != acc)
+ free (acc);
hs->failed = GNUNET_YES;
- return;
+ return GNUNET_SYSERR;
}
hs->results_obtained++;
+ return GNUNET_OK;
}
@@ -886,9 +655,8 @@ history_run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
struct HistoryState *hs = cls;
- uint64_t row_id = UINT64_MAX;
- const uint64_t *row_id_ptr = &row_id;
- struct TALER_BANK_AuthenticationData *auth;
+ uint64_t row_id = (hs->num_results > 0) ? 0 : UINT64_MAX;
+ const uint64_t *row_ptr;
(void) cmd;
/* Get row_id from trait. */
@@ -902,27 +670,24 @@ history_run (void *cls,
if (NULL == history_cmd)
TALER_TESTING_FAIL (is);
- if (GNUNET_OK != TALER_TESTING_get_trait_uint64 (history_cmd,
- 0,
- &row_id_ptr))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_uint64 (history_cmd,
+ 0,
+ &row_ptr))
TALER_TESTING_FAIL (is);
- row_id = *row_id_ptr;
-
+ else
+ row_id = *row_ptr;
TALER_LOG_DEBUG ("row id (from trait) is %llu\n",
(unsigned long long) row_id);
}
- auth = &AUTHS[hs->account_no - 1];
- hs->hh = TALER_BANK_history (is->ctx,
- hs->bank_url,
- auth,
- hs->account_no,
- hs->direction,
- hs->ascending,
- row_id,
- hs->num_results,
- &history_cb,
- is);
+ hs->hh = TALER_BANK_credit_history (is->ctx,
+ hs->account_url,
+ NULL,
+ row_id,
+ hs->num_results,
+ &history_cb,
+ is);
GNUNET_assert (NULL != hs->hh);
}
@@ -944,8 +709,9 @@ history_cleanup (void *cls,
if (NULL != hs->hh)
{
TALER_LOG_WARNING ("/history did not complete\n");
- TALER_BANK_history_cancel (hs->hh);
+ TALER_BANK_credit_history_cancel (hs->hh);
}
+ GNUNET_free (hs->account_url);
GNUNET_free (hs);
}
@@ -954,12 +720,8 @@ history_cleanup (void *cls,
* Make a "history" CMD.
*
* @param label command label.
- * @param bank_url base URL of the bank offering the "history"
+ * @param account_url base URL of the account offering the "history"
* operation.
- * @param account_no bank account number to ask the history for.
- * @param direction which direction this operation is interested.
- * @param ascending if #GNUNET_YES, the bank will return the rows
- * in ascending (= chronological) order.
* @param start_row_reference reference to a command that can
* offer a row identifier, to be used as the starting row
* to accept in the result.
@@ -967,25 +729,17 @@ history_cleanup (void *cls,
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_bank_history (const char *label,
- const char *bank_url,
- uint64_t account_no,
- enum TALER_BANK_Direction direction,
- unsigned int ascending,
+TALER_TESTING_cmd_bank_credits (const char *label,
+ const char *account_url,
const char *start_row_reference,
- unsigned long long num_results)
+ long long num_results)
{
struct HistoryState *hs;
hs = GNUNET_new (struct HistoryState);
- hs->bank_url = bank_url;
- hs->account_no = account_no;
- hs->direction = direction;
+ hs->account_url = GNUNET_strdup (account_url);
hs->start_row_reference = start_row_reference;
hs->num_results = num_results;
- hs->ascending = ascending;
- hs->start_date = GNUNET_TIME_UNIT_FOREVER_ABS;
- hs->end_date = GNUNET_TIME_UNIT_FOREVER_ABS;
{
struct TALER_TESTING_Command cmd = {
@@ -1001,4 +755,4 @@ TALER_TESTING_cmd_bank_history (const char *label,
}
-/* end of testing_api_cmd_history.c */
+/* end of testing_api_cmd_credit_history.c */
diff --git a/src/bank-lib/testing_api_cmd_history_debit.c b/src/bank-lib/testing_api_cmd_history_debit.c
new file mode 100644
index 00000000..93f84da0
--- /dev/null
+++ b/src/bank-lib/testing_api_cmd_history_debit.c
@@ -0,0 +1,758 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2018-2020 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/testing_api_cmd_history.c
+ * @brief command to check the /history API from the bank.
+ * @author Marcello Stanisci
+ */
+
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_exchange_service.h"
+#include "taler_testing_lib.h"
+#include "taler_testing_bank_lib.h"
+#include "taler_fakebank_lib.h"
+#include "taler_bank_service.h"
+#include "taler_fakebank_lib.h"
+
+
+/**
+ * State for a "history" CMD.
+ */
+struct HistoryState
+{
+ /**
+ * Base URL of the account offering the "history" operation.
+ */
+ const char *account_url;
+
+ /**
+ * Reference to command defining the
+ * first row number we want in the result.
+ */
+ const char *start_row_reference;
+
+ /**
+ * How many rows we want in the result, _at most_,
+ * and ascending/descending.
+ */
+ long long num_results;
+
+ /**
+ * Handle to a pending "history" operation.
+ */
+ struct TALER_BANK_DebitHistoryHandle *hh;
+
+ /**
+ * Expected number of results (= rows).
+ */
+ uint64_t results_obtained;
+
+ /**
+ * Set to GNUNET_YES if the callback detects something
+ * unexpected.
+ */
+ int failed;
+
+};
+
+
+/**
+ * Item in the transaction history, as reconstructed from the
+ * command history.
+ */
+struct History
+{
+
+ /**
+ * Wire details.
+ */
+ struct TALER_BANK_DebitDetails details;
+
+ /**
+ * Serial ID of the wire transfer.
+ */
+ uint64_t row_id;
+
+ /**
+ * URL to free.
+ */
+ char *url;
+};
+
+
+/**
+ * Offer internal data to other commands.
+ *
+ * @param cls closure.
+ * @param ret[out] set to the wanted data.
+ * @param trait name of the trait.
+ * @param index index number of the traits to be returned.
+ *
+ * @return #GNUNET_OK on success
+ */
+static int
+history_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ (void) cls;
+ (void) ret;
+ (void) trait;
+ (void) index;
+ /* Must define this function because some callbacks
+ * look for certain traits on _all_ the commands. */
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Free history @a h of length @a h_len.
+ *
+ * @param h history array to free.
+ * @param h_len number of entries in @a h.
+ */
+static void
+free_history (struct History *h,
+ uint64_t h_len)
+{
+ for (uint64_t off = 0; off<h_len; off++)
+ GNUNET_free (h[off].url);
+ GNUNET_free_non_null (h);
+}
+
+
+/**
+ * Log which history we expected. Called when an error occurs.
+ *
+ * @param h what we expected.
+ * @param h_len number of entries in @a h.
+ * @param off position of the missmatch.
+ */
+static void
+print_expected (struct History *h,
+ uint64_t h_len,
+ unsigned int off)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Transaction history missmatch at position %u/%llu\n",
+ off,
+ (unsigned long long) h_len);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected history:\n");
+ for (uint64_t i = 0; i<h_len; i++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "H(%llu): %s (serial: %llu, subject: %s,"
+ " counterpart: %s)\n",
+ (unsigned long long) i,
+ TALER_amount2s (&h[i].details.amount),
+ (unsigned long long) h[i].row_id,
+ TALER_B2S (&h[i].details.wtid),
+ h[i].details.account_url);
+ }
+}
+
+
+/**
+ * Tell if the current item is beyond the allowed limit.
+ *
+ * @param total current number of items in the built history list.
+ * Note, this is the list we build locally and compare with
+ * what the server returned.
+ * @param hs the history CMD state.
+ * @param pos current item to be evaluated or not (if the list
+ * has already enough elements).
+ * @return GNUNET_OK / GNUNET_NO.
+ */
+static int
+build_history_hit_limit (uint64_t total,
+ const struct HistoryState *hs,
+ const struct TALER_TESTING_Command *pos)
+{
+ return total >= hs->num_results;
+}
+
+
+/**
+ * This function constructs the list of history elements that
+ * interest the account number of the caller. It has two main
+ * loops: the first to figure out how many history elements have
+ * to be allocated, and the second to actually populate every
+ * element.
+ *
+ * @param is interpreter state (supposedly having the
+ * current CMD pointing at a "history" CMD).
+ * @param[out] rh history array to initialize.
+ *
+ * @return number of entries in @a rh.
+ */
+static uint64_t
+build_history (struct TALER_TESTING_Interpreter *is,
+ struct History **rh)
+{
+ struct HistoryState *hs = is->commands[is->ip].cls;
+ uint64_t total;
+ struct History *h;
+ const struct TALER_TESTING_Command *add_incoming_cmd;
+ int inc;
+ unsigned int start;
+ unsigned int end;
+
+ /**
+ * @var turns GNUNET_YES whenever either no 'start' value was
+ * given for the history query, or the given value is found
+ * in the list of all the CMDs.
+ */int ok;
+ const uint64_t *row_id_start = NULL;
+
+ if (NULL != hs->start_row_reference)
+ {
+ TALER_LOG_INFO
+ ("`%s': start row given via reference `%s'\n",
+ TALER_TESTING_interpreter_get_current_label (is),
+ hs->start_row_reference);
+ add_incoming_cmd = TALER_TESTING_interpreter_lookup_command
+ (is, hs->start_row_reference);
+ GNUNET_assert (NULL != add_incoming_cmd);
+ GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_uint64
+ (add_incoming_cmd, 0, &row_id_start));
+ }
+
+ GNUNET_assert (0 != hs->num_results);
+ if (0 == is->ip)
+ {
+ TALER_LOG_DEBUG ("Checking history at first CMD..\n");
+ *rh = NULL;
+ return 0;
+ }
+
+ /* AKA 'delta'. */
+ if (hs->num_results > 0)
+ {
+ inc = 1; /* _inc_rement */
+ start = 0;
+ end = is->ip - 1;
+ }
+ else
+ {
+ inc = -1;
+ start = is->ip - 1;
+ end = 0;
+ }
+
+ total = 0;
+ ok = GNUNET_NO;
+
+ if (NULL == row_id_start)
+ ok = GNUNET_YES;
+
+ /* This loop counts how many commands _later than "start"_ belong
+ * to the history of the caller. This is stored in the @var total
+ * variable. */
+ for (unsigned int off = start; off != end + inc; off += inc)
+ {
+ const struct TALER_TESTING_Command *pos = &is->commands[off];
+ const uint64_t *row_id;
+ const char *debit_account;
+ const char *credit_account;
+
+ /**
+ * The following command allows us to skip over those CMDs
+ * that do not offer a "row_id" trait. Such skipped CMDs are
+ * not interesting for building a history.
+ */if (GNUNET_OK != TALER_TESTING_get_trait_uint64 (pos,
+ 0,
+ &row_id))
+ continue;
+
+ /* Seek "/history" starting row. */
+ if (NULL != row_id_start)
+ {
+ if (*row_id_start == *row_id)
+ {
+ /* Doesn't count, start is excluded from output. */
+ total = 0;
+ ok = GNUNET_YES;
+ continue;
+ }
+ }
+
+ /* when 'start' was _not_ given, then ok == GNUNET_YES */
+ if (GNUNET_NO == ok)
+ continue; /* skip until we find the marker */
+
+ TALER_LOG_DEBUG ("Found first row\n");
+
+ if (build_history_hit_limit (total,
+ hs,
+ pos))
+ {
+ TALER_LOG_DEBUG ("Hit history limit\n");
+ break;
+ }
+
+ GNUNET_assert
+ (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT
+ (pos, &debit_account));
+
+ GNUNET_assert
+ (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT
+ (pos, &credit_account));
+
+ TALER_LOG_INFO ("Potential history element:"
+ " %s->%s; my account: %s\n",
+ debit_account,
+ credit_account,
+ hs->account_url);
+
+ if (0 == strcasecmp (hs->account_url,
+ debit_account))
+ {
+ TALER_LOG_INFO ("+1 my history\n");
+ total++; /* found matching record */
+ }
+ }
+
+ GNUNET_assert (GNUNET_YES == ok);
+
+ if (0 == total)
+ {
+ TALER_LOG_DEBUG ("Checking history at first CMD.. (2)\n");
+ *rh = NULL;
+ return 0;
+ }
+
+
+ GNUNET_assert (total < UINT_MAX);
+ h = GNUNET_new_array ((unsigned int) total,
+ struct History);
+ total = 0;
+ ok = GNUNET_NO;
+ if (NULL == row_id_start)
+ ok = GNUNET_YES;
+
+ /**
+ * This loop _only_ populates the array of history elements.
+ */
+ for (unsigned int off = start; off != end + inc; off += inc)
+ {
+ const struct TALER_TESTING_Command *pos = &is->commands[off];
+ const uint64_t *row_id;
+ char *bank_hostname;
+ const char *credit_account;
+ const char *debit_account;
+
+ if (GNUNET_OK != TALER_TESTING_GET_TRAIT_ROW_ID
+ (pos, &row_id))
+ continue;
+
+ if (NULL != row_id_start)
+ {
+
+ if (*row_id_start == *row_id)
+ {
+ /**
+ * Warning: this zeroing is superfluous, as
+ * total doesn't get incremented if 'start'
+ * was given and couldn't be found.
+ */total = 0;
+ ok = GNUNET_YES;
+ continue;
+ }
+ }
+
+ TALER_LOG_INFO ("Found first row (2)\n");
+
+ if (GNUNET_NO == ok)
+ {
+ TALER_LOG_INFO ("Skip on `%s'\n",
+ pos->label);
+ continue; /* skip until we find the marker */
+ }
+
+ if (build_history_hit_limit (total,
+ hs,
+ pos))
+ {
+ TALER_LOG_INFO ("Hit history limit (2)\n");
+ break;
+ }
+
+ GNUNET_assert
+ (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT
+ (pos, &debit_account));
+
+ GNUNET_assert
+ (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT
+ (pos, &credit_account));
+
+ TALER_LOG_INFO ("Potential history bit:"
+ " %s->%s; my account: %s\n",
+ debit_account,
+ credit_account,
+ hs->account_url);
+
+ /**
+ * Discard transactions where the audited account played
+ * _both_ the debit and the debit roles, but _only if_
+ * the audit goes on both directions.. This needs more
+ * explaination!
+ */if (0 == strcasecmp (hs->account_url,
+ debit_account))
+ {
+ GNUNET_break (0);
+ continue;
+ }
+
+ bank_hostname = strchr (hs->account_url, ':');
+ GNUNET_assert (NULL != bank_hostname);
+ bank_hostname += 3;
+
+ /* Next two blocks only put the 'direction' and 'banking'
+ * information. */
+
+ /* Asked for debit, and account got the debit. */
+ if (0 == strcasecmp (hs->account_url,
+ debit_account))
+ {
+ h[total].url = GNUNET_strdup (credit_account);
+ h[total].details.account_url = h[total].url;
+ }
+
+ /* This block _completes_ the information of the current item,
+ * with amount / subject / exchange URL. */
+ if (0 == strcasecmp (hs->account_url,
+ debit_account))
+ {
+ const struct TALER_Amount *amount;
+ const struct TALER_WireTransferIdentifierRawP *wtid;
+ const char *account_url;
+
+ GNUNET_assert (GNUNET_OK ==
+ TALER_TESTING_get_trait_amount_obj
+ (pos, 0, &amount));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_TESTING_get_trait_wtid
+ (pos, 0, &wtid));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_TESTING_get_trait_url
+ (pos, 1,
+ &account_url));
+ h[total].details.amount = *amount;
+ h[total].row_id = *row_id;
+ h[total].details.wtid = *wtid;
+ h[total].details.account_url = account_url;
+ TALER_LOG_INFO ("+1-bit of my history\n");
+ total++;
+ }
+ }
+ *rh = h;
+ return total;
+}
+
+
+/**
+ * Compute how many results we expect to be returned for
+ * the current command at @a is.
+ *
+ * @param is the interpreter state to inspect.
+ * @return number of results expected.
+ */
+static uint64_t
+compute_result_count (struct TALER_TESTING_Interpreter *is)
+{
+ uint64_t total;
+ struct History *h;
+
+ total = build_history (is, &h);
+ free_history (h, total);
+ return total;
+}
+
+
+/**
+ * Check that the "/history" response matches the
+ * CMD whose offset in the list of CMDs is @a off.
+ *
+ * @param is the interpreter state.
+ * @param off the offset (of the CMD list) where the command
+ * to check is.
+ * @param dir the expected direction of the transaction.
+ * @param details the expected transaction details.
+ *
+ * @return #GNUNET_OK if the transaction is what we expect.
+ */
+static int
+check_result (struct TALER_TESTING_Interpreter *is,
+ unsigned int off,
+ const struct TALER_BANK_DebitDetails *details)
+{
+ uint64_t total;
+ struct History *h;
+
+ total = build_history (is, &h);
+ if (off >= total)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Test says history has at most %u"
+ " results, but got result #%u to check\n",
+ (unsigned int) total,
+ off);
+ print_expected (h,
+ total,
+ off);
+ return GNUNET_SYSERR;
+ }
+ if ( (0 != GNUNET_memcmp (&h[off].details.wtid,
+ &details->wtid)) ||
+ (0 != TALER_amount_cmp (&h[off].details.amount,
+ &details->amount)) ||
+ (0 != strcasecmp (h[off].details.account_url,
+ details->account_url)) )
+ {
+ GNUNET_break (0);
+ print_expected (h,
+ total,
+ off);
+ free_history (h,
+ total);
+ return GNUNET_SYSERR;
+ }
+ free_history (h,
+ total);
+ return GNUNET_OK;
+}
+
+
+/**
+ * This callback will (1) check that the HTTP response code
+ * is acceptable and (2) that the history is consistent. The
+ * consistency is checked by going through all the past CMDs,
+ * reconstructing then the expected history as of those, and
+ * finally check it against what the bank returned.
+ *
+ * @param cls closure.
+ * @param http_status HTTP response code, #MHD_HTTP_OK (200)
+ * for successful status request 0 if the bank's reply is
+ * bogus (fails to follow the protocol),
+ * #MHD_HTTP_NO_CONTENT if there are no more results; on
+ * success the last callback is always of this status
+ * (even if `abs(num_results)` were already returned).
+ * @param ec taler status code.
+ * @param dir direction of the transfer.
+ * @param row_id monotonically increasing counter corresponding to
+ * the transaction.
+ * @param details details about the wire transfer.
+ * @param json detailed response from the HTTPD, or NULL if
+ * reply was not in JSON.
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
+ */
+static int
+history_cb (void *cls,
+ unsigned int http_status,
+ enum TALER_ErrorCode ec,
+ uint64_t row_id,
+ const struct TALER_BANK_DebitDetails *details,
+ const json_t *json)
+{
+ struct TALER_TESTING_Interpreter *is = cls;
+ struct HistoryState *hs = is->commands[is->ip].cls;
+
+ (void) row_id;
+ if (MHD_HTTP_OK != http_status)
+ {
+ hs->hh = NULL;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unwanted response code from /history: %u\n",
+ http_status);
+ TALER_TESTING_interpreter_fail (is);
+ return GNUNET_SYSERR;
+ }
+ if (NULL == details)
+ {
+ hs->hh = NULL;
+ if ( (hs->results_obtained != compute_result_count (is)) ||
+ (GNUNET_YES == hs->failed) )
+ {
+ uint64_t total;
+ struct History *h;
+
+ GNUNET_break (0);
+ total = build_history (is, &h);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected history of length %llu, got %llu;"
+ " HTTP status code: %u/%d, failed: %d\n",
+ (unsigned long long) total,
+ (unsigned long long) hs->results_obtained,
+ http_status,
+ (int) ec,
+ hs->failed);
+ print_expected (h,
+ total,
+ UINT_MAX);
+ free_history (h,
+ total);
+ TALER_TESTING_interpreter_fail (is);
+ return GNUNET_SYSERR;
+ }
+ TALER_TESTING_interpreter_next (is);
+ return GNUNET_OK;
+ }
+
+ /* check current element */
+ if (GNUNET_OK != check_result (is,
+ hs->results_obtained,
+ details))
+ {
+ char *acc;
+
+ GNUNET_break (0);
+ acc = json_dumps (json,
+ JSON_COMPACT);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Result %u was `%s'\n",
+ (unsigned int) hs->results_obtained++,
+ acc);
+ if (NULL != acc)
+ free (acc);
+ hs->failed = GNUNET_YES;
+ return GNUNET_SYSERR;
+ }
+ hs->results_obtained++;
+ return GNUNET_OK;
+}
+
+
+/**
+ * Run the command.
+ *
+ * @param cls closure.
+ * @param cmd the command to execute.
+ * @param is the interpreter state.
+ */
+static void
+history_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct HistoryState *hs = cls;
+ uint64_t row_id = (hs->num_results > 0) ? 0 : UINT64_MAX;
+ const uint64_t *row_ptr;
+
+ (void) cmd;
+ /* Get row_id from trait. */
+ if (NULL != hs->start_row_reference)
+ {
+ const struct TALER_TESTING_Command *history_cmd;
+
+ history_cmd = TALER_TESTING_interpreter_lookup_command
+ (is, hs->start_row_reference);
+
+ if (NULL == history_cmd)
+ TALER_TESTING_FAIL (is);
+
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_uint64 (history_cmd,
+ 0,
+ &row_ptr))
+ TALER_TESTING_FAIL (is);
+ else
+ row_id = *row_ptr;
+ TALER_LOG_DEBUG ("row id (from trait) is %llu\n",
+ (unsigned long long) row_id);
+ }
+
+ hs->hh = TALER_BANK_debit_history (is->ctx,
+ hs->account_url,
+ NULL,
+ row_id,
+ hs->num_results,
+ &history_cb,
+ is);
+ GNUNET_assert (NULL != hs->hh);
+}
+
+
+/**
+ * Free the state from a "history" CMD, and possibly cancel
+ * a pending operation thereof.
+ *
+ * @param cls closure.
+ * @param cmd the command which is being cleaned up.
+ */
+static void
+history_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct HistoryState *hs = cls;
+
+ (void) cmd;
+ if (NULL != hs->hh)
+ {
+ TALER_LOG_WARNING ("/history did not complete\n");
+ TALER_BANK_debit_history_cancel (hs->hh);
+ }
+ GNUNET_free (hs);
+}
+
+
+/**
+ * Make a "history" CMD.
+ *
+ * @param label command label.
+ * @param account_url base URL of the account offering the "history"
+ * operation.
+ * @param start_row_reference reference to a command that can
+ * offer a row identifier, to be used as the starting row
+ * to accept in the result.
+ * @param num_results how many rows we want in the result.
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_bank_debits (const char *label,
+ const char *account_url,
+ const char *start_row_reference,
+ long long num_results)
+{
+ struct HistoryState *hs;
+
+ hs = GNUNET_new (struct HistoryState);
+ hs->account_url = account_url;
+ hs->start_row_reference = start_row_reference;
+ hs->num_results = num_results;
+
+ {
+ struct TALER_TESTING_Command cmd = {
+ .label = label,
+ .cls = hs,
+ .run = &history_run,
+ .cleanup = &history_cleanup,
+ .traits = &history_traits
+ };
+
+ return cmd;
+ }
+}
+
+
+/* end of testing_api_cmd_history_debit.c */
diff --git a/src/bank-lib/testing_api_cmd_reject.c b/src/bank-lib/testing_api_cmd_reject.c
deleted file mode 100644
index 01c189f1..00000000
--- a/src/bank-lib/testing_api_cmd_reject.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 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/testing_api_cmd_reject.c
- * @brief command to check the /reject API from the bank.
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_exchange_service.h"
-#include "taler_testing_lib.h"
-#include "taler_fakebank_lib.h"
-#include "taler_bank_service.h"
-#include "taler_fakebank_lib.h"
-
-
-/**
- * State for a "reject" CMD.
- */
-struct RejectState
-{
-
- /**
- * Handle of a ongoing "reject" operation.
- */
- struct TALER_BANK_RejectHandle *rh;
-
- /**
- * Reference to any command that can offer a wire
- * transfer "row id" and its credit account so as
- * to give input data to the "reject" operation.
- */
- const char *deposit_reference;
-
- /**
- * Base URL of the bank implementing the "reject"
- * operation.
- */
- const char *bank_url;
-};
-
-/**
- * Check that the response code from the "reject" opetation
- * is acceptable, namely it equals "204 No Content".
- *
- * @param cls closure.
- * @param http_status HTTP response code.
- * @param ec taler-specific error code.
- */
-static void
-reject_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec)
-{
- struct TALER_TESTING_Interpreter *is = cls;
- struct RejectState *rs = is->commands[is->ip].cls;
-
- rs->rh = NULL;
- if (MHD_HTTP_NO_CONTENT != http_status)
- {
- GNUNET_break (0);
- fprintf (stderr,
- "Unexpected response code %u/%d\n",
- http_status,
- (int) ec);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Cleanup the state of a "reject" CMD, and possibly
- * cancel a pending operation thereof.
- *
- * @param cls closure.
- * @param cmd the command.
- */
-static void
-reject_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct RejectState *rs = cls;
-
- (void) cmd;
- if (NULL != rs->rh)
- {
- TALER_LOG_WARNING ("/reject did not complete\n");
- TALER_BANK_reject_cancel (rs->rh);
- }
- GNUNET_free (rs);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-reject_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct RejectState *rs = cls;
- const struct TALER_TESTING_Command *deposit_cmd;
- const uint64_t *credit_account;
- const uint64_t *row_id;
- extern struct TALER_BANK_AuthenticationData AUTHS[];
-
- (void) cmd;
- deposit_cmd
- = TALER_TESTING_interpreter_lookup_command (is,
- rs->deposit_reference);
- if (NULL == deposit_cmd)
- TALER_TESTING_FAIL (is);
- GNUNET_assert (GNUNET_OK ==
- TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT (deposit_cmd,
- &credit_account));
- GNUNET_assert (GNUNET_OK ==
- TALER_TESTING_GET_TRAIT_ROW_ID (deposit_cmd,
- &row_id));
- TALER_LOG_INFO ("Account %llu rejects deposit\n",
- (unsigned long long) *credit_account);
- rs->rh = TALER_BANK_reject (is->ctx,
- rs->bank_url,
- &AUTHS[*credit_account - 1],
- *credit_account,
- *row_id,
- &reject_cb,
- is);
- GNUNET_assert (NULL != rs->rh);
-}
-
-
-/**
- * Offer internal data from a "reject" CMD to other commands.
- *
- * @param cls closure.
- * @param ret[out] result.
- * @param trait name of the trait.
- * @param index index number of the trait to return.
- *
- * @return #GNUNET_OK on success.
- */
-static int
-reject_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct RejectState *rs = cls;
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_rejected (0, rs->deposit_reference),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Create a "reject" CMD.
- *
- * @param label command label.
- * @param bank_url base URL of the bank implementing the
- * "reject" operation.
- * @param deposit_reference reference to a command that will
- * provide a "row id" and credit (bank) account to craft
- * the "reject" request.
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_bank_reject (const char *label,
- const char *bank_url,
- const char *deposit_reference)
-{
- struct RejectState *rs;
-
- rs = GNUNET_new (struct RejectState);
- rs->bank_url = bank_url;
- rs->deposit_reference = deposit_reference;
-
- {
- struct TALER_TESTING_Command cmd = {
- .cls = rs,
- .run = &reject_run,
- .cleanup = &reject_cleanup,
- .label = label,
- .traits = &reject_traits
- };
-
- return cmd;
- }
-}
-
-
-/* end of testing_api_cmd_reject.c */
diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c
index 31dbdf15..b931c3c9 100644
--- a/src/benchmark/taler-exchange-benchmark.c
+++ b/src/benchmark/taler-exchange-benchmark.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2014-2019 Taler Systems SA
+ (C) 2014-2020 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
@@ -16,15 +16,13 @@
along with TALER; see the file COPYING. If not,
see <http://www.gnu.org/licenses/>
*/
-
/**
- * @file merchant/backend/taler-merchant-httpd.c
+ * @file benchmark/taler-exchange-benchmark.c
* @brief HTTP serving layer intended to perform crypto-work and
* communication with the exchange
* @author Marcello Stanisci
* @author Christian Grothoff
*/
-
#include "platform.h"
#include <gnunet/gnunet_util_lib.h>
#include <microhttpd.h>
@@ -58,23 +56,14 @@ enum BenchmarkError
*/
#define UNITY_SIZE 6
-/**
- * Account number of the merchant. Fakebank likes any number,
- * the only requirement is that this number then matches the
- * number given when building payto URLs at deposit time.
- */
-#define TALER_TESTING_USER_ACCOUNT_NUMBER 3
-
#define FIRST_INSTRUCTION -1
#define CMD_TRANSFER_TO_EXCHANGE(label, amount) \
TALER_TESTING_cmd_fakebank_transfer_retry \
(TALER_TESTING_cmd_fakebank_transfer (label, amount, \
- exchange_bank_account.details. \
- x_taler_bank.bank_base_url, \
- TALER_TESTING_USER_ACCOUNT_NUMBER, \
- exchange_bank_account.details. \
- x_taler_bank.no, \
+ user_bank_account.details. \
+ x_taler_bank.account_base_url, \
+ exchange_payto_url, \
"dummy_user", \
"dummy_password", \
"http://example.com/"))
@@ -108,6 +97,11 @@ enum BenchmarkMode
static struct TALER_Account exchange_bank_account;
/**
+ * Hold information about a user at the bank.
+ */
+static struct TALER_Account user_bank_account;
+
+/**
* Time snapshot taken right before executing the CMDs.
*/
static struct GNUNET_TIME_Absolute start_time;
@@ -169,6 +163,11 @@ static enum BenchmarkMode mode;
static char *cfg_filename;
/**
+ * payto://-URL of the exchange's bank account.
+ */
+static char *exchange_payto_url;
+
+/**
* Currency used.
*/
static char *currency;
@@ -405,12 +404,12 @@ stop_fakebank (void *cls)
static void
launch_fakebank (void *cls)
{
- const char *bank_base_url = cls;
+ const char *hostname = cls;
const char *port;
long pnum;
struct TALER_FAKEBANK_Handle *fakebank;
- port = strrchr (bank_base_url,
+ port = strrchr (hostname,
(unsigned char) ':');
if (NULL == port)
pnum = 80;
@@ -419,7 +418,7 @@ launch_fakebank (void *cls)
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Starting Fakebank on port %u (%s)\n",
(unsigned int) pnum,
- bank_base_url);
+ hostname);
fakebank = TALER_FAKEBANK_start ((uint16_t) pnum);
if (NULL == fakebank)
{
@@ -466,8 +465,7 @@ parallel_benchmark (TALER_TESTING_Main main_cb,
NULL == loglev ? "INFO" : loglev,
logfile);
GNUNET_SCHEDULER_run (&launch_fakebank,
- exchange_bank_account.details.x_taler_bank.
- bank_base_url);
+ exchange_bank_account.details.x_taler_bank.hostname);
exit (0);
}
if (-1 == fakebank)
@@ -824,10 +822,36 @@ main (int argc,
return BAD_CLI_ARG;
}
+ {
+ char *user_payto_url;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string
+ (cfg,
+ "benchmark",
+ "user-url",
+ &user_payto_url))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "benchmark",
+ "user-url");
+ return BAD_CONFIG_FILE;
+ }
+ if (TALER_EC_NONE !=
+ TALER_WIRE_payto_to_account (user_payto_url,
+ &user_bank_account))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _ ("Malformed payto:// URL `%s' in configuration\n"),
+ user_payto_url);
+ GNUNET_free (user_payto_url);
+ return BAD_CONFIG_FILE;
+ }
+ GNUNET_free (user_payto_url);
+ }
{
const char *bank_details_section;
- char *exchange_payto_url;
GNUNET_CONFIGURATION_iterate_sections
(cfg,
@@ -873,7 +897,6 @@ main (int argc,
GNUNET_free (exchange_payto_url);
return BAD_CONFIG_FILE;
}
- GNUNET_free (exchange_payto_url);
}
if ( (MODE_EXCHANGE == mode) || (MODE_BOTH == mode) )
{
diff --git a/src/exchange-tools/Makefile.am b/src/exchange-tools/Makefile.am
index 64b4cee8..0b9a2d52 100644
--- a/src/exchange-tools/Makefile.am
+++ b/src/exchange-tools/Makefile.am
@@ -23,7 +23,9 @@ taler_wire_SOURCES = \
taler-wire.c
taler_wire_LDADD = \
$(top_builddir)/src/util/libtalerutil.la \
+ $(top_builddir)/src/bank-lib/libtalerbank.la \
$(top_builddir)/src/wire/libtalerwire.la \
+ -lgnunetcurl \
-lgnunetutil
taler_exchange_keyup_SOURCES = \
@@ -32,6 +34,7 @@ taler_exchange_keyup_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/util/libtalerutil.la \
$(top_builddir)/src/pq/libtalerpq.la \
+ $(top_builddir)/src/bank-lib/libtalerbank.la \
$(top_builddir)/src/wire/libtalerwire.la \
$(top_builddir)/src/exchangedb/libtalerexchangedb.la \
-lgnunetutil $(XLIB)
@@ -44,6 +47,7 @@ taler_exchange_wire_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/json/libtalerjson.la \
$(top_builddir)/src/exchangedb/libtalerexchangedb.la \
+ $(top_builddir)/src/bank-lib/libtalerbank.la \
$(top_builddir)/src/wire/libtalerwire.la \
$(top_builddir)/src/util/libtalerutil.la \
-lgnunetjson \
diff --git a/src/exchange-tools/taler-exchange-keyup.c b/src/exchange-tools/taler-exchange-keyup.c
index e6e3db0d..f2ec3ca8 100644
--- a/src/exchange-tools/taler-exchange-keyup.c
+++ b/src/exchange-tools/taler-exchange-keyup.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
+ Copyright (C) 2014-2020 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
@@ -923,17 +923,17 @@ exchange_keys_update_denomkeys ()
* Sign @a af with @a priv
*
* @param[in,out] af fee structure to sign
- * @param wireplugin name of the plugin for which we sign
+ * @param method name of the wire method for which we sign
* @param priv private key to use for signing
*/
static void
sign_af (struct TALER_EXCHANGEDB_AggregateFees *af,
- const char *wireplugin,
+ const char *method,
const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
{
struct TALER_MasterWireFeePS wf;
- TALER_EXCHANGEDB_fees_2_wf (wireplugin,
+ TALER_EXCHANGEDB_fees_2_wf (method,
af,
&wf);
GNUNET_assert (GNUNET_OK ==
@@ -1101,28 +1101,15 @@ create_wire_fee_by_account (void *cls,
const struct TALER_EXCHANGEDB_AccountInfo *ai)
{
int *ret = cls;
- struct TALER_WIRE_Plugin *plugin;
if (GNUNET_NO == ai->credit_enabled)
return;
- plugin = TALER_WIRE_plugin_load (kcfg,
- ai->plugin_name);
- if (NULL == plugin)
- {
- fprintf (stderr,
- "Failed to load wire plugin `%s' configured for account `%s'\n",
- ai->plugin_name,
- ai->section_name);
- *ret = GNUNET_SYSERR;
- return;
- }
/* We may call this function repeatedly for the same method
if there are multiple accounts with plugins using the
same method, but except for some minor performance loss,
this is harmless. */
create_wire_fee_for_method (ret,
- plugin->method);
- TALER_WIRE_plugin_unload (plugin);
+ ai->method);
}
diff --git a/src/exchange-tools/taler-wire.c b/src/exchange-tools/taler-wire.c
index 12963324..5e3c18a6 100644
--- a/src/exchange-tools/taler-wire.c
+++ b/src/exchange-tools/taler-wire.c
@@ -22,11 +22,10 @@
* @author Marcello Stanisci
* @author Christian Grothoff
*/
-
#include <platform.h>
#include <gnunet/gnunet_util_lib.h>
#include "taler_util.h"
-#include "taler_wire_lib.h"
+#include "taler_bank_service.h"
/**
* If set to #GNUNET_YES, then we'll ask the bank for a list
@@ -36,17 +35,12 @@
static int history;
/**
- * If set to GNUNET_YES, then we'll ask the bank to execute a
+ * If set to #GNUNET_YES, then we'll ask the bank to execute a
* wire transfer.
*/
static int transfer;
/**
- * Name of the wire plugin to use with the bank.
- */
-static char *plugin_name;
-
-/**
* Global return code.
*/
static unsigned int global_ret = 1;
@@ -59,11 +53,9 @@ static unsigned int global_ret = 1;
static char *amount;
/**
- * Base32 encoding of a transaction ID. When asking the
- * bank for a transaction history, all the results will
- * have a transaction ID settled *after* this one.
+ * Starting row.
*/
-static char *since_when;
+static unsigned long long start_row;
/**
* Which config section has the credentials to access the bank.
@@ -77,19 +69,29 @@ static char *account_section;
static char *destination_account_url;
/**
- * Handle for the wire transfer preparation task.
+ * Handle for executing the wire transfer.
*/
-static struct TALER_WIRE_PrepareHandle *ph;
+static struct TALER_BANK_WireExecuteHandle *eh;
/**
- * Wire plugin handle.
+ * Handle to ongoing history operation.
*/
-static struct TALER_WIRE_Plugin *plugin_handle;
+static struct TALER_BANK_CreditHistoryHandle *hh;
/**
- * Handle to ongoing history operation.
+ * For authentication.
+ */
+static struct TALER_BANK_AuthenticationData auth;
+
+/**
+ * Handle to the context for interacting with the bank.
*/
-static struct TALER_WIRE_HistoryHandle *hh;
+static struct GNUNET_CURL_Context *ctx;
+
+/**
+ * Scheduler context for running the @e ctx.
+ */
+static struct GNUNET_CURL_RescheduleContext *rc;
/**
@@ -108,16 +110,16 @@ static struct TALER_WIRE_HistoryHandle *hh;
*/
static int
history_cb (void *cls,
+ unsigned int http_status,
enum TALER_ErrorCode ec,
- enum TALER_BANK_Direction dir,
- const void *row_off,
- size_t row_off_size,
- const struct TALER_WIRE_TransferDetails *details)
+ uint64_t serial_id,
+ const struct TALER_BANK_CreditDetails *details,
+ const json_t *json)
{
- char *row_off_enc;
-
(void) cls;
- if (TALER_BANK_DIRECTION_NONE == dir)
+ (void) ec;
+ (void) http_status;
+ if (NULL == details)
{
fprintf (stdout,
"End of transactions list.\n");
@@ -126,15 +128,9 @@ history_cb (void *cls,
return GNUNET_NO;
}
- row_off_enc = GNUNET_STRINGS_data_to_string_alloc (row_off,
- row_off_size);
- /* Give more details on screen (??) */
fprintf (stdout,
- "%s\n",
- row_off_enc);
-
- GNUNET_free (row_off_enc);
-
+ "%llu\n",
+ (unsigned long long) serial_id);
return GNUNET_OK;
}
@@ -142,72 +138,37 @@ history_cb (void *cls,
/**
* Callback that processes the outcome of a wire transfer
* execution.
+ *
+ * @param cls closure
+ * @param response_code HTTP status code
+ * @param ec taler error code
+ * @param row_id unique ID of the wire transfer in the bank's records
+ * @param timestamp when did the transaction go into effect
*/
static void
confirmation_cb (void *cls,
- int success,
- const void *row_id,
- size_t row_id_size,
- const char *emsg)
+ unsigned int response_code,
+ enum TALER_ErrorCode ec,
+ uint64_t row_id,
+ struct GNUNET_TIME_Absolute timestamp)
{
- if (GNUNET_YES != success)
+ if (MHD_HTTP_OK != response_code)
{
fprintf (stderr,
- "The wire transfer didn't execute correctly.\n");
- GNUNET_assert (NULL != emsg);
- fprintf (stderr,
- "%s",
- emsg);
+ "The wire transfer didn't execute correctly (%d).\n",
+ ec);
GNUNET_SCHEDULER_shutdown ();
return;
}
fprintf (stdout,
"Wire transfer executed successfully.\n");
-
global_ret = 0;
GNUNET_SCHEDULER_shutdown ();
}
/**
- * Takes prepared blob and executes the wire-transfer.
- *
- * @param cls NULL.
- * @param buf prepared wire transfer data.
- * @param buf_size size of the prepared wire transfer data.
- */
-static void
-prepare_cb (void *cls,
- const char *buf,
- size_t buf_size)
-{
- struct TALER_WIRE_ExecuteHandle *eh;
-
- if (NULL == (eh = plugin_handle->execute_wire_transfer
- (plugin_handle->cls,
- buf,
- buf_size,
- confirmation_cb,
- NULL)))
- {
- fprintf (stderr,
- "Could not execute the wire transfer\n");
-
- plugin_handle->prepare_wire_transfer_cancel
- (plugin_handle->cls,
- ph);
-
- plugin_handle->execute_wire_transfer_cancel
- (plugin_handle->cls,
- eh);
-
- GNUNET_SCHEDULER_shutdown ();
- }
-}
-
-
-/**
* Ask the bank to execute a wire transfer.
*/
static void
@@ -215,6 +176,8 @@ execute_wire_transfer ()
{
struct TALER_Amount a;
struct TALER_WireTransferIdentifierRawP wtid;
+ void *buf;
+ size_t buf_size;
if (NULL == amount)
{
@@ -223,7 +186,6 @@ execute_wire_transfer ()
GNUNET_SCHEDULER_shutdown ();
return;
}
-
if (GNUNET_OK != TALER_string_to_amount (amount,
&a))
{
@@ -240,19 +202,25 @@ execute_wire_transfer ()
GNUNET_SCHEDULER_shutdown ();
return;
}
- if (NULL == (ph = plugin_handle->prepare_wire_transfer
- (plugin_handle->cls,
- account_section,
- destination_account_url,
- &a,
- "http://exchange.example.com/",
- &wtid, /* Any value will do. */
- prepare_cb,
- NULL)))
+ TALER_BANK_prepare_wire_transfer (destination_account_url,
+ &a,
+ "http://exchange.example.com/",
+ &wtid,
+ &buf,
+ &buf_size);
+ eh = TALER_BANK_execute_wire_transfer (ctx,
+ destination_account_url,
+ &auth,
+ buf,
+ buf_size,
+ &confirmation_cb,
+ NULL);
+ if (NULL == eh)
{
fprintf (stderr,
- "Could not prepare the wire transfer\n");
+ "Could not execute the wire transfer\n");
GNUNET_SCHEDULER_shutdown ();
+ return;
}
}
@@ -264,30 +232,14 @@ execute_wire_transfer ()
static void
execute_history ()
{
- size_t bin_len = 0;
- void *since_when_bin = NULL;
-
- if (NULL != since_when)
- {
- bin_len = (strlen (since_when) * 5) / 8;
-
- since_when_bin = GNUNET_malloc (bin_len);
- GNUNET_assert
- (GNUNET_OK == GNUNET_STRINGS_string_to_data
- (since_when,
- strlen (since_when),
- since_when_bin,
- bin_len));
- }
-
- if (NULL == (hh = plugin_handle->get_history (plugin_handle->cls,
- account_section,
- TALER_BANK_DIRECTION_BOTH,
- since_when_bin,
- bin_len,
- -10,
- &history_cb,
- NULL)))
+ hh = TALER_BANK_credit_history (ctx,
+ destination_account_url,
+ &auth,
+ start_row,
+ -10,
+ &history_cb,
+ NULL);
+ if (NULL == hh)
{
fprintf (stderr,
"Could not request the transaction history.\n");
@@ -305,19 +257,27 @@ execute_history ()
static void
do_shutdown (void *cls)
{
+ if (NULL != ctx)
+ {
+ GNUNET_CURL_fini (ctx);
+ ctx = NULL;
+ }
+ if (NULL != rc)
+ {
+ GNUNET_CURL_gnunet_rc_destroy (rc);
+ rc = NULL;
+ }
if (NULL != hh)
{
- plugin_handle->get_history_cancel (plugin_handle->cls,
- hh);
+ TALER_BANK_credit_history_cancel (hh);
hh = NULL;
}
- if (NULL != ph)
+ if (NULL != eh)
{
- plugin_handle->prepare_wire_transfer_cancel (plugin_handle->cls,
- ph);
- ph = NULL;
+ TALER_BANK_execute_wire_transfer_cancel (eh);
+ eh = NULL;
}
- TALER_WIRE_plugin_unload (plugin_handle);
+ TALER_BANK_auth_free (&auth);
}
@@ -342,27 +302,18 @@ run (void *cls,
"The option: -s ACCOUNT-SECTION, is mandatory.\n");
return;
}
-
- if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string
- (cfg,
- account_section,
- "plugin",
- &plugin_name))
+ if (GNUNET_OK !=
+ TALER_BANK_auth_parse_cfg (cfg,
+ account_section,
+ &auth))
{
fprintf (stderr,
- "Could not find the 'plugin' value under %s\n",
+ "Authentication information not found in configuration section `%s'\n",
account_section);
+ GNUNET_SCHEDULER_shutdown ();
return;
}
- plugin_handle = TALER_WIRE_plugin_load (cfg,
- plugin_name);
- if (NULL == plugin_handle)
- {
- fprintf (stderr,
- "Could not load the wire plugin\n");
- return;
- }
if (GNUNET_YES == history)
execute_history ();
@@ -372,6 +323,14 @@ run (void *cls,
fprintf (stderr,
"Please give either --history/-H or --transfer/t\n");
+ ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+ &rc);
+ rc = GNUNET_CURL_gnunet_rc_create (ctx);
+ if (NULL == ctx)
+ {
+ GNUNET_break (0);
+ return;
+ }
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
NULL);
}
@@ -400,22 +359,23 @@ main (int argc,
"transfer",
"Execute a wire transfer.",
&transfer),
- GNUNET_GETOPT_option_string ('w',
- "since-when",
- "SW",
- "When asking the bank for"
- " transactions history, this"
- " option commands that all the"
- " results should have IDs settled"
- " after SW. If not given, then"
- " the 10 youngest transactions"
- " are returned.",
- &since_when),
- GNUNET_GETOPT_option_string ('s',
- "section",
- "ACCOUNT-SECTION",
- "Which config section has the credentials to access the bank. Mandatory.\n",
- &account_section),
+ GNUNET_GETOPT_option_ulong ('w',
+ "since-when",
+ "SW",
+ "When asking the bank for"
+ " transactions history, this"
+ " option commands that all the"
+ " results should have IDs settled"
+ " after SW. If not given, then"
+ " the 10 youngest transactions"
+ " are returned.",
+ &start_row),
+ GNUNET_GETOPT_option_mandatory
+ (GNUNET_GETOPT_option_string ('s',
+ "section",
+ "ACCOUNT-SECTION",
+ "Which config section has the credentials to access the bank. Mandatory.\n",
+ &account_section)),
GNUNET_GETOPT_option_string ('a',
"amount",
"AMOUNT",
diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am
index 3453683a..b08c85c6 100644
--- a/src/exchange/Makefile.am
+++ b/src/exchange/Makefile.am
@@ -29,9 +29,11 @@ taler_exchange_aggregator_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/json/libtalerjson.la \
$(top_builddir)/src/util/libtalerutil.la \
+ $(top_builddir)/src/bank-lib/libtalerbank.la \
$(top_builddir)/src/wire/libtalerwire.la \
$(top_builddir)/src/exchangedb/libtalerexchangedb.la \
-ljansson \
+ -lgnunetcurl \
-lgnunetutil
taler_exchange_wirewatch_SOURCES = \
@@ -40,9 +42,11 @@ taler_exchange_wirewatch_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/json/libtalerjson.la \
$(top_builddir)/src/util/libtalerutil.la \
+ $(top_builddir)/src/bank-lib/libtalerbank.la \
$(top_builddir)/src/wire/libtalerwire.la \
$(top_builddir)/src/exchangedb/libtalerexchangedb.la \
-ljansson \
+ -lgnunetcurl \
-lgnunetutil
taler_exchange_httpd_SOURCES = \
@@ -66,6 +70,7 @@ taler_exchange_httpd_SOURCES = \
taler-exchange-httpd_validation.c taler-exchange-httpd_validation.h
taler_exchange_httpd_LDADD = \
$(LIBGCRYPT_LIBS) \
+ $(top_builddir)/src/bank-lib/libtalerbank.la \
$(top_builddir)/src/wire/libtalerwire.la \
$(top_builddir)/src/mhd/libtalermhd.la \
$(top_builddir)/src/json/libtalerjson.la \
diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c
index 71a3efd7..2704f591 100644
--- a/src/exchange/taler-exchange-aggregator.c
+++ b/src/exchange/taler-exchange-aggregator.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2016-2018 Taler Systems SA
+ Copyright (C) 2016-2020 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
@@ -26,6 +26,7 @@
#include "taler_exchangedb_lib.h"
#include "taler_exchangedb_plugin.h"
#include "taler_json_lib.h"
+#include "taler_bank_service.h"
#include "taler_wire_lib.h"
@@ -45,9 +46,14 @@ struct WireAccount
struct WireAccount *prev;
/**
- * Handle to the plugin.
+ * Account information.
*/
- struct TALER_WIRE_Plugin *wire_plugin;
+ struct TALER_Account account;
+
+ /**
+ * Authentication data.
+ */
+ struct TALER_BANK_AuthenticationData auth;
/**
* Wire transfer fee structure.
@@ -59,6 +65,11 @@ struct WireAccount
*/
char *section_name;
+ /**
+ * Name of the wire method underlying the account.
+ */
+ char *method;
+
};
@@ -77,7 +88,7 @@ struct WirePrepareData
/**
* Wire execution handle.
*/
- struct TALER_WIRE_ExecuteHandle *eh;
+ struct TALER_BANK_WireExecuteHandle *eh;
/**
* Wire plugin used for this preparation.
@@ -187,10 +198,6 @@ struct AggregationUnit
*/
struct CloseTransferContext
{
- /**
- * Handle for preparing the wire transfer.
- */
- struct TALER_WIRE_PrepareHandle *ph;
/**
* Our database session.
@@ -263,6 +270,16 @@ static struct WirePrepareData *wpd;
static struct AggregationUnit *au;
/**
+ * Handle to the context for interacting with the bank.
+ */
+static struct GNUNET_CURL_Context *ctx;
+
+/**
+ * Scheduler context for running the @e ctx.
+ */
+static struct GNUNET_CURL_RescheduleContext *rc;
+
+/**
* Value to return from main(). #GNUNET_OK on success, #GNUNET_SYSERR
* on serious errors.
*/
@@ -339,7 +356,7 @@ update_fees (struct WireAccount *wa,
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
/* Let's try to load it from disk... */
wa->af = TALER_EXCHANGEDB_fees_read (cfg,
- wa->wire_plugin->method);
+ wa->method);
advance_fees (wa,
now);
for (struct TALER_EXCHANGEDB_AggregateFees *p = wa->af;
@@ -348,7 +365,7 @@ update_fees (struct WireAccount *wa,
{
qs = db_plugin->insert_wire_fee (db_plugin->cls,
session,
- wa->wire_plugin->method,
+ wa->method,
p->start_date,
p->end_date,
&p->wire_fee,
@@ -365,7 +382,7 @@ update_fees (struct WireAccount *wa,
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to find current wire transfer fees for `%s'\n",
- wa->wire_plugin->method);
+ wa->method);
return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
}
@@ -381,7 +398,7 @@ find_account_by_method (const char *method)
{
for (struct WireAccount *wa = wa_head; NULL != wa; wa = wa->next)
if (0 == strcmp (method,
- wa->wire_plugin->method))
+ wa->method))
return wa;
return NULL;
}
@@ -431,13 +448,40 @@ add_account_cb (void *cls,
if (GNUNET_YES != ai->debit_enabled)
return; /* not enabled for us, skip */
wa = GNUNET_new (struct WireAccount);
- wa->wire_plugin = TALER_WIRE_plugin_load (cfg,
- ai->plugin_name);
- if (NULL == wa->wire_plugin)
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ ai->section_name,
+ "METHOD",
+ &wa->method))
{
- fprintf (stderr,
- "Failed to load wire plugin for `%s'\n",
- ai->plugin_name);
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ ai->section_name,
+ "METHOD");
+ GNUNET_free (wa);
+ return;
+ }
+ if (GNUNET_OK !=
+ TALER_BANK_auth_parse_cfg (cfg,
+ ai->section_name,
+ &wa->auth))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Failed to load account `%s'\n",
+ ai->section_name);
+ GNUNET_free (wa->method);
+ GNUNET_free (wa);
+ return;
+ }
+ if (GNUNET_OK !=
+ TALER_BANK_account_parse_cfg (cfg,
+ ai->section_name,
+ &wa->account))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Failed to load account `%s'\n",
+ ai->section_name);
+ TALER_BANK_auth_free (&wa->auth);
+ GNUNET_free (wa->method);
GNUNET_free (wa);
return;
}
@@ -476,6 +520,16 @@ static void
shutdown_task (void *cls)
{
(void) cls;
+ if (NULL != ctx)
+ {
+ GNUNET_CURL_fini (ctx);
+ ctx = NULL;
+ }
+ if (NULL != rc)
+ {
+ GNUNET_CURL_gnunet_rc_destroy (rc);
+ rc = NULL;
+ }
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Running shutdown\n");
if (NULL != task)
@@ -487,9 +541,7 @@ shutdown_task (void *cls)
{
if (NULL != wpd->eh)
{
- wpd->wa->wire_plugin->execute_wire_transfer_cancel (
- wpd->wa->wire_plugin->cls,
- wpd->eh);
+ TALER_BANK_execute_wire_transfer_cancel (wpd->eh);
wpd->eh = NULL;
}
db_plugin->rollback (db_plugin->cls,
@@ -499,23 +551,12 @@ shutdown_task (void *cls)
}
if (NULL != au)
{
- if (NULL != au->ph)
- {
- au->wa->wire_plugin->prepare_wire_transfer_cancel (
- au->wa->wire_plugin->cls,
- au->ph);
- au->ph = NULL;
- }
db_plugin->rollback (db_plugin->cls,
au->session);
cleanup_au ();
}
if (NULL != ctc)
{
- ctc->wa->wire_plugin->prepare_wire_transfer_cancel (
- ctc->wa->wire_plugin->cls,
- ctc->ph);
- ctc->ph = NULL;
db_plugin->rollback (db_plugin->cls,
ctc->session);
GNUNET_free (ctc->method);
@@ -532,9 +573,11 @@ shutdown_task (void *cls)
GNUNET_CONTAINER_DLL_remove (wa_head,
wa_tail,
wa);
- TALER_WIRE_plugin_unload (wa->wire_plugin);
+ TALER_WIRE_account_free (&wa->account);
+ TALER_BANK_auth_free (&wa->auth);
TALER_EXCHANGEDB_fees_free (wa->af);
GNUNET_free (wa->section_name);
+ GNUNET_free (wa->method);
GNUNET_free (wa);
}
}
@@ -922,20 +965,6 @@ aggregate_cb (void *cls,
/**
- * Function to be called with the prepared transfer data
- * when running an aggregation on a merchant.
- *
- * @param cls closure with the `struct AggregationUnit`
- * @param buf transaction data to persist, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-prepare_cb (void *cls,
- const char *buf,
- size_t buf_size);
-
-
-/**
* Main work function that finds and triggers transfers for reserves
* closures.
*
@@ -989,83 +1018,6 @@ commit_or_warn (struct TALER_EXCHANGEDB_Session *session)
/**
- * Function to be called with the prepared transfer data
- * when closing a reserve.
- *
- * @param cls closure with a `struct CloseTransferContext`
- * @param buf transaction data to persist, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-prepare_close_cb (void *cls,
- const char *buf,
- size_t buf_size)
-{
- enum GNUNET_DB_QueryStatus qs;
-
- GNUNET_assert (cls == ctc);
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Prepared for reserve closing\n");
- ctc->ph = NULL;
- if (NULL == buf)
- {
- GNUNET_break (0); /* why? how to best recover? */
- db_plugin->rollback (db_plugin->cls,
- ctc->session);
- /* start again */
- GNUNET_free (ctc->method);
- GNUNET_free (ctc);
- ctc = NULL;
- task = GNUNET_SCHEDULER_add_now (&run_aggregation,
- NULL);
- return;
- }
-
- /* Commit our intention to execute the wire transfer! */
- qs = db_plugin->wire_prepare_data_insert (db_plugin->cls,
- ctc->session,
- ctc->method,
- buf,
- buf_size);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- GNUNET_break (0);
- db_plugin->rollback (db_plugin->cls,
- ctc->session);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- GNUNET_free (ctc->method);
- GNUNET_free (ctc);
- ctc = NULL;
- return;
- }
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- {
- db_plugin->rollback (db_plugin->cls,
- ctc->session);
- /* start again */
- task = GNUNET_SCHEDULER_add_now (&run_aggregation,
- NULL);
- GNUNET_free (ctc->method);
- GNUNET_free (ctc);
- ctc = NULL;
- return;
- }
-
- /* finally commit */
- (void) commit_or_warn (ctc->session);
- GNUNET_free (ctc->method);
- GNUNET_free (ctc);
- ctc = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Reserve closure committed, running transfer\n");
- task = GNUNET_SCHEDULER_add_now (&run_transfers,
- NULL);
-}
-
-
-/**
* Closure for #expired_reserve_cb().
*/
struct ExpiredReserveContext
@@ -1113,6 +1065,8 @@ expired_reserve_cb (void *cls,
int ret;
enum GNUNET_DB_QueryStatus qs;
struct WireAccount *wa;
+ void *buf;
+ size_t buf_size;
/* NOTE: potential optimization: use custom SQL API to not
fetch this: */
@@ -1121,7 +1075,7 @@ expired_reserve_cb (void *cls,
now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now);
- /* lookup wire plugin */
+ /* lookup account we should use */
wa = find_account_by_url (account_details);
if (NULL == wa)
{
@@ -1161,6 +1115,18 @@ expired_reserve_cb (void *cls,
TALER_amount_get_zero (left->currency,
&amount_without_fee));
}
+ /* round down to enable transfer */
+ if (GNUNET_SYSERR ==
+ TALER_WIRE_amount_round (&amount_without_fee))
+ {
+ GNUNET_break (0);
+ global_ret = GNUNET_SYSERR;
+ GNUNET_SCHEDULER_shutdown ();
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if ( (0 == amount_without_fee.value) &&
+ (0 == amount_without_fee.fraction) )
+ ret = GNUNET_NO;
/* NOTE: sizeof (*reserve_pub) == sizeof (wtid) right now, but to
be future-compatible, we use the memset + min construction */
@@ -1171,61 +1137,23 @@ expired_reserve_cb (void *cls,
reserve_pub,
GNUNET_MIN (sizeof (wtid),
sizeof (*reserve_pub)));
-
- qs = db_plugin->insert_reserve_closed (db_plugin->cls,
- session,
- reserve_pub,
- now,
- account_details,
- &wtid,
- left,
- closing_fee);
-
+ if (GNUNET_SYSERR != ret)
+ qs = db_plugin->insert_reserve_closed (db_plugin->cls,
+ session,
+ reserve_pub,
+ now,
+ account_details,
+ &wtid,
+ left,
+ closing_fee);
+ else
+ ret = GNUNET_DB_STATUS_HARD_ERROR;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Closing reserve %s over %s (%d, %d)\n",
TALER_B2S (reserve_pub),
TALER_amount2s (left),
ret,
qs);
- if ( (GNUNET_OK == ret) &&
- (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) )
- {
- /* success, perform wire transfer */
- if (GNUNET_SYSERR ==
- wa->wire_plugin->amount_round (wa->wire_plugin->cls,
- &amount_without_fee))
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- ctc = GNUNET_new (struct CloseTransferContext);
- ctc->wa = wa;
- ctc->session = session;
- ctc->method = TALER_WIRE_payto_get_method (account_details);
- ctc->ph
- = wa->wire_plugin->prepare_wire_transfer (wa->wire_plugin->cls,
- wa->section_name,
- account_details,
- &amount_without_fee,
- exchange_base_url,
- &wtid,
- &prepare_close_cb,
- ctc);
- if (NULL == ctc->ph)
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- GNUNET_free (ctc->method);
- GNUNET_free (ctc);
- ctc = NULL;
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- erc->async_cont = GNUNET_YES;
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
/* Check for hard failure */
if ( (GNUNET_SYSERR == ret) ||
(GNUNET_DB_STATUS_HARD_ERROR == qs) )
@@ -1235,10 +1163,59 @@ expired_reserve_cb (void *cls,
GNUNET_SCHEDULER_shutdown ();
return GNUNET_DB_STATUS_HARD_ERROR;
}
- /* Reserve balance was almost zero OR soft error */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Reserve was virtually empty, moving on\n");
- return qs;
+ if ( (GNUNET_OK != ret) ||
+ (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) )
+ {
+ /* Reserve balance was almost zero OR soft error */
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Reserve was virtually empty, moving on\n");
+ (void) commit_or_warn (ctc->session);
+ GNUNET_free (ctc->method);
+ GNUNET_free (ctc);
+ ctc = NULL;
+ task = GNUNET_SCHEDULER_add_now (&run_transfers,
+ NULL);
+ return qs;
+ }
+
+ /* success, perform wire transfer */
+ ctc = GNUNET_new (struct CloseTransferContext);
+ ctc->wa = wa;
+ ctc->session = session;
+ ctc->method = TALER_WIRE_payto_get_method (account_details);
+ TALER_BANK_prepare_wire_transfer (account_details,
+ &amount_without_fee,
+ exchange_base_url,
+ &wtid,
+ &buf,
+ &buf_size);
+ /* Commit our intention to execute the wire transfer! */
+ qs = db_plugin->wire_prepare_data_insert (db_plugin->cls,
+ ctc->session,
+ ctc->method,
+ buf,
+ buf_size);
+ GNUNET_free (buf);
+ if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+ {
+ GNUNET_break (0);
+ GNUNET_free (ctc->method);
+ GNUNET_free (ctc);
+ ctc = NULL;
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ {
+ /* start again */
+ GNUNET_free (ctc->method);
+ GNUNET_free (ctc);
+ ctc = NULL;
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ erc->async_cont = GNUNET_YES;
+ task = GNUNET_SCHEDULER_add_now (&run_transfers,
+ NULL);
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
}
@@ -1344,6 +1321,8 @@ run_aggregation (void *cls)
struct TALER_EXCHANGEDB_Session *session;
enum GNUNET_DB_QueryStatus qs;
const struct GNUNET_SCHEDULER_TaskContext *tc;
+ void *buf;
+ size_t buf_size;
(void) cls;
task = NULL;
@@ -1470,8 +1449,7 @@ run_aggregation (void *cls)
&au->total_amount,
&au->wire_fee)) ||
(GNUNET_SYSERR ==
- au->wa->wire_plugin->amount_round (au->wa->wire_plugin->cls,
- &au->final_amount)) ||
+ TALER_WIRE_amount_round (&au->final_amount)) ||
( (0 == au->final_amount.value) &&
(0 == au->final_amount.fraction) ) )
{
@@ -1555,70 +1533,26 @@ run_aggregation (void *cls)
char *url;
url = TALER_JSON_wire_to_payto (au->wire);
- au->ph = au->wa->wire_plugin->prepare_wire_transfer (
- au->wa->wire_plugin->cls,
- au->wa->section_name,
- url,
- &au->final_amount,
- exchange_base_url,
- &au->wtid,
- &prepare_cb,
- au);
+ TALER_BANK_prepare_wire_transfer (url,
+ &au->final_amount,
+ exchange_base_url,
+ &au->wtid,
+ &buf,
+ &buf_size);
GNUNET_free (url);
}
- if (NULL == au->ph)
- {
- /* something went very wrong, likely bad configuration,
- abort */
- db_plugin->rollback (db_plugin->cls,
- session);
- cleanup_au ();
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- /* otherwise we continue with #prepare_cb(), see below */
-}
-
-
-/**
- * Function to be called with the prepared transfer data.
- *
- * @param cls NULL
- * @param buf transaction data to persist, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-prepare_cb (void *cls,
- const char *buf,
- size_t buf_size)
-{
- struct TALER_EXCHANGEDB_Session *session = au->session;
- enum GNUNET_DB_QueryStatus qs;
-
- (void) cls;
GNUNET_free_non_null (au->additional_rows);
au->additional_rows = NULL;
- if (NULL == buf)
- {
- GNUNET_break (0); /* why? how to best recover? */
- db_plugin->rollback (db_plugin->cls,
- session);
- /* start again */
- task = GNUNET_SCHEDULER_add_now (&run_aggregation,
- NULL);
- cleanup_au ();
- return;
- }
-
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Storing %u bytes of wire prepare data\n",
(unsigned int) buf_size);
/* Commit our intention to execute the wire transfer! */
qs = db_plugin->wire_prepare_data_insert (db_plugin->cls,
session,
- au->wa->wire_plugin->method,
+ au->wa->method,
buf,
buf_size);
+ GNUNET_free (buf);
/* Commit the WTID data to 'wire_out' to finally satisfy aggregation
table constraints */
if (qs >= 0)
@@ -1691,29 +1625,30 @@ prepare_cb (void *cls,
* Function called with the result from the execute step.
*
* @param cls NULL
- * @param success #GNUNET_OK on success, #GNUNET_SYSERR on failure
- * @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
- * @param emsg NULL on success, otherwise an error message
+ * @param http_status_code #MHD_HTTP_OK on success
+ * @param ec taler error code
+ * @param row_id unique ID of the wire transfer in the bank's records
+ * @param wire_timestamp when did the transfer happen
*/
static void
wire_confirm_cb (void *cls,
- int success,
- const void *row_id,
- size_t row_id_size,
- const char *emsg)
+ unsigned int http_status_code,
+ enum TALER_ErrorCode ec,
+ uint64_t row_id,
+ struct GNUNET_TIME_Absolute wire_timestamp)
{
struct TALER_EXCHANGEDB_Session *session = wpd->session;
enum GNUNET_DB_QueryStatus qs;
(void) cls;
(void) row_id;
- (void) row_id_size;
wpd->eh = NULL;
- if (GNUNET_SYSERR == success)
+ if (MHD_HTTP_OK != http_status_code)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Wire transaction failed: %s\n",
- emsg);
+ "Wire transaction failed: %u/%d\n",
+ http_status_code,
+ ec);
db_plugin->rollback (db_plugin->cls,
session);
global_ret = GNUNET_SYSERR;
@@ -1792,6 +1727,8 @@ wire_prepare_cb (void *cls,
const char *buf,
size_t buf_size)
{
+ struct WireAccount *wa;
+
(void) cls;
wpd->row_id = rowid;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -1811,12 +1748,15 @@ wire_prepare_cb (void *cls,
wpd = NULL;
return;
}
- wpd->eh = wpd->wa->wire_plugin->execute_wire_transfer (
- wpd->wa->wire_plugin->cls,
- buf,
- buf_size,
- &wire_confirm_cb,
- NULL);
+ wa = wpd->wa;
+ wpd->eh = TALER_BANK_execute_wire_transfer (ctx,
+ wa->account.details.x_taler_bank.
+ account_base_url,
+ &wa->auth,
+ buf,
+ buf_size,
+ &wire_confirm_cb,
+ NULL);
if (NULL == wpd->eh)
{
GNUNET_break (0); /* why? how to best recover? */
@@ -1927,6 +1867,7 @@ run (void *cls,
(void) cls;
(void) args;
(void) cfgfile;
+
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (c,
"exchange",
@@ -1947,6 +1888,15 @@ run (void *cls,
global_ret = 1;
return;
}
+ ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+ &rc);
+ rc = GNUNET_CURL_gnunet_rc_create (ctx);
+ if (NULL == ctx)
+ {
+ GNUNET_break (0);
+ return;
+ }
+
task = GNUNET_SCHEDULER_add_now (&run_transfers,
NULL);
GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c
index 02448238..96e30e43 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -400,7 +400,6 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
json_t *json;
int res;
json_t *wire;
- char *emsg;
enum TALER_ErrorCode ec;
unsigned int hc;
struct TALER_EXCHANGEDB_Deposit deposit;
@@ -460,18 +459,6 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
"refund_deadline");
}
- if (TALER_EC_NONE !=
- (ec = TEH_json_validate_wireformat (wire,
- &emsg)))
- {
- GNUNET_JSON_parse_free (spec);
- res = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- ec,
- emsg);
- GNUNET_free (emsg);
- return res;
- }
if (GNUNET_OK !=
check_timestamp_current (deposit.timestamp))
{
diff --git a/src/exchange/taler-exchange-httpd_validation.c b/src/exchange/taler-exchange-httpd_validation.c
index 23dbbf24..d0371e93 100644
--- a/src/exchange/taler-exchange-httpd_validation.c
+++ b/src/exchange/taler-exchange-httpd_validation.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2016, 2017, 2018 Taler Systems SA
+ Copyright (C) 2016-2020 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
@@ -30,40 +30,6 @@
/**
- * Information we keep for each plugin.
- */
-struct Plugin
-{
-
- /**
- * We keep plugins in a DLL.
- */
- struct Plugin *next;
-
- /**
- * We keep plugins in a DLL.
- */
- struct Plugin *prev;
-
- /**
- * Pointer to the plugin.
- */
- struct TALER_WIRE_Plugin *plugin;
-
-};
-
-
-/**
- * Head of DLL of wire plugins.
- */
-static struct Plugin *wire_head;
-
-/**
- * Tail of DLL of wire plugins.
- */
-static struct Plugin *wire_tail;
-
-/**
* Array of wire methods supported by this exchange.
*/
static json_t *wire_accounts_array;
@@ -191,9 +157,8 @@ load_account (void *cls,
else
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Wire fees not specified for `%s', ignoring plugin %s\n",
- method,
- ai->plugin_name);
+ "Wire fees not specified for `%s'\n",
+ method);
*ret = GNUNET_SYSERR;
}
GNUNET_free (method);
@@ -201,35 +166,15 @@ load_account (void *cls,
if (GNUNET_YES == ai->debit_enabled)
{
- struct Plugin *p;
-
- p = GNUNET_new (struct Plugin);
- p->plugin = TALER_WIRE_plugin_load (cfg,
- ai->plugin_name);
- if (NULL == p->plugin)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to load plugin %s\n",
- ai->plugin_name);
- GNUNET_free (p);
- *ret = GNUNET_SYSERR;
- return;
- }
if (GNUNET_OK !=
- load_fee (p->plugin->method))
+ load_fee (ai->method))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Disabling plugin `%s' as wire transfer fees for `%s' are not given correctly\n",
- ai->plugin_name,
- p->plugin->method);
- TALER_WIRE_plugin_unload (p->plugin);
- GNUNET_free (p);
+ "Wire transfer fees for `%s' are not given correctly\n",
+ ai->method);
*ret = GNUNET_SYSERR;
return;
}
- GNUNET_CONTAINER_DLL_insert (wire_head,
- wire_tail,
- p);
}
}
@@ -251,12 +196,6 @@ TEH_VALIDATION_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
TALER_EXCHANGEDB_find_accounts (cfg,
&load_account,
&ret);
- if (NULL == wire_head)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to find properly configured wire transfer method\n");
- ret = GNUNET_SYSERR;
- }
if (GNUNET_OK != ret)
TEH_VALIDATION_done ();
return ret;
@@ -269,16 +208,6 @@ TEH_VALIDATION_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
void
TEH_VALIDATION_done ()
{
- struct Plugin *p;
-
- while (NULL != (p = wire_head))
- {
- GNUNET_CONTAINER_DLL_remove (wire_head,
- wire_tail,
- p);
- TALER_WIRE_plugin_unload (p->plugin);
- GNUNET_free (p);
- }
json_decref (wire_fee_object);
wire_fee_object = NULL;
json_decref (wire_accounts_array);
@@ -287,65 +216,6 @@ TEH_VALIDATION_done ()
/**
- * Check if the given wire format JSON object is correctly formatted as
- * a wire address.
- *
- * @param wire the JSON wire format object
- * @param[out] emsg set to error message if we return an error code
- * @return #TALER_EC_NONE if correctly formatted; otherwise error code
- */
-enum TALER_ErrorCode
-TEH_json_validate_wireformat (const json_t *wire,
- char **emsg)
-{
- const char *payto_url;
- json_error_t error;
- char *method;
-
- *emsg = NULL;
- if (0 != json_unpack_ex ((json_t *) wire,
- &error, 0,
- "{s:s}",
- "url", &payto_url))
- {
- GNUNET_asprintf (emsg,
- "No `url' specified in the wire details\n");
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_TYPE_MISSING;
- }
- method = TALER_WIRE_payto_get_method (payto_url);
- if (NULL == method)
- {
- GNUNET_asprintf (emsg,
- "Malformed payto URL `%s'\n",
- payto_url);
- return TALER_EC_PAYTO_MALFORMED;
- }
- for (struct Plugin *p = wire_head; NULL != p; p = p->next)
- {
- if (0 == strcasecmp (p->plugin->method,
- method))
- {
- enum TALER_ErrorCode ec;
-
- GNUNET_free (method);
- ec = p->plugin->wire_validate (p->plugin->cls,
- payto_url);
- if (TALER_EC_NONE != ec)
- GNUNET_asprintf (emsg,
- "Payto URL `%s' rejected by plugin\n",
- payto_url);
- return ec;
- }
- }
- GNUNET_asprintf (emsg,
- "Wire format type `%s' is not supported by this exchange\n",
- method);
- GNUNET_free (method);
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_TYPE_UNSUPPORTED;
-}
-
-
-/**
* Obtain JSON response for /wire
*
* @return JSON array with the supported validation methods, NULL on error
diff --git a/src/exchange/taler-exchange-wirewatch.c b/src/exchange/taler-exchange-wirewatch.c
index 21f62cd8..091f4ba2 100644
--- a/src/exchange/taler-exchange-wirewatch.c
+++ b/src/exchange/taler-exchange-wirewatch.c
@@ -27,6 +27,7 @@
#include "taler_exchangedb_lib.h"
#include "taler_exchangedb_plugin.h"
#include "taler_json_lib.h"
+#include "taler_bank_service.h"
#include "taler_wire_lib.h"
/**
@@ -37,23 +38,6 @@
/**
- * Closure for #reject_cb().
- */
-struct RejectContext
-{
- /**
- * Wire transfer subject that was illformed.
- */
- char *wtid_s;
-
- /**
- * Database session that encountered the problem.
- */
- struct TALER_EXCHANGEDB_Session *session;
-};
-
-
-/**
* Information we keep for each supported account.
*/
struct WireAccount
@@ -69,14 +53,19 @@ struct WireAccount
struct WireAccount *prev;
/**
- * Handle to the plugin.
+ * Name of the section that configures this account.
*/
- struct TALER_WIRE_Plugin *wire_plugin;
+ char *section_name;
/**
- * Name of the section that configures this account.
+ * Account information.
*/
- char *section_name;
+ struct TALER_Account account;
+
+ /**
+ * Authentication data.
+ */
+ struct TALER_BANK_AuthenticationData auth;
/**
* Are we running from scratch and should re-process all transactions
@@ -108,6 +97,16 @@ static struct WireAccount *wa_tail;
static struct WireAccount *wa_pos;
/**
+ * Handle to the context for interacting with the bank.
+ */
+static struct GNUNET_CURL_Context *ctx;
+
+/**
+ * Scheduler context for running the @e ctx.
+ */
+static struct GNUNET_CURL_RescheduleContext *rc;
+
+/**
* Which currency is used by this exchange?
*/
static char *exchange_currency_string;
@@ -132,23 +131,13 @@ static int global_ret;
* Encoded offset in the wire transfer list from where
* to start the next query with the bank.
*/
-static void *last_row_off;
-
-/**
- * Number of bytes in #last_row_off.
- */
-static size_t last_row_off_size;
+static uint64_t last_row_off;
/**
* Latest row offset seen in this transaction, becomes
* the new #last_row_off upon commit.
*/
-static void *latest_row_off;
-
-/**
- * Number of bytes in #latest_row_off.
- */
-static size_t latest_row_off_size;
+static uint64_t latest_row_off;
/**
* Should we delay the next request to the wire plugin a bit?
@@ -183,12 +172,7 @@ static struct GNUNET_SCHEDULER_Task *task;
/**
* Active request for history.
*/
-static struct TALER_WIRE_HistoryHandle *hh;
-
-/**
- * Active request to reject a wire transfer.
- */
-static struct TALER_WIRE_RejectHandle *rt;
+static struct TALER_BANK_CreditHistoryHandle *hh;
/**
@@ -202,6 +186,16 @@ shutdown_task (void *cls)
struct WireAccount *wa;
(void) cls;
+ if (NULL != ctx)
+ {
+ GNUNET_CURL_fini (ctx);
+ ctx = NULL;
+ }
+ if (NULL != rc)
+ {
+ GNUNET_CURL_gnunet_rc_destroy (rc);
+ rc = NULL;
+ }
if (NULL != task)
{
GNUNET_SCHEDULER_cancel (task);
@@ -209,20 +203,9 @@ shutdown_task (void *cls)
}
if (NULL != hh)
{
- wa_pos->wire_plugin->get_history_cancel (wa_pos->wire_plugin->cls,
- hh);
+ TALER_BANK_credit_history_cancel (hh);
hh = NULL;
}
- if (NULL != rt)
- {
- char *wtid_s;
-
- wtid_s = wa_pos->wire_plugin->reject_transfer_cancel (
- wa_pos->wire_plugin->cls,
- rt);
- rt = NULL;
- GNUNET_free (wtid_s);
- }
TALER_EXCHANGEDB_plugin_unload (db_plugin);
db_plugin = NULL;
while (NULL != (wa = wa_head))
@@ -230,14 +213,13 @@ shutdown_task (void *cls)
GNUNET_CONTAINER_DLL_remove (wa_head,
wa_tail,
wa);
- TALER_WIRE_plugin_unload (wa->wire_plugin);
+ TALER_WIRE_account_free (&wa->account);
+ TALER_BANK_auth_free (&wa->auth);
GNUNET_free (wa->section_name);
GNUNET_free (wa);
}
wa_pos = NULL;
- GNUNET_free_non_null (last_row_off);
- last_row_off = NULL;
- last_row_off_size = 0;
+ last_row_off = 0;
}
@@ -259,13 +241,26 @@ add_account_cb (void *cls,
return; /* not enabled for us, skip */
wa = GNUNET_new (struct WireAccount);
wa->reset_mode = reset_mode;
- wa->wire_plugin = TALER_WIRE_plugin_load (cfg,
- ai->plugin_name);
- if (NULL == wa->wire_plugin)
+ if (GNUNET_OK !=
+ TALER_BANK_auth_parse_cfg (cfg,
+ ai->section_name,
+ &wa->auth))
{
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- "Failed to load wire plugin for `%s'\n",
- ai->plugin_name);
+ "Failed to load account `%s'\n",
+ ai->section_name);
+ GNUNET_free (wa);
+ return;
+ }
+ if (GNUNET_OK !=
+ TALER_BANK_account_parse_cfg (cfg,
+ ai->section_name,
+ &wa->account))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Failed to load account `%s'\n",
+ ai->section_name);
+ TALER_BANK_auth_free (&wa->auth);
GNUNET_free (wa);
return;
}
@@ -336,70 +331,28 @@ find_transfers (void *cls);
/**
- * Function called upon completion of the rejection of a wire transfer.
- *
- * @param cls closure with the `struct RejectContext`
- * @param ec error code for the operation
- */
-static void
-reject_cb (void *cls,
- enum TALER_ErrorCode ec)
-{
- struct RejectContext *rtc = cls;
- enum GNUNET_DB_QueryStatus qs;
-
- rt = NULL;
- if (TALER_EC_NONE != ec)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to wire back transfer `%s': %d\n",
- rtc->wtid_s,
- ec);
- GNUNET_free (rtc->wtid_s);
- db_plugin->rollback (db_plugin->cls,
- rtc->session);
- GNUNET_free (rtc);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- GNUNET_free (rtc->wtid_s);
- qs = db_plugin->commit (db_plugin->cls,
- rtc->session);
- GNUNET_break (0 <= qs);
- GNUNET_free (rtc);
- task = GNUNET_SCHEDULER_add_now (&find_transfers,
- NULL);
-}
-
-
-/**
* Callbacks of this type are used to serve the result of asking
* the bank for the transaction history.
*
* @param cls closure with the `struct TALER_EXCHANGEDB_Session *`
* @param ec taler error code
- * @param dir direction of the transfer
- * @param row_off identification of the position at which we are querying
- * @param row_off_size number of bytes in @a row_off
+ * @param serial_id identification of the position at which we are querying
* @param details details about the wire transfer
+ * @param json raw JSON response
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/
static int
history_cb (void *cls,
+ unsigned int http_status,
enum TALER_ErrorCode ec,
- enum TALER_BANK_Direction dir,
- const void *row_off,
- size_t row_off_size,
- const struct TALER_WIRE_TransferDetails *details)
+ uint64_t serial_id,
+ const struct TALER_BANK_CreditDetails *details,
+ const json_t *json)
{
struct TALER_EXCHANGEDB_Session *session = cls;
enum GNUNET_DB_QueryStatus qs;
- struct TALER_ReservePublicKeyP reserve_pub;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Got history callback, direction %u!\n",
- (unsigned int) dir);
- if (TALER_BANK_DIRECTION_NONE == dir)
+ if (NULL == details)
{
hh = NULL;
if (TALER_EC_NONE != ec)
@@ -428,11 +381,8 @@ history_cb (void *cls,
if (0 < qs)
{
/* transaction success, update #last_row_off */
- GNUNET_free_non_null (last_row_off);
last_row_off = latest_row_off;
- last_row_off_size = latest_row_off_size;
- latest_row_off = NULL;
- latest_row_off_size = 0;
+ latest_row_off = 0;
/* if successful at limit, try increasing transaction batch size (AIMD) */
if (current_batch_size == batch_size)
@@ -462,49 +412,10 @@ history_cb (void *cls,
NULL);
return GNUNET_OK; /* will be ignored anyway */
}
- if (NULL != details->wtid_s)
- {
- struct RejectContext *rtc;
-
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Wire transfer over %s has invalid subject `%s', sending it back!\n",
- TALER_amount2s (&details->amount),
- details->wtid_s);
- GNUNET_break (0 != row_off_size);
- if (latest_row_off_size != row_off_size)
- {
- GNUNET_free_non_null (latest_row_off);
- latest_row_off = GNUNET_malloc (row_off_size);
- latest_row_off_size = row_off_size;
- }
- memcpy (latest_row_off,
- row_off,
- row_off_size);
- rtc = GNUNET_new (struct RejectContext);
- rtc->session = session;
- rtc->wtid_s = GNUNET_strdup (details->wtid_s);
- rt = wa_pos->wire_plugin->reject_transfer (wa_pos->wire_plugin->cls,
- wa_pos->section_name,
- row_off,
- row_off_size,
- &reject_cb,
- rtc);
- if (NULL == rt)
- {
- GNUNET_break (0);
- db_plugin->rollback (db_plugin->cls,
- session);
- GNUNET_assert (NULL == task);
- task = GNUNET_SCHEDULER_add_now (&find_transfers,
- NULL);
- }
- return GNUNET_SYSERR; /* will continue later... */
- }
-
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Adding wire transfer over %s with (hashed) subject `%s'\n",
TALER_amount2s (&details->amount),
- TALER_B2S (&details->wtid));
+ TALER_B2S (&details->reserve_pub));
/**
* Debug block.
@@ -515,8 +426,8 @@ history_cb (void *cls,
char wtid_s[PUBSIZE];
GNUNET_break
- (NULL != GNUNET_STRINGS_data_to_string (&details->wtid,
- sizeof (details->wtid),
+ (NULL != GNUNET_STRINGS_data_to_string (&details->reserve_pub,
+ sizeof (details->reserve_pub),
&wtid_s[0],
PUBSIZE));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -525,20 +436,14 @@ history_cb (void *cls,
}
current_batch_size++;
- /* Wire transfer identifier == reserve public key */
- GNUNET_assert (sizeof (reserve_pub) == sizeof (details->wtid));
- memcpy (&reserve_pub,
- &details->wtid,
- sizeof (reserve_pub));
qs = db_plugin->reserves_in_insert (db_plugin->cls,
session,
- &reserve_pub,
+ &details->reserve_pub,
&details->amount,
details->execution_date,
details->account_url,
wa_pos->section_name,
- row_off,
- row_off_size);
+ serial_id);
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{
GNUNET_break (0);
@@ -560,15 +465,7 @@ history_cb (void *cls,
return GNUNET_SYSERR;
}
- if (latest_row_off_size != row_off_size)
- {
- GNUNET_free_non_null (latest_row_off);
- latest_row_off = GNUNET_malloc (row_off_size);
- latest_row_off_size = row_off_size;
- }
- memcpy (latest_row_off,
- row_off,
- row_off_size);
+ latest_row_off = serial_id;
return GNUNET_OK;
}
@@ -615,8 +512,7 @@ find_transfers (void *cls)
qs = db_plugin->get_latest_reserve_in_reference (db_plugin->cls,
session,
wa_pos->section_name,
- &last_row_off,
- &last_row_off_size);
+ &last_row_off);
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -638,20 +534,17 @@ find_transfers (void *cls)
}
}
wa_pos->reset_mode = GNUNET_NO;
- GNUNET_assert ( (NULL == last_row_off) ||
- ( (NULL != last_row_off) &&
- (0 != last_row_off_size) ) );
delay = GNUNET_YES;
current_batch_size = 0;
- hh = wa_pos->wire_plugin->get_history (wa_pos->wire_plugin->cls,
- wa_pos->section_name,
- TALER_BANK_DIRECTION_CREDIT,
- last_row_off,
- last_row_off_size,
- batch_size,
- &history_cb,
- session);
+ hh = TALER_BANK_credit_history (ctx,
+ wa_pos->account.details.x_taler_bank.
+ account_base_url,
+ &wa_pos->auth,
+ last_row_off,
+ batch_size,
+ &history_cb,
+ session);
if (NULL == hh)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -695,6 +588,14 @@ run (void *cls,
NULL);
GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
cls);
+ ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+ &rc);
+ rc = GNUNET_CURL_gnunet_rc_create (ctx);
+ if (NULL == ctx)
+ {
+ GNUNET_break (0);
+ return;
+ }
}
diff --git a/src/exchangedb/exchangedb_accounts.c b/src/exchangedb/exchangedb_accounts.c
index e3150902..03779395 100644
--- a/src/exchangedb/exchangedb_accounts.c
+++ b/src/exchangedb/exchangedb_accounts.c
@@ -58,7 +58,7 @@ check_for_account (void *cls,
const char *section)
{
struct FindAccountContext *ctx = cls;
- char *plugin_name;
+ char *method;
char *payto_url;
char *wire_response_filename;
struct TALER_EXCHANGEDB_AccountInfo ai;
@@ -81,12 +81,12 @@ check_for_account (void *cls,
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (ctx->cfg,
section,
- "PLUGIN",
- &plugin_name))
+ "METHOD",
+ &method))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
section,
- "PLUGIN");
+ "METHOD");
GNUNET_free (payto_url);
return;
}
@@ -97,7 +97,7 @@ check_for_account (void *cls,
&wire_response_filename))
wire_response_filename = NULL;
ai.section_name = section;
- ai.plugin_name = plugin_name;
+ ai.method = method;
ai.payto_url = payto_url;
ai.wire_response_filename = wire_response_filename;
@@ -112,7 +112,7 @@ check_for_account (void *cls,
ctx->cb (ctx->cb_cls,
&ai);
GNUNET_free (payto_url);
- GNUNET_free (plugin_name);
+ GNUNET_free (method);
GNUNET_free_non_null (wire_response_filename);
}
diff --git a/src/exchangedb/exchangedb_fees.c b/src/exchangedb/exchangedb_fees.c
index f06be73a..386c5de9 100644
--- a/src/exchangedb/exchangedb_fees.c
+++ b/src/exchangedb/exchangedb_fees.c
@@ -144,12 +144,12 @@ TALER_EXCHANGEDB_fees_read (const struct GNUNET_CONFIGURATION_Handle *cfg,
/**
* Convert @a af to @a wf.
*
- * @param wireplugin name of the wire plugin the fees are for
+ * @param method name of the wire method the fees are for
* @param[in,out] af aggregate fees, host format (updated to round time)
* @param[out] wf aggregate fees, disk / signature format
*/
void
-TALER_EXCHANGEDB_fees_2_wf (const char *wireplugin,
+TALER_EXCHANGEDB_fees_2_wf (const char *method,
struct TALER_EXCHANGEDB_AggregateFees *af,
struct TALER_MasterWireFeePS *wf)
{
@@ -157,8 +157,8 @@ TALER_EXCHANGEDB_fees_2_wf (const char *wireplugin,
(void) GNUNET_TIME_round_abs (&af->end_date);
wf->purpose.size = htonl (sizeof (*wf));
wf->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_FEES);
- GNUNET_CRYPTO_hash (wireplugin,
- strlen (wireplugin) + 1,
+ GNUNET_CRYPTO_hash (method,
+ strlen (method) + 1,
&wf->h_wire_method);
wf->start_date = GNUNET_TIME_absolute_hton (af->start_date);
wf->end_date = GNUNET_TIME_absolute_hton (af->end_date);
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index 6ddbead9..5f2c6716 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -253,7 +253,7 @@ postgres_create_tables (void *cls)
GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS reserves_in"
"(reserve_in_serial_id BIGSERIAL UNIQUE"
",reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE CASCADE"
- ",wire_reference BYTEA NOT NULL"
+ ",wire_reference INT8 NOT NULL"
",credit_val INT8 NOT NULL"
",credit_frac INT4 NOT NULL"
",sender_account_details TEXT NOT NULL"
@@ -2158,8 +2158,7 @@ reserves_update (void *cls,
* @param sender_account_details account information for the sender (payto://-URL)
* @param exchange_account_section name of the section in the configuration for the exchange's
* account into which the deposit was made
- * @param wire_reference unique reference identifying the wire transfer (binary blob)
- * @param wire_reference_size number of bytes in @a wire_reference
+ * @param wire_ref unique reference identifying the wire transfer
* @return transaction status code
*/
static enum GNUNET_DB_QueryStatus
@@ -2170,8 +2169,7 @@ postgres_reserves_in_insert (void *cls,
struct GNUNET_TIME_Absolute execution_time,
const char *sender_account_details,
const char *exchange_account_section,
- const void *wire_reference,
- size_t wire_reference_size)
+ uint64_t wire_ref)
{
struct PostgresClosure *pg = cls;
enum GNUNET_DB_QueryStatus reserve_exists;
@@ -2252,8 +2250,7 @@ postgres_reserves_in_insert (void *cls,
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (&reserve.pub),
- GNUNET_PQ_query_param_fixed_size (wire_reference,
- wire_reference_size),
+ GNUNET_PQ_query_param_uint64 (&wire_ref),
TALER_PQ_query_param_amount (balance),
GNUNET_PQ_query_param_string (exchange_account_section),
GNUNET_PQ_query_param_string (sender_account_details),
@@ -2311,8 +2308,7 @@ postgres_reserves_in_insert (void *cls,
* @param session the database session handle
* @param exchange_account_name name of the section in the exchange's configuration
* for the account that we are tracking here
- * @param[out] wire_reference set to unique reference identifying the wire transfer (binary blob)
- * @param[out] wire_reference_size set to number of bytes in @a wire_reference
+ * @param[out] wire_ref set to unique reference identifying the wire transfer
* @return transaction status code
*/
static enum GNUNET_DB_QueryStatus
@@ -2320,17 +2316,15 @@ postgres_get_latest_reserve_in_reference (void *cls,
struct TALER_EXCHANGEDB_Session *
session,
const char *exchange_account_name,
- void **wire_reference,
- size_t *wire_reference_size)
+ uint64_t *wire_reference)
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (exchange_account_name),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_variable_size ("wire_reference",
- wire_reference,
- wire_reference_size),
+ GNUNET_PQ_result_spec_uint64 ("wire_reference",
+ wire_reference),
GNUNET_PQ_result_spec_end
};
@@ -6192,14 +6186,12 @@ reserves_in_serial_helper_cb (void *cls,
char *sender_account_details;
struct GNUNET_TIME_Absolute execution_date;
uint64_t rowid;
- void *wire_reference;
- size_t wire_reference_size;
+ uint64_t wire_reference;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
&reserve_pub),
- GNUNET_PQ_result_spec_variable_size ("wire_reference",
- &wire_reference,
- &wire_reference_size),
+ GNUNET_PQ_result_spec_uint64 ("wire_reference",
+ &wire_reference),
TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
&credit),
TALER_PQ_result_spec_absolute_time ("execution_date",
@@ -6227,7 +6219,6 @@ reserves_in_serial_helper_cb (void *cls,
&credit,
sender_account_details,
wire_reference,
- wire_reference_size,
execution_date);
GNUNET_PQ_cleanup_result (rs);
if (GNUNET_OK != ret)
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index a1e20e83..583e3c17 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -944,8 +944,7 @@ audit_refund_cb (void *cls,
* @param reserve_pub public key of the reserve (also the WTID)
* @param credit amount that was received
* @param sender_account_details information about the sender's bank account
- * @param wire_reference unique reference identifying the wire transfer (binary blob)
- * @param wire_reference_size number of bytes in @a wire_reference
+ * @param wire_reference unique reference identifying the wire transfer
* @param execution_date when did we receive the funds
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
@@ -955,8 +954,7 @@ audit_reserve_in_cb (void *cls,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *credit,
const char *sender_account_details,
- const void *wire_reference,
- size_t wire_reference_size,
+ uint64_t wire_reference,
struct GNUNET_TIME_Absolute execution_date)
{
auditor_row_cnt++;
@@ -1507,8 +1505,7 @@ run (void *cls)
const char *sndr = "payto://x-taler-bank/localhost:8080/1";
unsigned int matched;
unsigned int cnt;
- void *rr;
- size_t rr_size;
+ uint64_t rr;
enum GNUNET_DB_QueryStatus qs;
struct GNUNET_TIME_Absolute now;
@@ -1578,8 +1575,7 @@ run (void *cls)
plugin->get_latest_reserve_in_reference (plugin->cls,
session,
"account-1",
- &rr,
- &rr_size));
+ &rr));
now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now);
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
@@ -1590,17 +1586,13 @@ run (void *cls)
now,
sndr,
"account-1",
- "TEST",
4));
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->get_latest_reserve_in_reference (plugin->cls,
session,
"account-1",
- &rr,
- &rr_size));
- FAILIF (4 != rr_size);
- FAILIF (0 != memcmp ("TEST", rr, 4));
- GNUNET_free (rr);
+ &rr));
+ FAILIF (4 != rr);
FAILIF (GNUNET_OK !=
check_reserve (session,
&reserve_pub,
@@ -1617,24 +1609,18 @@ run (void *cls)
now,
sndr,
"account-1",
- "TEST2",
5));
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->get_latest_reserve_in_reference (plugin->cls,
session,
"account-1",
- &rr,
- &rr_size));
- GNUNET_free (rr);
+ &rr));
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->get_latest_reserve_in_reference (plugin->cls,
session,
"account-1",
- &rr,
- &rr_size));
- FAILIF (5 != rr_size);
- FAILIF (0 != memcmp ("TEST2", rr, 5));
- GNUNET_free (rr);
+ &rr));
+ FAILIF (5 != rr);
FAILIF (GNUNET_OK !=
check_reserve (session,
&reserve_pub,
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index af91f117..25bc67b2 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -31,8 +31,6 @@ talerinclude_HEADERS = \
taler_mhd_lib.h \
taler_pq_lib.h \
taler_signatures.h \
- taler_wire_lib.h \
- taler_wire_plugin.h \
taler_testing_bank_lib.h
endif
diff --git a/src/include/taler_auditordb_plugin.h b/src/include/taler_auditordb_plugin.h
index 03a1c6d4..14d477d3 100644
--- a/src/include/taler_auditordb_plugin.h
+++ b/src/include/taler_auditordb_plugin.h
@@ -870,7 +870,6 @@ struct TALER_AUDITORDB_Plugin
* @param pp where is the auditor in processing
* @param in_wire_off how far are we in the incoming wire transaction history
* @param out_wire_off how far are we in the outgoing wire transaction history
- * @param wire_off_size how many bytes do @a in_wire_off and @a out_wire_off take?
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
@@ -883,9 +882,8 @@ struct TALER_AUDITORDB_Plugin
const struct
TALER_AUDITORDB_WireAccountProgressPoint
*pp,
- const void *in_wire_off,
- const void *out_wire_off,
- size_t wire_off_size);
+ uint64_t in_wire_off,
+ uint64_t out_wire_off);
/**
@@ -899,7 +897,6 @@ struct TALER_AUDITORDB_Plugin
* @param pp where is the auditor in processing
* @param in_wire_off how far are we in the incoming wire transaction history
* @param out_wire_off how far are we in the outgoing wire transaction history
- * @param wire_off_size how many bytes do @a in_wire_off and @a out_wire_off take?
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
@@ -912,9 +909,8 @@ struct TALER_AUDITORDB_Plugin
const struct
TALER_AUDITORDB_WireAccountProgressPoint
*pp,
- const void *in_wire_off,
- const void *out_wire_off,
- size_t wire_off_size);
+ uint64_t in_wire_off,
+ uint64_t out_wire_off);
/**
@@ -927,7 +923,6 @@ struct TALER_AUDITORDB_Plugin
* @param[out] pp where is the auditor in processing
* @param[out] in_wire_off how far are we in the incoming wire transaction history
* @param[out] out_wire_off how far are we in the outgoing wire transaction history
- * @param[out] wire_off_size how many bytes do @a in_wire_off and @a out_wire_off take?
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
@@ -939,9 +934,8 @@ struct TALER_AUDITORDB_Plugin
struct
TALER_AUDITORDB_WireAccountProgressPoint
*pp,
- void **in_wire_off,
- void **out_wire_off,
- size_t *wire_off_size);
+ uint64_t *in_wire_off,
+ uint64_t *out_wire_off);
/**
diff --git a/src/include/taler_bank_service.h b/src/include/taler_bank_service.h
index a7246ad2..a2eec49a 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, 2016, 2017 Taler Systems SA
+ Copyright (C) 2015-2020 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
@@ -25,6 +25,7 @@
#include <jansson.h>
#include <gnunet/gnunet_curl_lib.h>
#include "taler_util.h"
+#include "taler_wire_lib.h"
#include "taler_error_codes.h"
@@ -122,13 +123,11 @@ typedef void
* to the operators of the bank.
*
* @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this request)
+ * @param account_base_url URL of the account (used to execute this request)
* @param auth authentication data to use
- * @param exchange_base_url base URL of the exchange (for tracking)
- * @param subject wire transfer subject for the transfer
+ * @param reserve_pub wire transfer subject for the transfer
* @param amount amount that was deposited
- * @param debit_account_no account number to withdraw from (53 bits at most)
- * @param credit_account_no account number to deposit into (53 bits at most)
+ * @param credit_account account to deposit into
* @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
@@ -137,13 +136,12 @@ typedef void
*/
struct TALER_BANK_AdminAddIncomingHandle *
TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context *ctx,
- const char *bank_base_url,
+ const char *account_base_url,
const struct TALER_BANK_AuthenticationData *auth,
- const char *exchange_base_url,
- const char *subject,
+ const struct
+ TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *amount,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
+ const char *credit_account,
TALER_BANK_AdminAddIncomingResultCallback res_cb,
void *res_cb_cls);
@@ -159,53 +157,103 @@ TALER_BANK_admin_add_incoming_cancel (struct
TALER_BANK_AdminAddIncomingHandle *aai);
+/* ********************* /taler/transfer *********************** */
+
/**
- * Which types of transactions should be (or is being) returned?
+ * Prepare for exeuction of a wire transfer.
+ *
+ * @param destination_account_url payto:// URL identifying where to send the money
+ * @param amount amount to transfer, already rounded
+ * @param exchange_base_url base URL of this exchange (included in subject
+ * to facilitate use of tracking API by merchant backend)
+ * @param wtid wire transfer identifier to use
+ * @param buf[out] set to transaction data to persist, NULL on error
+ * @param buf_size[out] set to number of bytes in @a buf, 0 on error
*/
-enum TALER_BANK_Direction
-{
+void
+TALER_BANK_prepare_wire_transfer (const char *destination_account_url,
+ const struct TALER_Amount *amount,
+ const char *exchange_base_url,
+ const struct
+ TALER_WireTransferIdentifierRawP *wtid,
+ void **buf,
+ size_t *buf_size);
- /**
- * Base case, used to indicate errors or end of list.
- */
- TALER_BANK_DIRECTION_NONE = 0,
- /**
- * Transactions where the bank account receives money.
- */
- TALER_BANK_DIRECTION_CREDIT = 1,
+/**
+ * Handle for active wire transfer.
+ */
+struct TALER_BANK_WireExecuteHandle;
- /**
- * Transactions where the bank account looses money.
- */
- TALER_BANK_DIRECTION_DEBIT = 2,
- /**
- * Return both types of transactions.
- */
- TALER_BANK_DIRECTION_BOTH = (TALER_BANK_DIRECTION_CREDIT
- | TALER_BANK_DIRECTION_DEBIT),
+/**
+ * Function called with the result from the execute step.
+ *
+ * @param cls closure
+ * @param response_code HTTP status code
+ * @param ec taler error code
+ * @param row_id unique ID of the wire transfer in the bank's records
+ * @param timestamp when did the transaction go into effect
+ */
+typedef void
+(*TALER_BANK_ConfirmationCallback)(void *cls,
+ unsigned int response_code,
+ enum TALER_ErrorCode ec,
+ uint64_t row_id,
+ struct GNUNET_TIME_Absolute timestamp);
- /**
- * Bit mask that is applied to view transactions that have been
- * cancelled. The bit is set for cancelled transactions that are
- * returned from /history, and must also be set in order for
- * cancelled transactions to show up in the /history.
- */
- TALER_BANK_DIRECTION_CANCEL = 4
-};
+/**
+
+ * Execute a wire transfer.
+ *
+ * @param ctx context for HTTP interaction
+ * @param bank_base_url URL of the base INCLUDING account number
+ * @param buf buffer with the prepared execution details
+ * @param buf_size number of bytes in @a buf
+ * @param cc function to call upon success
+ * @param cc_cls closure for @a cc
+ * @return NULL on error
+ */
+struct TALER_BANK_WireExecuteHandle *
+TALER_BANK_execute_wire_transfer (struct GNUNET_CURL_Context *ctx,
+ const char *bank_base_url,
+ const struct
+ TALER_BANK_AuthenticationData *auth,
+ const void *buf,
+ size_t buf_size,
+ TALER_BANK_ConfirmationCallback cc,
+ void *cc_cls);
/**
- * Handle for querying the bank's transaction history.
+ * Abort execution of a wire transfer. For example, because we are
+ * shutting down. Note that if an execution is aborted, it may or
+ * may not still succeed. The caller MUST run @e
+ * execute_wire_transfer again for the same request as soon as
+ * possilbe, to ensure that the request either ultimately succeeds
+ * or ultimately fails. Until this has been done, the transaction is
+ * in limbo (i.e. may or may not have been committed).
+ *
+ * @param eh execution to cancel
*/
-struct TALER_BANK_HistoryHandle;
+void
+TALER_BANK_execute_wire_transfer_cancel (struct
+ TALER_BANK_WireExecuteHandle *eh);
+
+
+/* ********************* /taler/credits *********************** */
/**
- * Details about a wire transfer.
+ * Handle for querying the bank for transactions
+ * made to the exchange.
*/
-struct TALER_BANK_TransferDetails
+struct TALER_BANK_CreditHistoryHandle;
+
+/**
+ * Details about a wire transfer to the exchange.
+ */
+struct TALER_BANK_CreditDetails
{
/**
* Amount that was transferred
@@ -218,21 +266,22 @@ struct TALER_BANK_TransferDetails
struct GNUNET_TIME_Absolute execution_date;
/**
- * Wire transfer subject. Usually a reserve public key
- * followed by the base URL of the exchange.
+ * Reserve public key encoded in the wire
+ * transfer subject.
*/
- char *wire_transfer_subject;
+ struct TALER_ReservePublicKeyP reserve_pub;
/**
- * payto://-URL of the other account that was involved
+ * payto://-URL of the source account that
+ * send the funds.
*/
- char *account_url;
+ const char *account_url;
};
/**
* Callbacks of this type are used to serve the result of asking
- * the bank for the transaction history.
+ * the bank for the credit transaction history.
*
* @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
@@ -241,31 +290,27 @@ struct TALER_BANK_TransferDetails
* last callback is always of this status (even if `abs(num_results)` were
* already returned).
* @param ec detailed error code
- * @param dir direction of the transfer
* @param serial_id monotonically increasing counter corresponding to the transaction
* @param details details about the wire transfer
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/
-typedef void
-(*TALER_BANK_HistoryResultCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- enum TALER_BANK_Direction dir,
- uint64_t serial_id,
- const struct
- TALER_BANK_TransferDetails *details,
- const json_t *json);
+typedef int
+(*TALER_BANK_CreditResultCallback) (void *cls,
+ unsigned int http_status,
+ enum TALER_ErrorCode ec,
+ uint64_t serial_id,
+ const struct
+ TALER_BANK_CreditDetails *details,
+ const json_t *json);
/**
- * Request the wire transfer history of a bank account.
+ * Request the wire credit history of an exchange's bank account.
*
* @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this request)
+ * @param account_base_url URL of the base INCLUDING account number
* @param auth authentication data to use
- * @param account_number which account number should we query
- * @param direction what kinds of wire transfers should be returned
- * @param ascending if GNUNET_YES, history elements will be returned in chronological order.
* @param start_row from which row on do we want to get results, use UINT64_MAX for the latest; exclusive
* @param num_results how many results do we want; negative numbers to go into the past,
* positive numbers to go into the future starting at @a start_row;
@@ -276,17 +321,14 @@ typedef void
* if the inputs are invalid (i.e. zero value for @e num_results).
* In this case, the callback is not called.
*/
-struct TALER_BANK_HistoryHandle *
-TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
- const char *bank_base_url,
- const struct TALER_BANK_AuthenticationData *auth,
- uint64_t account_number,
- enum TALER_BANK_Direction direction,
- unsigned int ascending,
- uint64_t start_row,
- int64_t num_results,
- TALER_BANK_HistoryResultCallback hres_cb,
- void *hres_cb_cls);
+struct TALER_BANK_CreditHistoryHandle *
+TALER_BANK_credit_history (struct GNUNET_CURL_Context *ctx,
+ const char *account_base_url,
+ const struct TALER_BANK_AuthenticationData *auth,
+ uint64_t start_row,
+ int64_t num_results,
+ TALER_BANK_CreditResultCallback hres_cb,
+ void *hres_cb_cls);
/**
@@ -297,64 +339,127 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
* @param hh the history request handle
*/
void
-TALER_BANK_history_cancel (struct TALER_BANK_HistoryHandle *hh);
+TALER_BANK_credit_history_cancel (struct TALER_BANK_CreditHistoryHandle *hh);
+
+/* ********************* /taler/debits *********************** */
/**
- * Handle for #TALER_BANK_reject() operation.
+ * Handle for querying the bank for transactions
+ * made from the exchange to merchants.
*/
-struct TALER_BANK_RejectHandle;
+struct TALER_BANK_DebitHistoryHandle;
+
+/**
+ * Details about a wire transfer made by the exchange
+ * to a merchant.
+ */
+struct TALER_BANK_DebitDetails
+{
+ /**
+ * Amount that was transferred
+ */
+ struct TALER_Amount amount;
+
+ /**
+ * Time of the the transfer
+ */
+ struct GNUNET_TIME_Absolute execution_date;
+
+ /**
+ * Wire transfer identifier used by the exchange.
+ */
+ struct TALER_WireTransferIdentifierRawP wtid;
+
+ /**
+ * Exchange's base URL as given in the wire transfer.
+ */
+ const char *exchange_base_url;
+
+ /**
+ * payto://-URL of the source account that
+ * send the funds.
+ */
+ const char *account_url;
+};
/**
* Callbacks of this type are used to serve the result of asking
- * the bank to reject an incoming wire transfer.
+ * the bank for the debit transaction history.
*
* @param cls closure
- * @param http_status HTTP response code, #MHD_HTTP_NO_CONTENT (204) for successful status request;
- * #MHD_HTTP_NOT_FOUND if the rowid is unknown;
+ * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
* 0 if the bank's reply is bogus (fails to follow the protocol),
+ * #MHD_HTTP_NO_CONTENT if there are no more results; on success the
+ * last callback is always of this status (even if `abs(num_results)` were
+ * already returned).
* @param ec detailed error code
+ * @param serial_id monotonically increasing counter corresponding to the transaction
+ * @param details details about the wire transfer
+ * @param json detailed response from the HTTPD, or NULL if reply was not in JSON
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/
-typedef void
-(*TALER_BANK_RejectResultCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec);
+typedef int
+(*TALER_BANK_DebitResultCallback) (void *cls,
+ unsigned int http_status,
+ enum TALER_ErrorCode ec,
+ uint64_t serial_id,
+ const struct
+ TALER_BANK_DebitDetails *details,
+ const json_t *json);
/**
- * Request rejection of a wire transfer, marking it as cancelled and voiding
- * its effects.
+ * Request the wire credit history of an exchange's bank account.
*
* @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this request)
+ * @param bank_base_url URL of the base INCLUDING account number
* @param auth authentication data to use
* @param account_number which account number should we query
- * @param rowid transfer to reject
- * @param rcb the callback to call with the operation result
- * @param rcb_cls closure for @a rcb
+ * @param start_row from which row on do we want to get results, use UINT64_MAX for the latest; exclusive
+ * @param num_results how many results do we want; negative numbers to go into the past,
+ * positive numbers to go into the future starting at @a start_row;
+ * must not be zero.
+ * @param hres_cb the callback to call with the transaction history
+ * @param hres_cb_cls closure for the above callback
* @return NULL
- * if the inputs are invalid.
+ * if the inputs are invalid (i.e. zero value for @e num_results).
* In this case, the callback is not called.
*/
-struct TALER_BANK_RejectHandle *
-TALER_BANK_reject (struct GNUNET_CURL_Context *ctx,
- const char *bank_base_url,
- const struct TALER_BANK_AuthenticationData *auth,
- uint64_t account_number,
- uint64_t rowid,
- TALER_BANK_RejectResultCallback rcb,
- void *rcb_cls);
+struct TALER_BANK_DebitHistoryHandle *
+TALER_BANK_debit_history (struct GNUNET_CURL_Context *ctx,
+ const char *bank_base_url,
+ const struct TALER_BANK_AuthenticationData *auth,
+ uint64_t start_row,
+ int64_t num_results,
+ TALER_BANK_DebitResultCallback hres_cb,
+ void *hres_cb_cls);
/**
- * Cancel an reject request. This function cannot be used on a request
- * handle if the response was is already served for it.
+ * Cancel an history request. This function cannot be used on a request
+ * handle if the last response (anything with a status code other than
+ * 200) is already served for it.
*
- * @param rh the reject request handle
+ * @param hh the history request handle
*/
void
-TALER_BANK_reject_cancel (struct TALER_BANK_RejectHandle *rh);
+TALER_BANK_debit_history_cancel (struct TALER_BANK_DebitHistoryHandle *hh);
+
+
+/**
+ * Convenience method for parsing configuration section with bank account data.
+ *
+ * @param cfg configuration to parse
+ * @param section the section with the configuration data
+ * @param acc[out] set to the account details
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_BANK_account_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *section,
+ struct TALER_Account *acc);
/**
diff --git a/src/include/taler_exchangedb_lib.h b/src/include/taler_exchangedb_lib.h
index e6364062..1681c45a 100644
--- a/src/include/taler_exchangedb_lib.h
+++ b/src/include/taler_exchangedb_lib.h
@@ -425,12 +425,12 @@ TALER_EXCHANGEDB_fees_read (const struct GNUNET_CONFIGURATION_Handle *cfg,
/**
* Convert @a af to @a wf.
*
- * @param wireplugin name of the wire plugin the fees are for
+ * @param wiremethod name of the wire method the fees are for
* @param[in,out] af aggregate fees, host format (updated to round time)
* @param[out] wf aggregate fees, disk / signature format
*/
void
-TALER_EXCHANGEDB_fees_2_wf (const char *wireplugin,
+TALER_EXCHANGEDB_fees_2_wf (const char *wiremethod,
struct TALER_EXCHANGEDB_AggregateFees *af,
struct TALER_MasterWireFeePS *wf);
@@ -470,10 +470,9 @@ struct TALER_EXCHANGEDB_AccountInfo
const char *section_name;
/**
- * Name of the wire plugin that should be used to access
- * the account.
+ * Name of the wire method used by this account.
*/
- const char *plugin_name;
+ const char *method;
/**
* payto://-URL of the account.
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index 0dcf4b84..09e3b180 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -960,8 +960,7 @@ typedef int
* @param reserve_pub public key of the reserve (also the WTID)
* @param credit amount that was received
* @param sender_account_details information about the sender's bank account, in payto://-format
- * @param wire_reference unique identifier for the wire transfer (plugin-specific format)
- * @param wire_reference_size number of bytes in @a wire_reference
+ * @param wire_reference unique identifier for the wire transfer
* @param execution_date when did we receive the funds
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
@@ -972,8 +971,7 @@ typedef int
TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *credit,
const char *sender_account_details,
- const void *wire_reference,
- size_t wire_reference_size,
+ uint64_t wire_reference,
struct GNUNET_TIME_Absolute
execution_date);
@@ -1500,8 +1498,7 @@ struct TALER_EXCHANGEDB_Plugin
* @param balance the amount that has to be added to the reserve
* @param execution_time when was the amount added
* @param sender_account_details information about the sender's bank account, in payto://-format
- * @param wire_reference unique reference identifying the wire transfer (binary blob)
- * @param wire_reference_size number of bytes in @a wire_reference
+ * @param wire_reference unique reference identifying the wire transfer
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
@@ -1512,8 +1509,7 @@ struct TALER_EXCHANGEDB_Plugin
struct GNUNET_TIME_Absolute execution_time,
const char *sender_account_details,
const char *exchange_account_name,
- const void *wire_reference,
- size_t wire_reference_size);
+ uint64_t wire_reference);
/**
@@ -1521,16 +1517,14 @@ struct TALER_EXCHANGEDB_Plugin
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param db the database connection handle
- * @param[out] wire_reference set to unique reference identifying the wire transfer (binary blob)
- * @param[out] wire_reference_size set to number of bytes in @a wire_reference
+ * @param[out] wire_ref set to unique reference identifying the wire transfer
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
(*get_latest_reserve_in_reference)(void *cls,
struct TALER_EXCHANGEDB_Session *db,
const char *exchange_account_name,
- void **wire_reference,
- size_t *wire_reference_size);
+ uint64_t *wire_ref);
/**
diff --git a/src/include/taler_fakebank_lib.h b/src/include/taler_fakebank_lib.h
index f3f92534..474c6627 100644
--- a/src/include/taler_fakebank_lib.h
+++ b/src/include/taler_fakebank_lib.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2016 Inria and GNUnet e.V.
+ (C) 2016-2020 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
@@ -74,8 +74,8 @@ TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle *h);
*/
uint64_t
TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
- uint64_t debit_account,
- uint64_t credit_account,
+ const char *debit_account,
+ const char *credit_account,
const struct TALER_Amount *amount,
const char *subject,
const char *exchange_base_url);
@@ -101,28 +101,13 @@ TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
int
TALER_FAKEBANK_check (struct TALER_FAKEBANK_Handle *h,
const struct TALER_Amount *want_amount,
- uint64_t want_debit,
- uint64_t want_credit,
+ const char *want_debit,
+ const char *want_credit,
const char *exchange_base_url,
char **subject);
/**
- * Reject incoming wire transfer to account @a credit_account
- * as identified by @a rowid.
- *
- * @param h fake bank handle
- * @param rowid identifies transfer to reject
- * @param credit_account account number of owner of credited account
- * @return #GNUNET_YES on success, #GNUNET_NO if the wire transfer was not found
- */
-int
-TALER_FAKEBANK_reject_transfer (struct TALER_FAKEBANK_Handle *h,
- uint64_t rowid,
- uint64_t credit_account);
-
-
-/**
* Stop running the fake bank.
*
* @param h bank to stop
diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h
index 6aefbd77..c836e446 100644
--- a/src/include/taler_mhd_lib.h
+++ b/src/include/taler_mhd_lib.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014 GNUnet e.V.
+ Copyright (C) 2014-2020 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
diff --git a/src/include/taler_testing_bank_lib.h b/src/include/taler_testing_bank_lib.h
index 350aca3b..43d12d33 100644
--- a/src/include/taler_testing_bank_lib.h
+++ b/src/include/taler_testing_bank_lib.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2018 Taler Systems SA
+ (C) 2018-2020 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
@@ -103,46 +103,42 @@ TALER_TESTING_has_in_name (const char *prog,
/* ************** Specific interpreter commands ************ */
/**
- * Make a "history" CMD.
+ * Make a credit "history" CMD.
*
* @param label command label.
- * @param bank_url base URL of the bank offering the "history"
+ * @param account_url base URL of the account offering the "history"
* operation.
- * @param account_no bank account number to ask the history for.
- * @param direction which direction this operation is interested
- * @param ascending if #GNUNET_YES, it ask the bank to return results
- * in chronological order.
* @param start_row_reference reference to a command that can
* offer a row identifier, to be used as the starting row
* to accept in the result.
- * @param num_results how many rows we want in the result.
+ * @param num_results how many rows we want in the result,
+ * and ascending/descending call
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_bank_history (const char *label,
- const char *bank_url,
- uint64_t account_no,
- enum TALER_BANK_Direction direction,
- unsigned int ascending,
+TALER_TESTING_cmd_bank_credits (const char *label,
+ const char *account_url,
const char *start_row_reference,
- unsigned long long num_results);
+ long long num_results);
/**
- * Create a "reject" CMD.
+ * Make a debit "history" CMD.
*
* @param label command label.
- * @param bank_url base URL of the bank implementing the
- * "reject" operation.
- * @param deposit_reference reference to a command that will
- * provide a "row id" and credit (bank) account to craft
- * the "reject" request.
- *
+ * @param account_url base URL of the account offering the "history"
+ * operation.
+ * @param start_row_reference reference to a command that can
+ * offer a row identifier, to be used as the starting row
+ * to accept in the result.
+ * @param num_results how many rows we want in the result.
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_bank_reject (const char *label,
- const char *bank_url,
- const char *deposit_reference);
+TALER_TESTING_cmd_bank_debits (const char *label,
+ const char *account_url,
+ const char *start_row_reference,
+ long long num_results);
+
#endif
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index a039f0ec..33f07070 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -48,23 +48,24 @@
} while (0)
+#define TALER_TESTING_GET_TRAIT_ROW_ID(cmd,out) \
+ TALER_TESTING_get_trait_uint64 (cmd, 3, out)
+
+#define TALER_TESTING_MAKE_TRAIT_ROW_ID(data) \
+ TALER_TESTING_make_trait_uint64 (3, data)
+
+
#define TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT(cmd,out) \
- TALER_TESTING_get_trait_uint64 (cmd, 0, out)
+ TALER_TESTING_get_trait_string (cmd, 4, out)
#define TALER_TESTING_MAKE_TRAIT_CREDIT_ACCOUNT(data) \
- TALER_TESTING_make_trait_uint64 (0, data)
+ TALER_TESTING_make_trait_string (4, data)
#define TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT(cmd,out) \
- TALER_TESTING_get_trait_uint64 (cmd, 1, out)
+ TALER_TESTING_get_trait_string (cmd, 5, out)
#define TALER_TESTING_MAKE_TRAIT_DEBIT_ACCOUNT(data) \
- TALER_TESTING_make_trait_uint64 (1, data)
-
-#define TALER_TESTING_GET_TRAIT_ROW_ID(cmd,out) \
- TALER_TESTING_get_trait_uint64 (cmd, 3, out)
-
-#define TALER_TESTING_MAKE_TRAIT_ROW_ID(data) \
- TALER_TESTING_make_trait_uint64 (3, data)
+ TALER_TESTING_make_trait_string (5, data)
/**
@@ -715,13 +716,9 @@ TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb,
*
* @param label command label.
* @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- * wire transer. For simplicity, both credit and debit
- * bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- * gives money.
- * @param credit_account_no which account (expressed as a number)
- * receives money.
+ * @param account_base_url base URL of the account that implements this
+ * wire transer (which account gives money).
+ * @param payto_credit_account which account receives money.
* @param auth_username username identifying the @a
* debit_account_no at the bank.
* @param auth_password password for @a auth_username.
@@ -734,51 +731,14 @@ TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb,
struct TALER_TESTING_Command
TALER_TESTING_cmd_fakebank_transfer (const char *label,
const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
+ const char *account_base_url,
+ const char *payto_credit_account,
const char *auth_username,
const char *auth_password,
const char *exchange_url);
/**
- * Create "fakebank transfer" CMD, letting the caller specifying
- * the subject line.
- *
- * @param label command label.
- * @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- * wire transer. For simplicity, both credit and debit
- * bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- * gives money.
- * @param credit_account_no which account (expressed as a number)
- * receives money.
- *
- * @param auth_username username identifying the @a
- * debit_account_no at the bank.
- * @param auth_password password for @a auth_username.
- * @param subject wire transfer's subject line.
- * @param exchange_url which exchange is involved in this transfer.
- * This data is used for tracking purposes (FIXME: explain
- * _how_).
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_with_subject (const char *label,
- const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
- const char *auth_username,
- const char *auth_password,
- const char *subject,
- const char *exchange_url);
-
-
-/**
* Create "fakebank transfer" CMD, letting the caller specify
* a reference to a command that can offer a reserve private key.
* This private key will then be used to construct the subject line
@@ -786,11 +746,9 @@ TALER_TESTING_cmd_fakebank_transfer_with_subject (const char *label,
*
* @param label command label.
* @param amount the amount to transfer.
- * @param bank_url base URL of the bank running the transfer.
- * @param debit_account_no which account (expressed as a number)
- * gives money.
- * @param credit_account_no which account (expressed as a number)
- * receives money.
+ * @param account_base_url base URL of the account that implements this
+ * wire transer (which account gives money).
+ * @param payto_credit_account which account receives money.
* @param auth_username username identifying the @a
* debit_account_no at the bank.
* @param auth_password password for @a auth_username.
@@ -804,9 +762,9 @@ TALER_TESTING_cmd_fakebank_transfer_with_subject (const char *label,
struct TALER_TESTING_Command
TALER_TESTING_cmd_fakebank_transfer_with_ref (const char *label,
const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
+ const char *account_base_url,
+ const char *payto_credit_account,
+
const char *auth_username,
const char *auth_password,
const char *ref,
@@ -822,14 +780,9 @@ TALER_TESTING_cmd_fakebank_transfer_with_ref (const char *label,
*
* @param label command label.
* @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- * wire transer. For simplicity, both credit and debit
- * bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- * gives money.
- * @param credit_account_no which account (expressed as a number)
- * receives money.
- *
+ * @param account_base_url base URL of the account that implements this
+ * wire transer (which account gives money).
+ * @param payto_credit_account which account receives money.
* @param auth_username username identifying the @a
* debit_account_no at the bank.
* @param auth_password password for @a auth_username.
@@ -847,9 +800,9 @@ TALER_TESTING_cmd_fakebank_transfer_with_ref (const char *label,
struct TALER_TESTING_Command
TALER_TESTING_cmd_fakebank_transfer_with_instance (const char *label,
const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
+ const char *account_base_url,
+ const char *
+ payto_credit_account,
const char *auth_username,
const char *auth_password,
const char *instance,
@@ -1268,8 +1221,8 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_check_bank_transfer (const char *label,
const char *exchange_base_url,
const char *amount,
- uint64_t debit_account,
- uint64_t credit_account);
+ const char *debit_account,
+ const char *credit_account);
/**
@@ -1617,7 +1570,6 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
*
* @return the trait.
*/
-
struct TALER_TESTING_Trait
TALER_TESTING_make_trait_reserve_priv (unsigned int index,
const struct
@@ -1641,6 +1593,34 @@ TALER_TESTING_get_trait_reserve_priv (const struct TALER_TESTING_Command *cmd,
/**
+ * Offer a reserve public key.
+ *
+ * @param index reserve pubs's index number.
+ * @param reserve_priv reserve public key to offer.
+ * @return the trait.
+ */
+struct TALER_TESTING_Trait
+TALER_TESTING_make_trait_reserve_pub (unsigned int index,
+ const struct
+ TALER_ReservePublicKeyP *reserve_pub);
+
+
+/**
+ * Obtain a reserve public key from a @a cmd.
+ *
+ * @param cmd command to extract the reserve pub from.
+ * @param index reserve pub's index number.
+ * @param reserve_pub[out] set to the reserve pub.
+ * @return #GNUNET_OK on success.
+ */
+int
+TALER_TESTING_get_trait_reserve_pub (const struct TALER_TESTING_Command *cmd,
+ unsigned int index,
+ const struct
+ TALER_ReservePublicKeyP **reserve_pub);
+
+
+/**
* Make a trait for a exchange signature.
*
* @param index index number to associate to the offered exchange pub.
@@ -2129,34 +2109,34 @@ TALER_TESTING_make_trait_peer_key_pub (unsigned int index,
/**
- * Obtain a transfer subject from @a cmd.
+ * Obtain a string from @a cmd.
*
* @param cmd command to extract the subject from.
* @param index index number associated with the transfer
* subject to offer.
- * @param transfer_subject[out] where to write the offered
- * transfer subject.
+ * @param s[out] where to write the offered
+ * string.
*
* @return #GNUNET_OK on success.
*/
int
-TALER_TESTING_get_trait_transfer_subject (const struct
- TALER_TESTING_Command *cmd,
- unsigned int index,
- const char **transfer_subject);
+TALER_TESTING_get_trait_string (const struct
+ TALER_TESTING_Command *cmd,
+ unsigned int index,
+ const char **s);
/**
- * Offer transfer subject.
+ * Offer string subject.
*
* @param index index number associated with the transfer
* subject being offered.
- * @param transfer_subject transfer subject to offer.
+ * @param s string to offer.
* @return the trait.
*/
struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_transfer_subject (unsigned int index,
- const char *transfer_subject);
+TALER_TESTING_make_trait_string (unsigned int index,
+ const char *s);
/**
@@ -2223,7 +2203,6 @@ TALER_TESTING_get_trait_amount (const struct TALER_TESTING_Command *cmd,
* @param index which url is to be picked,
* in case multiple are offered.
* @param url the url to offer.
- *
* @return the trait.
*/
struct TALER_TESTING_Trait
diff --git a/src/include/taler_wire_lib.h b/src/include/taler_wire_lib.h
index 3c851091..c7d9f78d 100644
--- a/src/include/taler_wire_lib.h
+++ b/src/include/taler_wire_lib.h
@@ -22,7 +22,7 @@
#define TALER_WIRE_H
#include <gnunet/gnunet_util_lib.h>
-#include "taler_wire_plugin.h"
+
/**
* Different account types supported by payto://.
@@ -46,6 +46,7 @@ enum TALER_PaytoAccountType
TALER_PAC_IBAN
};
+
/**
* Information about an account extracted from a payto://-URL.
*/
@@ -71,19 +72,15 @@ struct TALER_Account
{
/**
- * Hostname of the bank (possibly including port).
+ * Bank account base URL.
*/
- char *hostname;
+ char *account_base_url;
/**
- * Bank account number.
+ * Only the hostname of the bank.
*/
- unsigned long long no;
+ char *hostname;
- /**
- * Base URL of the bank hosting the account above.
- */
- char *bank_base_url;
} x_taler_bank;
/**
@@ -114,6 +111,18 @@ TALER_WIRE_account_free (struct TALER_Account *acc);
/**
+ * Round the amount to something that can be
+ * transferred on the wire.
+ *
+ * @param[in,out] amount amount to round down
+ * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
+ * #GNUNET_SYSERR if the amount or currency was invalid
+ */
+int
+TALER_WIRE_amount_round (struct TALER_Amount *amount);
+
+
+/**
* Parse @a payto_url and store the result in @a acc
*
* @param payto_url URL to parse
@@ -135,36 +144,4 @@ char *
TALER_WIRE_payto_get_method (const char *payto_url);
-/**
- * Get the plugin name from the payment method.
- *
- * @param method the method implemented by the plugin (for
- * simplicity, we assume 1 method is implemented by 1 plugin).
- * @return the plugin name, NULL if not found.
- */
-const char *
-TALER_WIRE_get_plugin_from_method (const char *method);
-
-
-/**
- * Load a WIRE plugin.
- *
- * @param cfg configuration to use
- * @param plugin_name name of the plugin to load
- * @return #GNUNET_OK on success
- */
-struct TALER_WIRE_Plugin *
-TALER_WIRE_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const char *plugin_name);
-
-
-/**
- * Unload a WIRE plugin.
- *
- * @param plugin the plugin to unload
- */
-void
-TALER_WIRE_plugin_unload (struct TALER_WIRE_Plugin *plugin);
-
-
#endif
diff --git a/src/include/taler_wire_plugin.h b/src/include/taler_wire_plugin.h
index ffc7adf5..b5621e68 100644
--- a/src/include/taler_wire_plugin.h
+++ b/src/include/taler_wire_plugin.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2016, 2017 GNUnet e.V. & Inria
+ Copyright (C) 2016-2020 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
@@ -41,22 +41,9 @@ typedef void
/**
- * Callback to process a merchant registration outcome.
- *
- * @param cls closure
- * @param status GNUNET_OK if the registration succeeded,
- * GNUNET_NO otherwise.
- */
-typedef void
-(*TALER_WIRE_MerchantRegisterCallback) (void *cls,
- unsigned int status);
-
-/**
* Details about a valid wire transfer to the exchange.
- * It is the plugin's responsibility to filter and undo
- * invalid transfers.
*/
-struct TALER_WIRE_TransferDetails
+struct TALER_WIRE_CreditDetails
{
/**
* Amount that was transferred
@@ -69,22 +56,44 @@ struct TALER_WIRE_TransferDetails
struct GNUNET_TIME_Absolute execution_date;
/**
- * Binary data that was encoded in the wire transfer subject, if
- * it decoded properly. Otherwise all-zeros and @e wtid_s is set.
+ * Binary data that was encoded in the wire transfer subject.
*/
- struct TALER_WireTransferIdentifierRawP wtid;
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * payto://-URL of the source's account (used
+ * when the reserve is closed or for debugging).
+ */
+ const char *source_account_url;
+};
+
+
+/**
+ * Details about a valid wire transfer made by the
+ * exchange's aggregator to a merchant.
+ */
+struct TALER_WIRE_DebitDetails
+{
+ /**
+ * Amount that was transferred
+ */
+ struct TALER_Amount amount;
/**
- * Wire transfer identifer as a string. Set to NULL if the
- * identifier was properly Base32 encoded and this @e wtid could be
- * set instead.
+ * Time of the the transfer
+ */
+ struct GNUNET_TIME_Absolute execution_date;
+
+ /**
+ * Binary data that was encoded in the wire transfer subject.
*/
- char *wtid_s;
+ struct TALER_WireTransferIdentifierRawP wtid;
/**
- * payto://-URL of the other account that was involved
+ * payto://-URL of the target account which received
+ * the funds.
*/
- char *account_url;
+ const char *target_account_url;
};
@@ -96,33 +105,40 @@ struct TALER_WIRE_TransferDetails
*
* @param cls closure
* @param ec taler error code
- * @param dir direction of the transfer, #TALER_BANK_DIRECTION_NONE when
- * the iteration is complete
* @param row_off identification of the position at which we are querying
* @param row_off_size number of bytes in @a row_off
* @param details details about the wire transfer
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/
typedef int
-(*TALER_WIRE_HistoryResultCallback) (void *cls,
- enum TALER_ErrorCode ec,
- enum TALER_BANK_Direction dir,
- const void *row_off,
- size_t row_off_size,
- const struct
- TALER_WIRE_TransferDetails *details);
+(*TALER_WIRE_CreditResultCallback) (void *cls,
+ enum TALER_ErrorCode ec,
+ const void *row_off,
+ size_t row_off_size,
+ const struct
+ TALER_WIRE_CreditDetails *details);
/**
* Callbacks of this type are used to serve the result of asking
- * the bank to reject a wire transfer.
+ * the bank for the transaction history. NOTE: this function will
+ * NOT get the list of history elements, but rather get (iteratively)
+ * called for each (parsed) history element.
*
* @param cls closure
- * @param ec status of the operation, #TALER_EC_NONE on success
+ * @param ec taler error code
+ * @param row_off identification of the position at which we are querying
+ * @param row_off_size number of bytes in @a row_off
+ * @param details details about the wire transfer
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/
-typedef void
-(*TALER_WIRE_RejectTransferCallback) (void *cls,
- enum TALER_ErrorCode ec);
+typedef int
+(*TALER_WIRE_DebitResultCallback) (void *cls,
+ enum TALER_ErrorCode ec,
+ const void *row_off,
+ size_t row_off_size,
+ const struct
+ TALER_WIRE_DebitDetails *details);
/**
@@ -136,9 +152,14 @@ struct TALER_WIRE_PrepareHandle;
struct TALER_WIRE_ExecuteHandle;
/**
- * Handle returned for querying the transaction history.
+ * Handle returned for querying the credit transaction history.
*/
-struct TALER_WIRE_HistoryHandle;
+struct TALER_WIRE_CreditHistoryHandle;
+
+/**
+ * Handle returned for querying the debit transaction history.
+ */
+struct TALER_WIRE_DebitHistoryHandle;
/**
@@ -146,7 +167,8 @@ struct TALER_WIRE_HistoryHandle;
*
* @param cls closure
* @param success #GNUNET_OK on success, #GNUNET_SYSERR on failure
- * @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
+ * @param row_id unique ID of the wire transfer in the bank's records; NULL on error
+ * @param row_id_size number of bytes in @e row_id
* @param emsg NULL on success, otherwise an error message
*/
typedef void
@@ -156,6 +178,7 @@ typedef void
size_t row_id_size,
const char *emsg);
+
/**
* @brief The plugin API, returned from the plugin's "init" function.
* The argument given to "init" is simply a configuration handle.
@@ -176,11 +199,10 @@ struct TALER_WIRE_Plugin
/**
* Which wire method (payto://METHOD/") is supported by this plugin?
- * For example, "iban" or "x-taler-bank".
+ * For example, "x-taler-bank" or "iban".
*/
const char *method;
-
/**
* Round amount DOWN to the amount that can be transferred via the wire
* method. For example, Taler may support 0.000001 EUR as a unit of
@@ -210,80 +232,7 @@ struct TALER_WIRE_Plugin
/**
- * Prepare for exeuction of a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param origin_account_section configuration section specifying the origin
- * account of the exchange to use
- * @param destination_account_url payto:// URL identifying where to send the money
- * @param amount amount to transfer, already rounded
- * @param exchange_base_url base URL of this exchange (included in subject
- * to facilitate use of tracking API by merchant backend)
- * @param wtid wire transfer identifier to use
- * @param ptc function to call with the prepared data to persist
- * @param ptc_cls closure for @a ptc
- * @return NULL on failure
- */
- struct TALER_WIRE_PrepareHandle *
- (*prepare_wire_transfer) (void *cls,
- const char *origin_account_section,
- const char *destination_account_url,
- const struct TALER_Amount *amount,
- const char *exchange_base_url,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- TALER_WIRE_PrepareTransactionCallback ptc,
- void *ptc_cls);
-
-
- /**
- * Abort preparation of a wire transfer. For example,
- * because we are shutting down.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param pth preparation to cancel
- */
- void
- (*prepare_wire_transfer_cancel) (void *cls,
- struct TALER_WIRE_PrepareHandle *pth);
-
-
- /**
- * Execute a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param buf buffer with the prepared execution details
- * @param buf_size number of bytes in @a buf
- * @param cc function to call upon success
- * @param cc_cls closure for @a cc
- * @return NULL on error
- */
- struct TALER_WIRE_ExecuteHandle *
- (*execute_wire_transfer) (void *cls,
- const char *buf,
- size_t buf_size,
- TALER_WIRE_ConfirmationCallback cc,
- void *cc_cls);
-
-
- /**
- * Abort execution of a wire transfer. For example, because we are
- * shutting down. Note that if an execution is aborted, it may or
- * may not still succeed. The caller MUST run @e
- * execute_wire_transfer again for the same request as soon as
- * possilbe, to ensure that the request either ultimately succeeds
- * or ultimately fails. Until this has been done, the transaction is
- * in limbo (i.e. may or may not have been committed).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param eh execution to cancel
- */
- void
- (*execute_wire_transfer_cancel) (void *cls,
- struct TALER_WIRE_ExecuteHandle *eh);
-
-
- /**
- * Query transfer history of an account. We use the variable-size
+ * Query credits made to exchange account. We use the variable-size
* @a start_off to indicate which transfers we are interested in as
* different banking systems may have different ways to identify
* transfers. The @a start_off value must thus match the value of
@@ -295,7 +244,6 @@ struct TALER_WIRE_Plugin
* @param cls the @e cls of this struct with the plugin-specific state
* @param account_section specifies the configuration section which
* identifies the account for which we should get the history
- * @param direction what kinds of wire transfers should be returned
* @param start_off from which row on do we want to get results, use NULL for the latest; exclusive
* @param start_off_len number of bytes in @a start_off
* @param num_results how many results do we want; negative numbers to go into the past,
@@ -304,70 +252,65 @@ struct TALER_WIRE_Plugin
* @param hres_cb the callback to call with the transaction history
* @param hres_cb_cls closure for the above callback
*/
- struct TALER_WIRE_HistoryHandle *
- (*get_history) (void *cls,
+ struct TALER_WIRE_CreditHistoryHandle *
+ (*get_credits) (void *cls,
const char *account_section,
- enum TALER_BANK_Direction direction,
const void *start_off,
size_t start_off_len,
int64_t num_results,
- TALER_WIRE_HistoryResultCallback hres_cb,
+ TALER_WIRE_CreditResultCallback hres_cb,
void *hres_cb_cls);
/**
* Cancel going over the account's history.
*
* @param cls plugins' closure
- * @param whh operation to cancel
+ * @param chh operation to cancel
*/
void
- (*get_history_cancel) (void *cls,
- struct TALER_WIRE_HistoryHandle *whh);
+ (*get_credits_cancel) (void *cls,
+ struct TALER_WIRE_CreditHistoryHandle *chh);
/**
- * Reject an incoming wire transfer that was obtained from the
- * history. This function can be used to transfer funds back to
- * the sender if the WTID was malformed (i.e. due to a typo).
- *
- * Calling `reject_transfer` twice on the same wire transfer should
- * be idempotent, i.e. not cause the funds to be wired back twice.
- * Furthermore, the transfer should henceforth be removed from the
- * results returned by @e get_history.
+ * Query debits (transfers to merchants) made by an exchange. We use the
+ * variable-size @a start_off to indicate which transfers we are interested
+ * in as different banking systems may have different ways to identify
+ * transfers. The @a start_off value must thus match the value of a
+ * `row_off` argument previously given to the @a hres_cb. Use NULL to query
+ * transfers from the beginning of time (with positive @a num_results) or
+ * from the latest committed transfers (with negative @a num_results).
*
- * @param cls plugin's closure
+ * @param cls the @e cls of this struct with the plugin-specific state
* @param account_section specifies the configuration section which
- * identifies the account to use to reject the transfer
- * @param start_off offset of the wire transfer in plugin-specific format
+ * identifies the account for which we should get the history
+ * @param start_off from which row on do we want to get results, use NULL for the latest; exclusive
* @param start_off_len number of bytes in @a start_off
- * @param rej_cb function to call with the result of the operation
- * @param rej_cb_cls closure for @a rej_cb
- * @return handle to cancel the operation
+ * @param num_results how many results do we want; negative numbers to go into the past,
+ * positive numbers to go into the future starting at @a start_row;
+ * must not be zero.
+ * @param hres_cb the callback to call with the transaction history
+ * @param hres_cb_cls closure for the above callback
*/
- struct TALER_WIRE_RejectHandle *
- (*reject_transfer)(void *cls,
- const char *account_section,
- const void *start_off,
- size_t start_off_len,
- TALER_WIRE_RejectTransferCallback rej_cb,
- void *rej_cb_cls);
-
+ struct TALER_WIRE_DebitHistoryHandle *
+ (*get_debits) (void *cls,
+ const char *account_section,
+ const void *start_off,
+ size_t start_off_len,
+ int64_t num_results,
+ TALER_WIRE_DebitResultCallback hres_cb,
+ void *hres_cb_cls);
/**
- * Cancel ongoing reject operation. Note that the rejection may still
- * proceed. Basically, if this function is called, the rejection may
- * have happened or not. This function is usually used during shutdown
- * or system upgrades. At a later point, the application must call
- * @e reject_transfer again for this wire transfer, unless the
- * @e get_history shows that the wire transfer no longer exists.
+ * Cancel going over the account's history.
*
* @param cls plugins' closure
- * @param rh operation to cancel
- * @return closure of the callback of the operation
+ * @param dhh operation to cancel
*/
- void *
- (*reject_transfer_cancel)(void *cls,
- struct TALER_WIRE_RejectHandle *rh);
+ void
+ (*get_debits_cancel) (void *cls,
+ struct TALER_WIRE_DebitHistoryHandle *dhh);
+
};
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index de0c8935..ee8389f6 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -103,6 +103,7 @@ libtalertesting_la_SOURCES = \
testing_api_trait_exchange_sig.c \
testing_api_trait_json.c \
testing_api_trait_process.c \
+ testing_api_trait_reserve_pub.c \
testing_api_trait_reserve_priv.c \
testing_api_trait_number.c \
testing_api_trait_fresh_coin.c \
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index abb95816..6b51519f 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -1262,7 +1262,7 @@ keys_completed_cb (void *cls,
for (unsigned int i = 0; i<kd_old.num_denom_keys; i++)
kd.denom_keys[i].key.rsa_public_key
= GNUNET_CRYPTO_rsa_public_key_dup (
- kd_old.denom_keys[i].key.rsa_public_key);
+ kd_old.denom_keys[i].key.rsa_public_key);
kd.num_auditors = kd_old.num_auditors;
kd.auditors = GNUNET_new_array (kd.num_auditors,
diff --git a/src/lib/testing_api_cmd_bank_check.c b/src/lib/testing_api_cmd_bank_check.c
index f51c535a..f74f7afe 100644
--- a/src/lib/testing_api_cmd_bank_check.c
+++ b/src/lib/testing_api_cmd_bank_check.c
@@ -52,12 +52,12 @@ struct BankCheckState
/**
* Expected debit bank account.
*/
- uint64_t debit_account;
+ const char *debit_account;
/**
* Expected credit bank account.
*/
- uint64_t credit_account;
+ const char *credit_account;
/**
* Wire transfer subject (set by fakebank-lib).
@@ -95,18 +95,16 @@ check_bank_transfer_run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
struct BankCheckState *bcs = cls;
-
struct TALER_Amount amount;
- const uint64_t *debit_account;
- const uint64_t *credit_account;
+ const char *debit_account;
+ const char *credit_account;
const char *exchange_base_url;
-
if (NULL == bcs->deposit_reference)
{
TALER_LOG_INFO ("Deposit reference NOT given\n");
- debit_account = &bcs->debit_account;
- credit_account = &bcs->credit_account;
+ debit_account = bcs->debit_account;
+ credit_account = bcs->credit_account;
exchange_base_url = bcs->exchange_base_url;
if (GNUNET_OK !=
@@ -154,14 +152,13 @@ check_bank_transfer_run (void *cls,
GNUNET_assert
(GNUNET_OK == TALER_TESTING_get_trait_url
(deposit_cmd, 0, &exchange_base_url)); // check 0 works!
-
}
if (GNUNET_OK !=
TALER_FAKEBANK_check (is->fakebank,
&amount,
- *debit_account,
- *credit_account,
+ debit_account,
+ credit_account,
exchange_base_url,
&bcs->subject))
{
@@ -217,18 +214,18 @@ check_bank_transfer_traits (void *cls,
wtid_ptr = NULL;
else
wtid_ptr = &bcs->wtid;
-
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_transfer_subject (0, bcs->subject),
- TALER_TESTING_make_trait_wtid (0, wtid_ptr),
- TALER_TESTING_make_trait_url (0, bcs->exchange_base_url),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
+ {
+ struct TALER_TESTING_Trait traits[] = {
+ TALER_TESTING_make_trait_wtid (0, wtid_ptr),
+ TALER_TESTING_make_trait_url (0, bcs->exchange_base_url),
+ TALER_TESTING_trait_end ()
+ };
+
+ return TALER_TESTING_get_trait (traits,
+ ret,
+ trait,
+ index);
+ }
}
@@ -250,8 +247,8 @@ TALER_TESTING_cmd_check_bank_transfer
(const char *label,
const char *exchange_base_url,
const char *amount,
- uint64_t debit_account,
- uint64_t credit_account)
+ const char *debit_account,
+ const char *credit_account)
{
struct BankCheckState *bcs;
@@ -260,18 +257,18 @@ TALER_TESTING_cmd_check_bank_transfer
bcs->amount = amount;
bcs->debit_account = debit_account;
bcs->credit_account = credit_account;
-
bcs->deposit_reference = NULL;
-
- struct TALER_TESTING_Command cmd = {
- .label = label,
- .cls = bcs,
- .run = &check_bank_transfer_run,
- .cleanup = &check_bank_transfer_cleanup,
- .traits = &check_bank_transfer_traits
- };
-
- return cmd;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .label = label,
+ .cls = bcs,
+ .run = &check_bank_transfer_run,
+ .cleanup = &check_bank_transfer_cleanup,
+ .traits = &check_bank_transfer_traits
+ };
+
+ return cmd;
+ }
}
diff --git a/src/lib/testing_api_cmd_fakebank_transfer.c b/src/lib/testing_api_cmd_fakebank_transfer.c
index 81378238..e212fd31 100644
--- a/src/lib/testing_api_cmd_fakebank_transfer.c
+++ b/src/lib/testing_api_cmd_fakebank_transfer.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
+ Copyright (C) 2018-2020 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
@@ -51,24 +51,14 @@ struct FakebankTransferState
struct TALER_Amount amount;
/**
- * Wire transfer subject.
+ * Base URL of the debit account.
*/
- const char *subject;
+ const char *debit_url;
/**
- * Base URL of the bank serving the request.
+ * Money receiver account URL.
*/
- const char *bank_url;
-
- /**
- * Money sender account number.
- */
- uint64_t debit_account_no;
-
- /**
- * Money receiver account number.
- */
- uint64_t credit_account_no;
+ const char *payto_credit_account;
/**
* Username to use for authentication.
@@ -87,6 +77,11 @@ struct FakebankTransferState
struct TALER_ReservePrivateKeyP reserve_priv;
/**
+ * Reserve public key matching @e reserve_priv.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
* Handle to the pending request at the fakebank.
*/
struct TALER_BANK_AdminAddIncomingHandle *aih;
@@ -188,16 +183,15 @@ do_retry (void *cls)
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param serial_id unique ID of the wire transfer
* @param timestamp time stamp of the transaction made.
- * @param full_response full response from the exchange (for
- * logging, in case of errors)
+ * @param json raw response
*/
static void
-add_incoming_cb (void *cls,
+confirmation_cb (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t serial_id,
struct GNUNET_TIME_Absolute timestamp,
- const json_t *full_response)
+ const json_t *json)
{
struct FakebankTransferState *fts = cls;
struct TALER_TESTING_Interpreter *is = fts->is;
@@ -256,130 +250,115 @@ fakebank_transfer_run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
struct FakebankTransferState *fts = cls;
- char *subject;
struct TALER_BANK_AuthenticationData auth;
- struct TALER_ReservePublicKeyP reserve_pub;
- if (NULL != fts->subject)
+ /* Use reserve public key as subject */
+ if (NULL != fts->reserve_reference)
{
- subject = GNUNET_strdup (fts->subject);
+ const struct TALER_TESTING_Command *ref;
+ const struct TALER_ReservePrivateKeyP *reserve_priv;
+
+ ref = TALER_TESTING_interpreter_lookup_command
+ (is, fts->reserve_reference);
+ if (NULL == ref)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (is);
+ return;
+ }
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_reserve_priv (ref,
+ 0,
+ &reserve_priv))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (is);
+ return;
+ }
+ fts->reserve_priv.eddsa_priv = reserve_priv->eddsa_priv;
}
else
{
- /* Use reserve public key as subject */
- if (NULL != fts->reserve_reference)
+ if (NULL != fts->instance)
{
- const struct TALER_TESTING_Command *ref;
- const struct TALER_ReservePrivateKeyP *reserve_priv;
+ char *section;
+ char *keys;
+ struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+ struct GNUNET_CONFIGURATION_Handle *cfg;
- ref = TALER_TESTING_interpreter_lookup_command
- (is, fts->reserve_reference);
- if (NULL == ref)
+ GNUNET_assert (NULL != fts->config_filename);
+ cfg = GNUNET_CONFIGURATION_create ();
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_load (cfg,
+ fts->config_filename))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
+
+ GNUNET_asprintf (&section,
+ "instance-%s",
+ fts->instance);
if (GNUNET_OK !=
- TALER_TESTING_get_trait_reserve_priv (ref,
- 0,
- &reserve_priv))
+ GNUNET_CONFIGURATION_get_value_filename
+ (cfg,
+ section,
+ "TIP_RESERVE_PRIV_FILENAME",
+ &keys))
{
- GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Configuration fails to specify reserve"
+ " private key filename in section %s\n",
+ section);
+ GNUNET_free (section);
TALER_TESTING_interpreter_fail (is);
return;
}
- fts->reserve_priv.eddsa_priv = reserve_priv->eddsa_priv;
- }
- else
- {
- if (NULL != fts->instance)
+ priv = GNUNET_CRYPTO_eddsa_key_create_from_file (keys);
+ GNUNET_free (keys);
+ if (NULL == priv)
{
- char *section;
- char *keys;
- struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
- struct GNUNET_CONFIGURATION_Handle *cfg;
-
- GNUNET_assert (NULL != fts->config_filename);
- cfg = GNUNET_CONFIGURATION_create ();
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_load (cfg,
- fts->config_filename))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_asprintf (&section,
- "instance-%s",
- fts->instance);
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename
- (cfg,
- section,
- "TIP_RESERVE_PRIV_FILENAME",
- &keys))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Configuration fails to specify reserve"
- " private key filename in section %s\n",
- section);
- GNUNET_free (section);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- priv = GNUNET_CRYPTO_eddsa_key_create_from_file (keys);
- GNUNET_free (keys);
- if (NULL == priv)
- {
- GNUNET_log_config_invalid
- (GNUNET_ERROR_TYPE_ERROR,
- section,
- "TIP_RESERVE_PRIV_FILENAME",
- "Failed to read private key");
- GNUNET_free (section);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- fts->reserve_priv.eddsa_priv = *priv;
+ GNUNET_log_config_invalid
+ (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "TIP_RESERVE_PRIV_FILENAME",
+ "Failed to read private key");
GNUNET_free (section);
- GNUNET_free (priv);
- GNUNET_CONFIGURATION_destroy (cfg);
+ TALER_TESTING_interpreter_fail (is);
+ return;
}
- else
- {
- /* No referenced reserve, no instance to take priv
- * from, no explicit subject given: create new key! */
- struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+ fts->reserve_priv.eddsa_priv = *priv;
+ GNUNET_free (section);
+ GNUNET_free (priv);
+ GNUNET_CONFIGURATION_destroy (cfg);
+ }
+ else
+ {
+ /* No referenced reserve, no instance to take priv
+ * from, no explicit subject given: create new key! */
+ struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
- priv = GNUNET_CRYPTO_eddsa_key_create ();
- fts->reserve_priv.eddsa_priv = *priv;
- GNUNET_free (priv);
- }
+ priv = GNUNET_CRYPTO_eddsa_key_create ();
+ fts->reserve_priv.eddsa_priv = *priv;
+ GNUNET_free (priv);
}
- GNUNET_CRYPTO_eddsa_key_get_public
- (&fts->reserve_priv.eddsa_priv, &reserve_pub.eddsa_pub);
- subject = GNUNET_STRINGS_data_to_string_alloc
- (&reserve_pub, sizeof (reserve_pub));
}
-
+ GNUNET_CRYPTO_eddsa_key_get_public (&fts->reserve_priv.eddsa_priv,
+ &fts->reserve_pub.eddsa_pub);
auth.method = TALER_BANK_AUTH_BASIC;
auth.details.basic.username = (char *) fts->auth_username;
auth.details.basic.password = (char *) fts->auth_password;
fts->is = is;
fts->aih = TALER_BANK_admin_add_incoming
(TALER_TESTING_interpreter_get_context (is),
- fts->bank_url,
+ fts->debit_url,
&auth,
- fts->exchange_url,
- subject,
+ &fts->reserve_pub,
&fts->amount,
- fts->debit_account_no,
- fts->credit_account_no,
- &add_incoming_cb,
+ fts->payto_credit_account,
+ &confirmation_cb,
fts);
- GNUNET_free (subject);
if (NULL == fts->aih)
{
GNUNET_break (0);
@@ -408,6 +387,7 @@ fakebank_transfer_cleanup (void *cls,
"Command %s did not complete\n",
cmd->label);
TALER_BANK_admin_add_incoming_cancel (fts->aih);
+ fts->aih = NULL;
}
if (NULL != fts->retry_task)
{
@@ -435,32 +415,21 @@ fakebank_transfer_traits (void *cls,
unsigned int index)
{
struct FakebankTransferState *fts = cls;
- #define MANDATORY 7
- struct TALER_TESTING_Trait traits[MANDATORY + 1] = {
- TALER_TESTING_MAKE_TRAIT_DEBIT_ACCOUNT
- (&fts->debit_account_no),
- TALER_TESTING_MAKE_TRAIT_CREDIT_ACCOUNT
- (&fts->credit_account_no),
+ struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_url (0, fts->exchange_url),
+ TALER_TESTING_make_trait_url (1, fts->debit_url),
TALER_TESTING_MAKE_TRAIT_ROW_ID (&fts->serial_id),
+ TALER_TESTING_MAKE_TRAIT_CREDIT_ACCOUNT (fts->payto_credit_account),
+ TALER_TESTING_MAKE_TRAIT_DEBIT_ACCOUNT (fts->debit_url),
TALER_TESTING_make_trait_amount_obj (0, &fts->amount),
- TALER_TESTING_make_trait_absolute_time (0, &fts->timestamp)
+ TALER_TESTING_make_trait_absolute_time (0, &fts->timestamp),
+ TALER_TESTING_make_trait_reserve_priv (0,
+ &fts->reserve_priv),
+ TALER_TESTING_make_trait_reserve_pub (0,
+ &fts->reserve_pub),
+ TALER_TESTING_trait_end ()
};
- /**
- * The user gave explicit subject,
- * there must be NO reserve priv. */
- if (NULL != fts->subject)
- traits[MANDATORY - 1] =
- TALER_TESTING_make_trait_transfer_subject (0,
- fts->subject);
- /* A reserve priv must exist if no subject was given. */
- else
- traits[MANDATORY - 1] = TALER_TESTING_make_trait_reserve_priv
- (0, &fts->reserve_priv),
-
- traits[MANDATORY] = TALER_TESTING_trait_end ();
-
return TALER_TESTING_get_trait (traits,
ret,
trait,
@@ -475,27 +444,21 @@ fakebank_transfer_traits (void *cls,
*
* @param label command label.
* @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- * wire transer. For simplicity, both credit and debit
- * bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- * gives money.
- * @param credit_account_no which account (expressed as a number)
- * receives money.
+ * @param account_base_url base URL of the account that implements this
+ * wire transer (which account gives money).
+ * @param payto_credit_account which account receives money.
* @param auth_username username identifying the @a
* debit_account_no at the bank.
* @param auth_password password for @a auth_username.
* @param exchange_url which exchange is involved in this transfer.
- *
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_fakebank_transfer
(const char *label,
const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
+ const char *account_base_url,
+ const char *payto_credit_account,
const char *auth_username,
const char *auth_password,
const char *exchange_url)
@@ -503,9 +466,8 @@ TALER_TESTING_cmd_fakebank_transfer
struct FakebankTransferState *fts;
fts = GNUNET_new (struct FakebankTransferState);
- fts->bank_url = bank_url;
- fts->credit_account_no = credit_account_no;
- fts->debit_account_no = debit_account_no;
+ fts->debit_url = account_base_url;
+ fts->payto_credit_account = payto_credit_account;
fts->auth_username = auth_username;
fts->auth_password = auth_password;
fts->exchange_url = exchange_url;
@@ -520,87 +482,17 @@ TALER_TESTING_cmd_fakebank_transfer
GNUNET_assert (0);
}
- struct TALER_TESTING_Command cmd = {
- .cls = fts,
- .label = label,
- .run = &fakebank_transfer_run,
- .cleanup = &fakebank_transfer_cleanup,
- .traits = &fakebank_transfer_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Create "fakebank transfer" CMD, letting the caller specifying
- * the subject line.
- *
- * @param label command label.
- * @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- * wire transer. For simplicity, both credit and debit
- * bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- * gives money.
- * @param credit_account_no which account (expressed as a number)
- * receives money.
- *
- * @param auth_username username identifying the @a
- * debit_account_no at the bank.
- * @param auth_password password for @a auth_username.
- * @param subject wire transfer's subject line.
- * @param exchange_url which exchange is involved in this transfer.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_with_subject
- (const char *label,
- const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
- const char *auth_username,
- const char *auth_password,
- const char *subject,
- const char *exchange_url)
-{
- struct FakebankTransferState *fts;
-
- fts = GNUNET_new (struct FakebankTransferState);
-
- TALER_LOG_DEBUG ("%s:FTS@%p\n",
- label,
- fts);
-
- fts->bank_url = bank_url;
- fts->credit_account_no = credit_account_no;
- fts->debit_account_no = debit_account_no;
- fts->auth_username = auth_username;
- fts->auth_password = auth_password;
- fts->subject = subject;
- fts->exchange_url = exchange_url;
- if (GNUNET_OK !=
- TALER_string_to_amount (amount,
- &fts->amount))
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %s\n",
- amount,
- label);
- GNUNET_assert (0);
+ struct TALER_TESTING_Command cmd = {
+ .cls = fts,
+ .label = label,
+ .run = &fakebank_transfer_run,
+ .cleanup = &fakebank_transfer_cleanup,
+ .traits = &fakebank_transfer_traits
+ };
+
+ return cmd;
}
-
- struct TALER_TESTING_Command cmd = {
- .cls = fts,
- .label = label,
- .run = &fakebank_transfer_run,
- .cleanup = &fakebank_transfer_cleanup,
- .traits = &fakebank_transfer_traits
- };
-
- return cmd;
}
@@ -631,9 +523,8 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_fakebank_transfer_with_ref
(const char *label,
const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
+ const char *account_base_url,
+ const char *payto_credit_account,
const char *auth_username,
const char *auth_password,
const char *ref,
@@ -642,9 +533,8 @@ TALER_TESTING_cmd_fakebank_transfer_with_ref
struct FakebankTransferState *fts;
fts = GNUNET_new (struct FakebankTransferState);
- fts->bank_url = bank_url;
- fts->credit_account_no = credit_account_no;
- fts->debit_account_no = debit_account_no;
+ fts->debit_url = account_base_url;
+ fts->payto_credit_account = payto_credit_account;
fts->auth_username = auth_username;
fts->auth_password = auth_password;
fts->reserve_reference = ref;
@@ -659,16 +549,17 @@ TALER_TESTING_cmd_fakebank_transfer_with_ref
label);
GNUNET_assert (0);
}
-
- struct TALER_TESTING_Command cmd = {
- .cls = fts,
- .label = label,
- .run = &fakebank_transfer_run,
- .cleanup = &fakebank_transfer_cleanup,
- .traits = &fakebank_transfer_traits
- };
-
- return cmd;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = fts,
+ .label = label,
+ .run = &fakebank_transfer_run,
+ .cleanup = &fakebank_transfer_cleanup,
+ .traits = &fakebank_transfer_traits
+ };
+
+ return cmd;
+ }
}
@@ -705,9 +596,8 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_fakebank_transfer_with_instance
(const char *label,
const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
+ const char *account_base_url,
+ const char *payto_credit_account,
const char *auth_username,
const char *auth_password,
const char *instance,
@@ -717,9 +607,8 @@ TALER_TESTING_cmd_fakebank_transfer_with_instance
struct FakebankTransferState *fts;
fts = GNUNET_new (struct FakebankTransferState);
- fts->bank_url = bank_url;
- fts->credit_account_no = credit_account_no;
- fts->debit_account_no = debit_account_no;
+ fts->debit_url = account_base_url;
+ fts->payto_credit_account = payto_credit_account;
fts->auth_username = auth_username;
fts->auth_password = auth_password;
fts->instance = instance;
@@ -735,16 +624,17 @@ TALER_TESTING_cmd_fakebank_transfer_with_instance
label);
GNUNET_assert (0);
}
-
- struct TALER_TESTING_Command cmd = {
- .cls = fts,
- .label = label,
- .run = &fakebank_transfer_run,
- .cleanup = &fakebank_transfer_cleanup,
- .traits = &fakebank_transfer_traits
- };
-
- return cmd;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = fts,
+ .label = label,
+ .run = &fakebank_transfer_run,
+ .cleanup = &fakebank_transfer_cleanup,
+ .traits = &fakebank_transfer_traits
+ };
+
+ return cmd;
+ }
}
diff --git a/src/lib/testing_api_cmd_status.c b/src/lib/testing_api_cmd_status.c
index 398221a1..2da404fb 100644
--- a/src/lib/testing_api_cmd_status.c
+++ b/src/lib/testing_api_cmd_status.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
+ Copyright (C) 2014-2020 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
@@ -146,6 +146,7 @@ status_run (void *cls,
const struct TALER_TESTING_Command *create_reserve;
const struct TALER_ReservePrivateKeyP *reserve_priv;
struct TALER_ReservePublicKeyP reserve_pub;
+ const struct TALER_ReservePublicKeyP *reserve_pubp;
ss->is = is;
GNUNET_assert (NULL != ss->reserve_reference);
@@ -163,44 +164,31 @@ status_run (void *cls,
/* NOTE: the following line might generate a ERROR log
* statements, but it can be ignored. */
- if (GNUNET_OK == TALER_TESTING_get_trait_reserve_priv
- (create_reserve,
- 0,
- &reserve_priv))
+ if (GNUNET_OK ==
+ TALER_TESTING_get_trait_reserve_priv (create_reserve,
+ 0,
+ &reserve_priv))
{
GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
&reserve_pub.eddsa_pub);
+ reserve_pubp = &reserve_pub;
}
else
{
- const char *transfer_subject;
-
- if (GNUNET_OK != TALER_TESTING_get_trait_transfer_subject
- (create_reserve,
- 0,
- &transfer_subject))
- {
- GNUNET_break (0);
- TALER_LOG_ERROR ("The reserve has neither a priv nor a subject line.\n");
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (transfer_subject,
- strlen (transfer_subject),
- &reserve_pub.eddsa_pub,
- sizeof (struct TALER_ReservePublicKeyP)))
+ TALER_TESTING_get_trait_reserve_pub (create_reserve,
+ 0,
+ &reserve_pubp))
{
GNUNET_break (0);
- TALER_LOG_ERROR ("Transfer subject is not a public key.\n");
+ TALER_LOG_ERROR ("The reserve has neither a priv nor a pub.\n");
TALER_TESTING_interpreter_fail (is);
return;
}
}
ss->rsh = TALER_EXCHANGE_reserve_status (is->exchange,
- &reserve_pub,
+ reserve_pubp,
&reserve_status_cb,
ss);
}
diff --git a/src/lib/testing_api_cmd_track.c b/src/lib/testing_api_cmd_track.c
index 41c6be17..070218cf 100644
--- a/src/lib/testing_api_cmd_track.c
+++ b/src/lib/testing_api_cmd_track.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
+ Copyright (C) 2014-2020 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
@@ -190,15 +190,11 @@ deposit_wtid_cb
if (NULL != tts->bank_transfer_reference)
{
const struct TALER_TESTING_Command *bank_transfer_cmd;
- char *ws;
+ const struct TALER_WireTransferIdentifierRawP *wtid_want;
/* _this_ wire transfer subject line. */
- ws = GNUNET_STRINGS_data_to_string_alloc (wtid,
- sizeof (*wtid));
-
bank_transfer_cmd = TALER_TESTING_interpreter_lookup_command
(is, tts->bank_transfer_reference);
-
if (NULL == bank_transfer_cmd)
{
GNUNET_break (0);
@@ -206,12 +202,9 @@ deposit_wtid_cb
return;
}
- /* expected wire transfer subject line. */
- const char *transfer_subject;
-
if (GNUNET_OK !=
- TALER_TESTING_get_trait_transfer_subject
- (bank_transfer_cmd, 0, &transfer_subject))
+ TALER_TESTING_get_trait_wtid
+ (bank_transfer_cmd, 0, &wtid_want))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
@@ -219,15 +212,13 @@ deposit_wtid_cb
}
/* Compare that expected and gotten subjects match. */
- if (0 != strcmp (ws, transfer_subject))
+ if (0 != GNUNET_memcmp (wtid,
+ wtid_want))
{
GNUNET_break (0);
- GNUNET_free (ws);
TALER_TESTING_interpreter_fail (tts->is);
return;
}
-
- GNUNET_free (ws);
}
break;
case MHD_HTTP_ACCEPTED:
diff --git a/src/lib/testing_api_trait_reserve_pub.c b/src/lib/testing_api_trait_reserve_pub.c
new file mode 100644
index 00000000..b9cd070d
--- /dev/null
+++ b/src/lib/testing_api_trait_reserve_pub.c
@@ -0,0 +1,77 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2018-2020 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 exchange-lib/testing_api_trait_reserve_pub.c
+ * @brief implements reserve public key trait
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "exchange_api_handle.h"
+#include "taler_signatures.h"
+#include "taler_testing_lib.h"
+
+#define TALER_TESTING_TRAIT_RESERVE_PUBLIC_KEY \
+ "reserve-public-key"
+
+/**
+ * Obtain a reserve public key from a @a cmd.
+ *
+ * @param cmd command to extract the reserve pub from.
+ * @param index reserve pub's index number.
+ * @param reserve_pub[out] set to the reserve pub.
+ * @return #GNUNET_OK on success.
+ */
+int
+TALER_TESTING_get_trait_reserve_pub
+ (const struct TALER_TESTING_Command *cmd,
+ unsigned int index,
+ const struct TALER_ReservePublicKeyP **reserve_pub)
+{
+ return cmd->traits (cmd->cls,
+ (const void **) reserve_pub,
+ TALER_TESTING_TRAIT_RESERVE_PUBLIC_KEY,
+ index);
+}
+
+
+/**
+ * Offer a reserve public key.
+ *
+ * @param index reserve pub's index number.
+ * @param reserve_pub reserve public key to offer.
+ * @return the trait.
+ */
+struct TALER_TESTING_Trait
+TALER_TESTING_make_trait_reserve_pub
+ (unsigned int index,
+ const struct TALER_ReservePublicKeyP *reserve_pub)
+{
+ struct TALER_TESTING_Trait ret = {
+ .index = index,
+ .trait_name = TALER_TESTING_TRAIT_RESERVE_PUBLIC_KEY,
+ .ptr = (const void *) reserve_pub
+ };
+ return ret;
+}
+
+
+/* end of testing_api_trait_reserve_pub.c */
diff --git a/src/lib/testing_api_trait_string.c b/src/lib/testing_api_trait_string.c
index 8d3d5df0..b9f57ab7 100644
--- a/src/lib/testing_api_trait_string.c
+++ b/src/lib/testing_api_trait_string.c
@@ -30,7 +30,7 @@
#include "taler_testing_lib.h"
#define TALER_TESTING_TRAIT_CONTRACT_TERMS "contract-terms"
-#define TALER_TESTING_TRAIT_TRANSFER_SUBJECT "transfer-subject"
+#define TALER_TESTING_TRAIT_STRING "string"
#define TALER_TESTING_TRAIT_AMOUNT "amount"
#define TALER_TESTING_TRAIT_URL "url"
#define TALER_TESTING_TRAIT_ORDER_ID "order-id"
@@ -80,46 +80,45 @@ TALER_TESTING_make_trait_contract_terms
/**
- * Obtain a transfer subject from @a cmd.
+ * Obtain a string from @a cmd.
*
* @param cmd command to extract the subject from.
* @param index index number associated with the transfer
* subject to offer.
- * @param transfer_subject[out] where to write the offered
- * transfer subject.
+ * @param s[out] where to write the offered
+ * string
* @return #GNUNET_OK on success.
*/
int
-TALER_TESTING_get_trait_transfer_subject
+TALER_TESTING_get_trait_string
(const struct TALER_TESTING_Command *cmd,
unsigned int index,
- const char **transfer_subject)
+ const char **s)
{
return cmd->traits (cmd->cls,
- (const void **) transfer_subject,
- TALER_TESTING_TRAIT_TRANSFER_SUBJECT,
+ (const void **) s,
+ TALER_TESTING_TRAIT_STRING,
index);
}
/**
- * Offer transfer subject.
+ * Offer string.
*
* @param index index number associated with the transfer
* subject being offered.
- * @param transfer_subject transfer subject to offer.
- *
+ * @param s transfer subject to offer.
* @return the trait.
*/
struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_transfer_subject
+TALER_TESTING_make_trait_string
(unsigned int index,
- const char *transfer_subject)
+ const char *s)
{
struct TALER_TESTING_Trait ret = {
.index = index,
- .trait_name = TALER_TESTING_TRAIT_TRANSFER_SUBJECT,
- .ptr = (const void *) transfer_subject
+ .trait_name = TALER_TESTING_TRAIT_STRING,
+ .ptr = (const void *) s
};
return ret;
}
diff --git a/src/wire-plugins/Makefile.am b/src/wire-plugins/Makefile.am
deleted file mode 100644
index 6d5b3e8b..00000000
--- a/src/wire-plugins/Makefile.am
+++ /dev/null
@@ -1,81 +0,0 @@
-# This Makefile.am is in the public domain
-AM_CPPFLAGS = -I$(top_srcdir)/src/include
-
-if USE_COVERAGE
- AM_CFLAGS = --coverage -O0
- XLIB = -lgcov
-endif
-
-pkgcfgdir = $(prefix)/share/taler/config.d/
-
-EXTRA_DIST = \
- test_wire_plugin.conf \
- test_wire_plugin_transactions_taler-bank.conf
-
-plugindir = $(libdir)/taler
-
-if HAVE_LIBCURL
-plugin_LTLIBRARIES = \
- libtaler_plugin_wire_taler_bank.la
-else
-if HAVE_LIBGNURL
-plugin_LTLIBRARIES = \
- libtaler_plugin_wire_taler_bank.la
-endif
-endif
-
-noinst_LTLIBRARIES = \
- libtaler_plugin_wire_template.la
-
-
-libtaler_plugin_wire_taler_bank_la_SOURCES = \
- plugin_wire_taler-bank.c
-libtaler_plugin_wire_taler_bank_la_LIBADD = \
- $(LTLIBINTL)
-libtaler_plugin_wire_taler_bank_la_LDFLAGS = \
- $(TALER_PLUGIN_LDFLAGS) \
- $(top_builddir)/src/bank-lib/libtalerbank.la \
- $(top_builddir)/src/json/libtalerjson.la \
- $(top_builddir)/src/wire/libtalerwire.la \
- $(top_builddir)/src/util/libtalerutil.la \
- -lgnunetcurl \
- -lgnunetutil $(XLIB)
-
-
-libtaler_plugin_wire_template_la_SOURCES = \
- plugin_wire_template.c
-libtaler_plugin_wire_template_la_LIBADD = \
- $(LTLIBINTL)
-libtaler_plugin_wire_template_la_LDFLAGS = \
- $(TALER_PLUGIN_LDFLAGS) \
- $(top_builddir)/src/util/libtalerutil.la \
- -lgnunetutil $(XLIB)
-
-
-AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
-
-TESTS = \
- test_wire_plugin \
- test_wire_plugin_transactions_taler_bank
-
-check_PROGRAMS= $(TESTS)
-
-
-test_wire_plugin_SOURCES = \
- test_wire_plugin.c
-test_wire_plugin_LDADD = \
- -lgnunetutil \
- $(top_builddir)/src/wire/libtalerwire.la \
- $(top_builddir)/src/util/libtalerutil.la
-
-
-test_wire_plugin_transactions_taler_bank_SOURCES = \
- test_wire_plugin_transactions_taler-bank.c
-test_wire_plugin_transactions_taler_bank_LDADD = \
- -lgnunetjson \
- -lgnunetutil \
- -ljansson \
- $(top_builddir)/src/wire/libtalerwire.la \
- $(top_builddir)/src/bank-lib/libtalerbank.la \
- $(top_builddir)/src/bank-lib/libtalerfakebank.la \
- $(top_builddir)/src/util/libtalerutil.la
diff --git a/src/wire-plugins/plugin_wire_taler-bank.c b/src/wire-plugins/plugin_wire_taler-bank.c
deleted file mode 100644
index ad8daa4e..00000000
--- a/src/wire-plugins/plugin_wire_taler-bank.c
+++ /dev/null
@@ -1,1306 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2017, 2018 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 plugin_wire_taler_bank.c
- * @brief plugin for the "x-taler-bank" wire method
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_wire_plugin.h"
-#include "taler_json_lib.h"
-#include "taler_wire_lib.h"
-#include "taler_bank_service.h"
-#include "taler_signatures.h"
-#include <gnunet/gnunet_curl_lib.h>
-
-/* only for HTTP status codes */
-#include <microhttpd.h>
-
-/**
- * Type of the "cls" argument given to each of the functions in
- * our API.
- */
-struct TalerBankClosure
-{
-
- /**
- * Which currency do we support?
- */
- char *currency;
-
- /**
- * Handle to the context for sending funds to the bank.
- */
- struct GNUNET_CURL_Context *ctx;
-
- /**
- * Scheduler context for running the @e ctx.
- */
- struct GNUNET_CURL_RescheduleContext *rc;
-
- /**
- * Configuration we use to lookup account information.
- */
- struct GNUNET_CONFIGURATION_Handle *cfg;
-
-};
-
-
-/**
- * Handle returned by #taler_bank_prepare_wire_transfer.
- */
-struct TALER_WIRE_PrepareHandle
-{
-
- /**
- * Task we use for async execution.
- */
- struct GNUNET_SCHEDULER_Task *task;
-
- /**
- * TalerBank closure we run in.
- */
- struct TalerBankClosure *tc;
-
- /**
- * Authentication information.
- */
- struct TALER_BANK_AuthenticationData auth;
-
- /**
- * Which account should be debited? Given as the respective
- * section in the configuration file.
- */
- char *origin_account_url;
-
- /**
- * Which account should be credited?
- */
- char *destination_account_url;
-
- /**
- * Base URL to use for the exchange.
- */
- char *exchange_base_url;
-
- /**
- * Function to call with the serialized data.
- */
- TALER_WIRE_PrepareTransactionCallback ptc;
-
- /**
- * Closure for @e ptc.
- */
- void *ptc_cls;
-
- /**
- * Amount to transfer.
- */
- struct TALER_Amount amount;
-
- /**
- * Subject of the wire transfer.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
-
-};
-
-
-/**
- * Handle returned by #taler_bank_execute_wire_transfer.
- */
-struct TALER_WIRE_ExecuteHandle
-{
-
- /**
- * Handle to the HTTP request to the bank.
- */
- struct TALER_BANK_AdminAddIncomingHandle *aaih;
-
- /**
- * Function to call with the result.
- */
- TALER_WIRE_ConfirmationCallback cc;
-
- /**
- * Closure for @e cc.
- */
- void *cc_cls;
-};
-
-
-/**
- * Round amount DOWN to the amount that can be transferred via the wire
- * method. For example, Taler may support 0.000001 EUR as a unit of
- * payment, but SEPA only supports 0.01 EUR. This function would
- * round 0.125 EUR to 0.12 EUR in this case.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param[in,out] amount amount to round down
- * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
- * #GNUNET_SYSERR if the amount or currency was invalid
- */
-static int
-taler_bank_amount_round (void *cls,
- struct TALER_Amount *amount)
-{
- struct TalerBankClosure *tc = cls;
- uint32_t delta;
-
- if (NULL == tc->currency)
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler",
- "CURRENCY");
- return GNUNET_SYSERR; /* not configured with currency */
- }
- if (0 != strcasecmp (amount->currency,
- tc->currency))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- /* 'taler_bank' method supports 1/100 of the unit currency, i.e. 0.01 CUR */
- delta = amount->fraction % (TALER_AMOUNT_FRAC_BASE / 100);
- if (0 == delta)
- return GNUNET_NO;
- amount->fraction -= delta;
- return GNUNET_OK;
-}
-
-
-/**
- * Check if the given payto:// URL is correctly formatted.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param account_url an account URL
- * @return #TALER_EC_NONE if correctly formatted
- */
-static enum TALER_ErrorCode
-taler_bank_wire_validate (void *cls,
- const char *account_url)
-{
- (void) cls;
- struct TALER_Account acc;
- enum TALER_ErrorCode ec;
-
- ec = TALER_WIRE_payto_to_account (account_url,
- &acc);
- if (TALER_EC_NONE == ec)
- {
- if (TALER_PAC_X_TALER_BANK != acc.type)
- ec = TALER_EC_PAYTO_WRONG_METHOD;
- TALER_WIRE_account_free (&acc);
- }
- return ec;
-}
-
-
-GNUNET_NETWORK_STRUCT_BEGIN
-/**
- * Format we used for serialized transaction data.
- */
-struct BufFormatP
-{
-
- /**
- * The wire transfer identifier.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- /**
- * The amount.
- */
- struct TALER_AmountNBO amount;
-
- /* followed by 0-terminated origin account URL */
-
- /* followed by 0-terminated destination account URL */
-
- /* followed by 0-terminated exchange base URL */
-
- /* optionally followed by 0-terminated origin username URL */
-
- /* optionally followed by 0-terminated origin password URL */
-
-};
-GNUNET_NETWORK_STRUCT_END
-
-
-/**
- * Abort preparation of a wire transfer. For example,
- * because we are shutting down.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param pth preparation to cancel
- */
-static void
-taler_bank_prepare_wire_transfer_cancel (void *cls,
- struct TALER_WIRE_PrepareHandle *pth)
-{
- (void) cls;
- if (NULL != pth->task)
- GNUNET_SCHEDULER_cancel (pth->task);
- TALER_BANK_auth_free (&pth->auth);
- GNUNET_free (pth->origin_account_url);
- GNUNET_free (pth->destination_account_url);
- GNUNET_free (pth->exchange_base_url);
- GNUNET_free (pth);
-}
-
-
-/**
- * Prepare for exeuction of a wire transfer. Calls the
- * callback with the serialized state.
- *
- * @param cls the `struct TALER_WIRE_PrepareHandle`
- */
-static void
-do_prepare (void *cls)
-{
- struct TALER_WIRE_PrepareHandle *pth = cls;
- size_t len_i;
- size_t len_o;
- size_t len_au;
- size_t len_ap;
- size_t len_b;
- struct BufFormatP bf;
-
- pth->task = NULL;
- /* serialize the state into a 'buf' */
- len_o = strlen (pth->origin_account_url) + 1;
- len_i = strlen (pth->destination_account_url) + 1;
- len_b = strlen (pth->exchange_base_url) + 1;
- len_au = 0;
- len_ap = 0;
- switch (pth->auth.method)
- {
- case TALER_BANK_AUTH_NONE:
- break;
- case TALER_BANK_AUTH_BASIC:
- len_au = strlen (pth->auth.details.basic.username) + 1;
- len_ap = strlen (pth->auth.details.basic.password) + 1;
- break;
- }
- bf.wtid = pth->wtid;
- TALER_amount_hton (&bf.amount,
- &pth->amount);
- {
- char buf[sizeof (struct BufFormatP) + len_o + len_i + len_b + len_au
- + len_ap];
-
- memcpy (buf,
- &bf,
- sizeof (struct BufFormatP));
- memcpy (&buf[sizeof (struct BufFormatP)],
- pth->origin_account_url,
- len_o);
- memcpy (&buf[sizeof (struct BufFormatP) + len_o],
- pth->destination_account_url,
- len_i);
- memcpy (&buf[sizeof (struct BufFormatP) + len_o + len_i],
- pth->exchange_base_url,
- len_b);
- switch (pth->auth.method)
- {
- case TALER_BANK_AUTH_NONE:
- break;
- case TALER_BANK_AUTH_BASIC:
- memcpy (&buf[sizeof (struct BufFormatP) + len_o + len_i + len_b],
- pth->auth.details.basic.username,
- len_au);
- memcpy (&buf[sizeof (struct BufFormatP) + len_o + len_i + len_b + len_au],
- pth->auth.details.basic.password,
- len_ap);
- break;
- }
- /* finally give the state back */
- pth->ptc (pth->ptc_cls,
- buf,
- sizeof (buf));
- }
- taler_bank_prepare_wire_transfer_cancel (NULL,
- pth);
-}
-
-
-/**
- * Parse account configuration from @a cfg in @a section into @a account.
- * Obtains the URL option and initializes @a account from it.
- *
- * @param cfg configuration to parse
- * @param section section with the account configuration
- * @param account[out] account information to initialize
- * @return #GNUNET_OK on success
- */
-static int
-parse_account_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const char *section,
- struct TALER_Account *account)
-{
- char *account_url;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- section,
- "URL",
- &account_url))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- section,
- "URL");
- return GNUNET_SYSERR;
- }
-
- if (TALER_EC_NONE !=
- TALER_WIRE_payto_to_account (account_url,
- account))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- section,
- "URL",
- "Malformed payto:// URL for x-taler-bank method");
- GNUNET_free (account_url);
- return GNUNET_SYSERR;
- }
- if (TALER_PAC_X_TALER_BANK != account->type)
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- section,
- "URL",
- "Malformed payto:// URL for x-taler-bank method");
- GNUNET_free (account_url);
- TALER_WIRE_account_free (account);
- return GNUNET_SYSERR;
- }
- GNUNET_free (account_url);
- return GNUNET_OK;
-}
-
-
-/**
- * Prepare for exeuction of a wire transfer. Note that we should call
- * @a ptc asynchronously (as that is what the API requires, because
- * some transfer methods need it). So while we could immediately call
- * @a ptc, we first bundle up all the data and schedule a task to do
- * the work.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param origin_account_section configuration section specifying the origin
- * account of the exchange to use
- * @param destination_account_url payto:// URL identifying where to send the money
- * @param amount amount to transfer, already rounded
- * @param exchange_base_url base URL of this exchange
- * @param wtid wire transfer identifier to use
- * @param ptc function to call with the prepared data to persist
- * @param ptc_cls closure for @a ptc
- * @return NULL on failure
- */
-static struct TALER_WIRE_PrepareHandle *
-taler_bank_prepare_wire_transfer (void *cls,
- const char *origin_account_section,
- const char *destination_account_url,
- const struct TALER_Amount *amount,
- const char *exchange_base_url,
- const struct
- TALER_WireTransferIdentifierRawP *wtid,
- TALER_WIRE_PrepareTransactionCallback ptc,
- void *ptc_cls)
-{
- struct TalerBankClosure *tc = cls;
- struct TALER_WIRE_PrepareHandle *pth;
- char *origin_account_url;
- struct TALER_Account a_in;
- struct TALER_Account a_out;
-
- /* Check that payto:// URLs are valid */
- if (TALER_EC_NONE !=
- TALER_WIRE_payto_to_account (destination_account_url,
- &a_out))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "payto://-URL `%s' is invalid!\n",
- destination_account_url);
- return NULL;
- }
- if (TALER_PAC_X_TALER_BANK != a_out.type)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "payto://-URL `%s' is invalid!\n",
- destination_account_url);
- TALER_WIRE_account_free (&a_out);
- return NULL;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (tc->cfg,
- origin_account_section,
- "URL",
- &origin_account_url))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- origin_account_section,
- "URL");
- TALER_WIRE_account_free (&a_out);
- return NULL;
- }
- if (TALER_EC_NONE !=
- TALER_WIRE_payto_to_account (origin_account_url,
- &a_in))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- origin_account_section,
- "URL",
- "Malformed payto:// URL for x-taler-bank method");
- GNUNET_free (origin_account_url);
- TALER_WIRE_account_free (&a_out);
- return NULL;
- }
- if (TALER_PAC_X_TALER_BANK != a_in.type)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "payto://-URL `%s' is invalid!\n",
- origin_account_url);
- GNUNET_free (origin_account_url);
- TALER_WIRE_account_free (&a_in);
- TALER_WIRE_account_free (&a_out);
- return NULL;
- }
-
- /* Make sure the bank is the same! */
- if (0 != strcasecmp (a_in.details.x_taler_bank.hostname,
- a_out.details.x_taler_bank.hostname))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "x-taler-bank hostname missmatch: `%s' != `%s'\n",
- a_in.details.x_taler_bank.hostname,
- a_out.details.x_taler_bank.hostname);
- TALER_WIRE_account_free (&a_in);
- TALER_WIRE_account_free (&a_out);
- GNUNET_free (origin_account_url);
- return NULL;
- }
- TALER_WIRE_account_free (&a_in);
- TALER_WIRE_account_free (&a_out);
-
- pth = GNUNET_new (struct TALER_WIRE_PrepareHandle);
- if (GNUNET_OK !=
- TALER_BANK_auth_parse_cfg (tc->cfg,
- origin_account_section,
- &pth->auth))
- {
- GNUNET_free (pth);
- GNUNET_free (origin_account_url);
- return NULL;
- }
-
- pth->tc = tc;
- pth->origin_account_url = origin_account_url;
- pth->destination_account_url = GNUNET_strdup (destination_account_url);
- pth->exchange_base_url = GNUNET_strdup (exchange_base_url);
- pth->wtid = *wtid;
- pth->ptc = ptc;
- pth->ptc_cls = ptc_cls;
- pth->amount = *amount;
- pth->task = GNUNET_SCHEDULER_add_now (&do_prepare,
- pth);
- return pth;
-}
-
-
-/**
- * Called with the result of submitting information about an incoming
- * transaction to a bank.
- *
- * @param cls closure with the `struct TALER_WIRE_ExecuteHandle`
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
- * 0 if the bank's reply is bogus (fails to follow the protocol)
- * @param ec error code from the bank
- * @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
- * @param timestamp time when the transfer was settled by the bank.
- * @param json detailed response from the HTTPD, or NULL if reply was not JSON
- */
-static void
-execute_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- uint64_t serial_id,
- struct GNUNET_TIME_Absolute timestamp,
- const json_t *json)
-{
- struct TALER_WIRE_ExecuteHandle *eh = cls;
- json_t *reason;
- const char *emsg;
- char *s;
- uint64_t serial_id_nbo;
-
- (void) timestamp;
- eh->aaih = NULL;
- emsg = NULL;
- if (NULL != json)
- {
- reason = json_object_get (json,
- "reason");
- if (NULL != reason)
- emsg = json_string_value (reason);
- }
- if (NULL != emsg)
- GNUNET_asprintf (&s,
- "%u/%u (%s)",
- http_status,
- (unsigned int) ec,
- emsg);
- else
- GNUNET_asprintf (&s,
- "%u/%u",
- http_status,
- (unsigned int) ec);
- serial_id_nbo = GNUNET_htonll (serial_id);
- eh->cc (eh->cc_cls,
- (MHD_HTTP_OK == http_status) ? GNUNET_OK : GNUNET_SYSERR,
- &serial_id_nbo,
- sizeof (uint64_t),
- (MHD_HTTP_OK == http_status) ? NULL : s);
- GNUNET_free (s);
- GNUNET_free (eh);
-}
-
-
-/**
- * Execute a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param buf buffer with the prepared execution details
- * @param buf_size number of bytes in @a buf
- * @param cc function to call upon success
- * @param cc_cls closure for @a cc
- * @return NULL on error
- */
-static struct TALER_WIRE_ExecuteHandle *
-taler_bank_execute_wire_transfer (void *cls,
- const char *buf,
- size_t buf_size,
- TALER_WIRE_ConfirmationCallback cc,
- void *cc_cls)
-{
- struct TalerBankClosure *tc = cls;
- struct TALER_WIRE_ExecuteHandle *eh;
- struct TALER_Amount amount;
- struct TALER_Account origin_account;
- struct TALER_Account destination_account;
- struct BufFormatP bf;
- const char *exchange_base_url;
- const char *origin_account_url;
- const char *destination_account_url;
- struct TALER_BANK_AuthenticationData auth;
- size_t left;
- size_t slen;
- char *wire_s;
-
- if (NULL == tc->ctx)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Bank not initialized, cannot do transfers!\n");
- return NULL; /* not initialized with configuration, cannot do transfers */
- }
- if ( (buf_size <= sizeof (struct BufFormatP)) ||
- ('\0' != buf[buf_size - 1]) )
- {
- GNUNET_break (0);
- return NULL;
- }
- memcpy (&bf,
- buf,
- sizeof (bf));
- TALER_amount_ntoh (&amount,
- &bf.amount);
- origin_account_url = &buf[sizeof (struct BufFormatP)];
- left = buf_size - sizeof (struct BufFormatP);
- slen = strlen (origin_account_url) + 1;
- /* make sure there's enough space to accomodate what's been taken now */
- GNUNET_assert (left >= slen);
- left -= slen;
- if (0 == left)
- {
- GNUNET_break (0);
- return NULL;
- }
- destination_account_url = &origin_account_url[slen];
- slen = strlen (destination_account_url) + 1;
- GNUNET_assert (left >= slen);
- left -= slen;
- if (0 == left)
- {
- GNUNET_break (0);
- return NULL;
- }
- exchange_base_url = &destination_account_url[slen];
- slen = strlen (exchange_base_url) + 1;
- GNUNET_assert (left >= slen);
- left -= slen;
- if (0 == left)
- {
- auth.method = TALER_BANK_AUTH_NONE;
- }
- else
- {
- auth.method = TALER_BANK_AUTH_BASIC;
- auth.details.basic.username = (char *) &exchange_base_url[slen];
- slen = strlen (auth.details.basic.username) + 1;
- GNUNET_assert (left >= slen);
- left -= slen;
- if (0 == left)
- {
- GNUNET_break (0);
- return NULL;
- }
- auth.details.basic.password = &auth.details.basic.username[slen];
- slen = strlen (auth.details.basic.password) + 1;
- GNUNET_assert (left >= slen);
- left -= slen;
- if (0 != left)
- {
- GNUNET_break (0);
- return NULL;
- }
- }
-
- if (TALER_EC_NONE !=
- TALER_WIRE_payto_to_account (origin_account_url,
- &origin_account))
- {
- GNUNET_break (0);
- return NULL;
- }
- if (TALER_EC_NONE !=
- TALER_WIRE_payto_to_account (destination_account_url,
- &destination_account))
- {
- TALER_WIRE_account_free (&origin_account);
- GNUNET_break (0);
- return NULL;
- }
- if ( (TALER_PAC_X_TALER_BANK != origin_account.type) ||
- (TALER_PAC_X_TALER_BANK != destination_account.type) ||
- (0 != strcasecmp (origin_account.details.x_taler_bank.hostname,
- destination_account.details.x_taler_bank.hostname)) )
- {
- GNUNET_break (0);
- TALER_WIRE_account_free (&origin_account);
- TALER_WIRE_account_free (&destination_account);
- return NULL;
- }
-
- eh = GNUNET_new (struct TALER_WIRE_ExecuteHandle);
- eh->cc = cc;
- eh->cc_cls = cc_cls;
- wire_s = GNUNET_STRINGS_data_to_string_alloc (&bf.wtid,
- sizeof (bf.wtid));
- eh->aaih = TALER_BANK_admin_add_incoming (tc->ctx,
- origin_account.details.x_taler_bank.
- bank_base_url,
- &auth,
- exchange_base_url,
- wire_s,
- &amount,
- (uint64_t) origin_account.details.
- x_taler_bank.no,
- (uint64_t) destination_account.
- details.x_taler_bank.no,
- &execute_cb,
- eh);
- TALER_WIRE_account_free (&origin_account);
- TALER_WIRE_account_free (&destination_account);
- GNUNET_free (wire_s);
- if (NULL == eh->aaih)
- {
- GNUNET_break (0);
- GNUNET_free (eh);
- return NULL;
- }
- return eh;
-}
-
-
-/**
- * Abort execution of a wire transfer. For example, because we are
- * shutting down. Note that if an execution is aborted, it may or
- * may not still succeed. The caller MUST run @e
- * execute_wire_transfer again for the same request as soon as
- * possilbe, to ensure that the request either ultimately succeeds
- * or ultimately fails. Until this has been done, the transaction is
- * in limbo (i.e. may or may not have been committed).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param eh execution to cancel
- */
-static void
-taler_bank_execute_wire_transfer_cancel (void *cls,
- struct TALER_WIRE_ExecuteHandle *eh)
-{
- (void) cls;
- TALER_BANK_admin_add_incoming_cancel (eh->aaih);
- GNUNET_free (eh);
-}
-
-
-/**
- * Handle for a #taler_bank_get_history() request.
- */
-struct TALER_WIRE_HistoryHandle
-{
-
- /**
- * Function to call with results, can become NULL if the
- * application cancels the iteration.
- */
- TALER_WIRE_HistoryResultCallback hres_cb;
-
- /**
- * Closure for @e hres_cb.
- */
- void *hres_cb_cls;
-
- /**
- * Request to the bank.
- */
- struct TALER_BANK_HistoryHandle *hh;
-
- /**
- * Authentication to use for access.
- */
- struct TALER_BANK_AuthenticationData auth;
-
-};
-
-
-/**
- * Cancel going over the account's history.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param whh operation to cancel
- */
-static void
-taler_bank_get_history_cancel (void *cls,
- struct TALER_WIRE_HistoryHandle *whh)
-{
- (void) cls;
- if (NULL != whh->hh)
- {
- TALER_BANK_history_cancel (whh->hh);
- whh->hh = NULL;
- }
- TALER_BANK_auth_free (&whh->auth);
- GNUNET_free (whh);
-}
-
-
-/**
- * Function called with results from the bank
- * about the transaction history.
- *
- * @param cls the `struct TALER_WIRE_HistoryHandle`
- * @param http_status HTTP response code, #MHD_HTTP_OK (200)
- * for successful status request 0 if the bank's reply
- * is bogus (fails to follow the protocol),
- * #MHD_HTTP_NO_CONTENT if there are no more results; on
- * success the last callback is always of this status
- * (even if `abs(num_results)` were already returned).
- * @param ec taler error code
- * @param dir direction of the transfer
- * @param serial_id monotonically increasing
- * counter corresponding to the transaction
- * @param details details about the wire transfer
- * @param json detailed response from the HTTPD,
- * or NULL if reply was not in JSON
- */
-static void
-bhist_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- enum TALER_BANK_Direction dir,
- uint64_t serial_id,
- const struct TALER_BANK_TransferDetails *details,
- const json_t *json)
-{
- struct TALER_WIRE_HistoryHandle *whh = cls;
- uint64_t bserial_id = GNUNET_htonll (serial_id);
- struct TALER_WIRE_TransferDetails wd;
-
- (void) json;
- switch (http_status)
- {
- case MHD_HTTP_OK:
- {
- char *subject;
- char *space;
-
- wd.amount = details->amount;
- wd.execution_date = details->execution_date;
- subject = GNUNET_strdup (details->wire_transfer_subject);
- space = strchr (subject,
- (unsigned char) ' ');
- if (NULL != space)
- {
- /* Space separates the actual wire transfer subject
- from the exchange base URL (if present, expected
- only for outgoing transactions). So we cut the
- string off at the space. */
- *space = '\0';
- }
- /* NOTE: For a real bank, the subject should include a
- checksum! */
- if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (subject,
- strlen (subject),
- &wd.wtid,
- sizeof (wd.wtid)))
- {
- /* Ill-formed wire subject, set binary version to all zeros
- and pass as a string, this time including the part after
- the space. */
- memset (&wd.wtid,
- 0,
- sizeof (wd.wtid));
- wd.wtid_s = details->wire_transfer_subject;
- }
- else
- {
- wd.wtid_s = NULL;
- }
- GNUNET_free (subject);
- wd.account_url = details->account_url;
- if ( (NULL != whh->hres_cb) &&
- (GNUNET_OK !=
- whh->hres_cb (whh->hres_cb_cls,
- TALER_EC_NONE,
- dir,
- &bserial_id,
- sizeof (bserial_id),
- &wd)) )
- whh->hres_cb = NULL;
- GNUNET_break (NULL != whh->hh);
- /* Once we get the sentinel element, the handle becomes invalid. */
- if (TALER_BANK_DIRECTION_NONE == dir)
- {
- whh->hh = NULL;
- taler_bank_get_history_cancel (NULL,
- whh);
- }
- return;
- }
- case MHD_HTTP_NO_CONTENT:
- if (NULL != whh->hres_cb)
- (void) whh->hres_cb (whh->hres_cb_cls,
- ec,
- TALER_BANK_DIRECTION_NONE,
- NULL,
- 0,
- NULL);
- whh->hh = NULL;
- taler_bank_get_history_cancel (NULL,
- whh);
- return;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Bank failed with HTTP status %u (EC: %u)\n",
- http_status,
- ec);
- if (NULL != whh->hres_cb)
- (void) whh->hres_cb (whh->hres_cb_cls,
- ec,
- TALER_BANK_DIRECTION_NONE,
- NULL,
- 0,
- NULL);
- whh->hh = NULL;
- taler_bank_get_history_cancel (NULL,
- whh);
- return;
- }
-}
-
-
-/**
- * Query transfer history of an account. We use the variable-size
- * @a start_off to indicate which transfers we are interested in as
- * different banking systems may have different ways to identify
- * transfers. The @a start_off value must thus match the value of
- * a `row_off` argument previously given to the @a hres_cb. Use
- * NULL to query transfers from the beginning of time (with
- * positive @a num_results) or from the lataler_bank committed
- * transfers (with negative @a num_results).
- *
- * @param cls the @e cls of this struct with the plugin-specific
- * state
- * @param account_section specifies the configuration section which
- * identifies the account for which we should get the history
- * @param direction what kinds of wire transfers should be returned
- * @param start_off from which row on do we want to get results, use NULL for the latest; exclusive
- * @param start_off_len number of bytes in @a start_off; must be `sizeof(uint64_t)`.
- * @param num_results how many results do we want; negative numbers to go into the past,
- * positive numbers to go into the future starting at @a start_row;
- * must not be zero.
- * @param hres_cb the callback to call with the transaction history
- * @param hres_cb_cls closure for the above callback
- */
-static struct TALER_WIRE_HistoryHandle *
-taler_bank_get_history (void *cls,
- const char *account_section,
- enum TALER_BANK_Direction direction,
- const void *start_off,
- size_t start_off_len,
- int64_t num_results,
- TALER_WIRE_HistoryResultCallback hres_cb,
- void *hres_cb_cls)
-{
- struct TalerBankClosure *tc = cls;
- struct TALER_WIRE_HistoryHandle *whh;
- const uint64_t *start_off_b64;
- uint64_t start_row;
- struct TALER_Account account;
-
- GNUNET_assert (NULL != hres_cb);
- if (0 == num_results)
- {
- GNUNET_break (0);
- return NULL;
- }
- if (TALER_BANK_DIRECTION_NONE == direction)
- {
- GNUNET_break (0);
- return NULL;
- }
- if ( (NULL != start_off) &&
- (sizeof (uint64_t) != start_off_len) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Wire plugin 'taler_bank' got"
- " start offset of wrong size (%llu"
- " instead of %llu)\n",
- (unsigned long long) start_off_len,
- (unsigned long long) sizeof (uint64_t));
- GNUNET_break (0);
-
- /**
- * Probably something is wrong with the DB, some
- * other component wrote a wrong value to it. Instead
- * of completely stopping to work, we just scan from the
- * beginning. */start_off = NULL;
- }
- if (NULL == start_off)
- {
- start_row = UINT64_MAX; /* no start row */
- }
- else
- {
- start_off_b64 = start_off;
- start_row = GNUNET_ntohll (*start_off_b64);
- }
- if (GNUNET_OK !=
- parse_account_cfg (tc->cfg,
- account_section,
- &account))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not parse the config section '%s'\n",
- account_section);
- return NULL;
- }
-
- whh = GNUNET_new (struct TALER_WIRE_HistoryHandle);
- if (GNUNET_OK !=
- TALER_BANK_auth_parse_cfg (tc->cfg,
- account_section,
- &whh->auth))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not parse the auth values from '%s'\n",
- account_section);
- TALER_WIRE_account_free (&account);
- GNUNET_free (whh);
- return NULL;
- }
- whh->hres_cb = hres_cb;
- whh->hres_cb_cls = hres_cb_cls;
- whh->hh = TALER_BANK_history (tc->ctx,
- account.details.x_taler_bank.bank_base_url,
- &whh->auth,
- (uint64_t) account.details.x_taler_bank.no,
- direction,
- /* Defaults to descending ordering always. */
- GNUNET_NO,
- start_row,
- num_results,
- &bhist_cb,
- whh);
- if (NULL == whh->hh)
- {
- GNUNET_break (0);
- taler_bank_get_history_cancel (tc,
- whh);
- TALER_WIRE_account_free (&account);
- return NULL;
- }
- TALER_WIRE_account_free (&account);
- return whh;
-}
-
-
-/**
- * Context for a rejection operation.
- */
-struct TALER_WIRE_RejectHandle
-{
- /**
- * Function to call with the result.
- */
- TALER_WIRE_RejectTransferCallback rej_cb;
-
- /**
- * Closure for @e rej_cb.
- */
- void *rej_cb_cls;
-
- /**
- * Handle for the reject operation.
- */
- struct TALER_BANK_RejectHandle *brh;
-
- /**
- * Authentication information to use.
- */
- struct TALER_BANK_AuthenticationData auth;
-};
-
-
-/**
- * Callbacks of this type are used to serve the result of asking
- * the bank to reject an incoming wire transfer.
- *
- * @param cls closure
- * @param http_status HTTP response code, #MHD_HTTP_NO_CONTENT (204) for successful status request;
- * #MHD_HTTP_NOT_FOUND if the rowid is unknown;
- * 0 if the bank's reply is bogus (fails to follow the protocol),
- * @param ec detailed error code
- */
-static void
-reject_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec)
-{
- struct TALER_WIRE_RejectHandle *rh = cls;
-
- (void) http_status;
- rh->brh = NULL;
- rh->rej_cb (rh->rej_cb_cls,
- ec);
- GNUNET_free (rh);
-}
-
-
-/**
- * Cancel ongoing reject operation. Note that the rejection may still
- * proceed. Basically, if this function is called, the rejection may
- * have happened or not. This function is usually used during shutdown
- * or system upgrades. At a later point, the application must call
- * @e reject_transfer again for this wire transfer, unless the
- * @e get_history shows that the wire transfer no longer exists.
- *
- * @param cls plugins' closure
- * @param rh operation to cancel
- * @return closure of the callback of the operation
- */
-static void *
-taler_bank_reject_transfer_cancel (void *cls,
- struct TALER_WIRE_RejectHandle *rh)
-{
- void *ret = rh->rej_cb_cls;
-
- (void) cls;
- if (NULL != rh->brh)
- TALER_BANK_reject_cancel (rh->brh);
- TALER_BANK_auth_free (&rh->auth);
- GNUNET_free (rh);
- return ret;
-}
-
-
-/**
- * Reject an incoming wire transfer that was obtained from the
- * history. This function can be used to transfer funds back to
- * the sender if the WTID was malformed (i.e. due to a typo).
- *
- * Calling `reject_transfer` twice on the same wire transfer should
- * be idempotent, i.e. not cause the funds to be wired back twice.
- * Furthermore, the transfer should henceforth be removed from the
- * results returned by @e get_history.
- *
- * @param cls plugin's closure
- * @param account_section specifies the configuration section which
- * identifies the account to use to reject the transfer
- * @param start_off offset of the wire transfer in plugin-specific format
- * @param start_off_len number of bytes in @a start_off
- * @param rej_cb function to call with the result of the operation
- * @param rej_cb_cls closure for @a rej_cb
- * @return handle to cancel the operation
- */
-static struct TALER_WIRE_RejectHandle *
-taler_bank_reject_transfer (void *cls,
- const char *account_section,
- const void *start_off,
- size_t start_off_len,
- TALER_WIRE_RejectTransferCallback rej_cb,
- void *rej_cb_cls)
-{
- struct TalerBankClosure *tc = cls;
- const uint64_t *rowid_b64 = start_off;
- struct TALER_WIRE_RejectHandle *rh;
- struct TALER_Account account;
-
- if (sizeof (uint64_t) != start_off_len)
- {
- GNUNET_break (0);
- return NULL;
- }
- rh = GNUNET_new (struct TALER_WIRE_RejectHandle);
- if (GNUNET_OK !=
- TALER_BANK_auth_parse_cfg (tc->cfg,
- account_section,
- &rh->auth))
- {
- GNUNET_free (rh);
- return NULL;
- }
- if (GNUNET_OK !=
- parse_account_cfg (tc->cfg,
- account_section,
- &account))
- {
- (void) taler_bank_reject_transfer_cancel (tc,
- rh);
- return NULL;
- }
- rh->rej_cb = rej_cb;
- rh->rej_cb_cls = rej_cb_cls;
- TALER_LOG_INFO ("Rejecting over %s bank URL\n",
- account.details.x_taler_bank.hostname);
- rh->brh = TALER_BANK_reject (tc->ctx,
- account.details.x_taler_bank.bank_base_url,
- &rh->auth,
- (uint64_t) account.details.x_taler_bank.no,
- GNUNET_ntohll (*rowid_b64),
- &reject_cb,
- rh);
- if (NULL == rh->brh)
- {
- (void) taler_bank_reject_transfer_cancel (tc,
- rh);
- TALER_WIRE_account_free (&account);
- return NULL;
- }
- TALER_WIRE_account_free (&account);
- return rh;
-}
-
-
-/**
- * Initialize taler_bank-wire subsystem.
- *
- * @param cls a configuration instance
- * @return NULL on error, otherwise a `struct TALER_WIRE_Plugin`
- */
-void *
-libtaler_plugin_wire_taler_bank_init (void *cls)
-{
- struct GNUNET_CONFIGURATION_Handle *cfg = cls;
- struct TalerBankClosure *tc;
- struct TALER_WIRE_Plugin *plugin;
-
- tc = GNUNET_new (struct TalerBankClosure);
- tc->cfg = cfg;
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "taler",
- "CURRENCY",
- &tc->currency))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler",
- "CURRENCY");
- GNUNET_free (tc);
- return NULL;
- }
- tc->ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
- &tc->rc);
- tc->rc = GNUNET_CURL_gnunet_rc_create (tc->ctx);
- if (NULL == tc->ctx)
- {
- GNUNET_break (0);
- GNUNET_free (tc->currency);
- GNUNET_free (tc);
- return NULL;
- }
- plugin = GNUNET_new (struct TALER_WIRE_Plugin);
- plugin->cls = tc;
- plugin->method = "x-taler-bank";
- plugin->amount_round = &taler_bank_amount_round;
- plugin->wire_validate = &taler_bank_wire_validate;
- plugin->prepare_wire_transfer = &taler_bank_prepare_wire_transfer;
- plugin->prepare_wire_transfer_cancel =
- &taler_bank_prepare_wire_transfer_cancel;
- plugin->execute_wire_transfer = &taler_bank_execute_wire_transfer;
- plugin->execute_wire_transfer_cancel =
- &taler_bank_execute_wire_transfer_cancel;
- plugin->get_history = &taler_bank_get_history;
- plugin->get_history_cancel = &taler_bank_get_history_cancel;
- plugin->reject_transfer = &taler_bank_reject_transfer;
- plugin->reject_transfer_cancel = &taler_bank_reject_transfer_cancel;
- return plugin;
-}
-
-
-/**
- * Shutdown taler-bank wire subsystem.
- *
- * @param cls a `struct TALER_WIRE_Plugin`
- * @return NULL (always)
- */
-void *
-libtaler_plugin_wire_taler_bank_done (void *cls)
-{
- struct TALER_WIRE_Plugin *plugin = cls;
- struct TalerBankClosure *tc = plugin->cls;
-
- if (NULL != tc->ctx)
- {
- GNUNET_CURL_fini (tc->ctx);
- tc->ctx = NULL;
- }
- if (NULL != tc->rc)
- {
- GNUNET_CURL_gnunet_rc_destroy (tc->rc);
- tc->rc = NULL;
- }
- GNUNET_free_non_null (tc->currency);
- GNUNET_free (tc);
- GNUNET_free (plugin);
- return NULL;
-}
-
-
-/* end of plugin_wire_taler-bank.c */
diff --git a/src/wire-plugins/plugin_wire_template.c b/src/wire-plugins/plugin_wire_template.c
deleted file mode 100644
index 731885ac..00000000
--- a/src/wire-plugins/plugin_wire_template.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2016, 2018 GNUnet e.V.
-
- 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 plugin_wire_template.c
- * @brief template for wire plugins; replace "template" with real plugin name!
- * @author Florian Dold
- * @author Christian Grothoff
- * @author Sree Harsha Totakura
- */
-#include "platform.h"
-#include "taler_wire_plugin.h"
-
-
-/**
- * Type of the "cls" argument given to each of the functions in
- * our API.
- */
-struct TemplateClosure
-{
-
- /**
- * Which currency do we support?
- */
- char *currency;
-
- /**
- * Which configuration do we use to lookup accounts?
- */
- struct GNUNET_CONFIGURATION_Handle *cfg;
-
-};
-
-
-/**
- * Round amount DOWN to the amount that can be transferred via the wire
- * method. For example, Taler may support 0.000001 EUR as a unit of
- * payment, but SEPA only supports 0.01 EUR. This function would
- * round 0.125 EUR to 0.12 EUR in this case.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param[in,out] amount amount to round down
- * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
- * #GNUNET_SYSERR if the amount or currency was invalid
- */
-static int
-template_amount_round (void *cls,
- struct TALER_Amount *amount)
-{
- struct TemplateClosure *tc = cls;
-
- if (0 != strcasecmp (amount->currency,
- tc->currency))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- GNUNET_break (0); // not implemented
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Check if the given payto:// URL is correctly formatted for this plugin
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param account_url the payto:// URL
- * @return #TALER_EC_NONE if correctly formatted
- */
-static enum TALER_ErrorCode
-template_wire_validate (void *cls,
- const char *account_url)
-{
- (void) cls;
- (void) account_url;
- GNUNET_break (0);
- return TALER_EC_NOT_IMPLEMENTED;
-}
-
-
-/**
- * Prepare for exeuction of a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param origin_account_section configuration section specifying the origin
- * account of the exchange to use
- * @param destination_account_url payto:// URL identifying where to send the money
- * @param amount amount to transfer, already rounded
- * @param exchange_base_url base URL of the exchange (for tracking)
- * @param wtid wire transfer identifier to use
- * @param ptc function to call with the prepared data to persist
- * @param ptc_cls closure for @a ptc
- * @return NULL on failure
- */
-static struct TALER_WIRE_PrepareHandle *
-template_prepare_wire_transfer (void *cls,
- const char *origin_account_section,
- const char *destination_account_url,
- const struct TALER_Amount *amount,
- const char *exchange_base_url,
- const struct
- TALER_WireTransferIdentifierRawP *wtid,
- TALER_WIRE_PrepareTransactionCallback ptc,
- void *ptc_cls)
-{
- (void) cls;
- (void) origin_account_section;
- (void) destination_account_url;
- (void) amount;
- (void) exchange_base_url;
- (void) wtid;
- (void) ptc;
- (void) ptc_cls;
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Abort preparation of a wire transfer. For example,
- * because we are shutting down.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param pth preparation to cancel
- */
-static void
-template_prepare_wire_transfer_cancel (void *cls,
- struct TALER_WIRE_PrepareHandle *pth)
-{
- (void) cls;
- (void) pth;
- GNUNET_break (0);
-}
-
-
-/**
- * Execute a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param buf buffer with the prepared execution details
- * @param buf_size number of bytes in @a buf
- * @param cc function to call upon success
- * @param cc_cls closure for @a cc
- * @return NULL on error
- */
-static struct TALER_WIRE_ExecuteHandle *
-template_execute_wire_transfer (void *cls,
- const char *buf,
- size_t buf_size,
- TALER_WIRE_ConfirmationCallback cc,
- void *cc_cls)
-{
- (void) cls;
- (void) buf;
- (void) buf_size;
- (void) cc;
- (void) cc_cls;
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Abort execution of a wire transfer. For example, because we are
- * shutting down. Note that if an execution is aborted, it may or
- * may not still succeed. The caller MUST run @e
- * execute_wire_transfer again for the same request as soon as
- * possilbe, to ensure that the request either ultimately succeeds
- * or ultimately fails. Until this has been done, the transaction is
- * in limbo (i.e. may or may not have been committed).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param eh execution to cancel
- */
-static void
-template_execute_wire_transfer_cancel (void *cls,
- struct TALER_WIRE_ExecuteHandle *eh)
-{
- (void) cls;
- (void) eh;
- GNUNET_break (0);
-}
-
-
-/**
- * Query transfer history of an account. We use the variable-size
- * @a start_off to indicate which transfers we are interested in as
- * different banking systems may have different ways to identify
- * transfers. The @a start_off value must thus match the value of
- * a `row_off` argument previously given to the @a hres_cb. Use
- * NULL to query transfers from the beginning of time (with
- * positive @a num_results) or from the latest committed transfers
- * (with negative @a num_results).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param account_section specifies the configuration section which
- * identifies the account for which we should get the history
- * @param direction what kinds of wire transfers should be returned
- * @param start_off from which row on do we want to get results, use NULL for the latest; exclusive
- * @param start_off_len number of bytes in @a start_off; must be `sizeof(uint64_t)`.
- * @param num_results how many results do we want; negative numbers to go into the past,
- * positive numbers to go into the future starting at @a start_row;
- * must not be zero.
- * @param hres_cb the callback to call with the transaction history
- * @param hres_cb_cls closure for the above callback
- */
-static struct TALER_WIRE_HistoryHandle *
-template_get_history (void *cls,
- const char *account_section,
- enum TALER_BANK_Direction direction,
- const void *start_off,
- size_t start_off_len,
- int64_t num_results,
- TALER_WIRE_HistoryResultCallback hres_cb,
- void *hres_cb_cls)
-{
- (void) cls;
- (void) account_section;
- (void) direction;
- (void) start_off;
- (void) start_off_len;
- (void) num_results;
- (void) hres_cb;
- (void) hres_cb_cls;
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Cancel going over the account's history.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param whh operation to cancel
- */
-static void
-template_get_history_cancel (void *cls,
- struct TALER_WIRE_HistoryHandle *whh)
-{
- (void) cls;
- (void) whh;
- GNUNET_break (0);
-}
-
-
-/**
- * Reject an incoming wire transfer that was obtained from the
- * history. This function can be used to transfer funds back to
- * the sender if the WTID was malformed (i.e. due to a typo).
- *
- * Calling `reject_transfer` twice on the same wire transfer should
- * be idempotent, i.e. not cause the funds to be wired back twice.
- * Furthermore, the transfer should henceforth be removed from the
- * results returned by @e get_history.
- *
- * @param cls plugin's closure
- * @param account_section specifies the configuration section which
- * identifies the account to use to reject the transfer
- * @param start_off offset of the wire transfer in plugin-specific format
- * @param start_off_len number of bytes in @a start_off
- * @param rej_cb function to call with the result of the operation
- * @param rej_cb_cls closure for @a rej_cb
- * @return handle to cancel the operation
- */
-static struct TALER_WIRE_RejectHandle *
-template_reject_transfer (void *cls,
- const char *account_section,
- const void *start_off,
- size_t start_off_len,
- TALER_WIRE_RejectTransferCallback rej_cb,
- void *rej_cb_cls)
-{
- (void) cls;
- (void) account_section;
- (void) start_off;
- (void) start_off_len;
- (void) rej_cb;
- (void) rej_cb_cls;
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Cancel ongoing reject operation. Note that the rejection may still
- * proceed. Basically, if this function is called, the rejection may
- * have happened or not. This function is usually used during shutdown
- * or system upgrades. At a later point, the application must call
- * @e reject_transfer again for this wire transfer, unless the
- * @e get_history shows that the wire transfer no longer exists.
- *
- * @param cls plugins' closure
- * @param rh operation to cancel
- * @return closure of the callback of the operation
- */
-static void *
-template_reject_transfer_cancel (void *cls,
- struct TALER_WIRE_RejectHandle *rh)
-{
- (void) cls;
- (void) rh;
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Initialize template-wire subsystem.
- *
- * @param cls a configuration instance
- * @return NULL on error, otherwise a `struct TALER_WIRE_Plugin`
- */
-void *
-libtaler_plugin_wire_template_init (void *cls)
-{
- struct GNUNET_CONFIGURATION_Handle *cfg = cls;
- struct TemplateClosure *tc;
- struct TALER_WIRE_Plugin *plugin;
-
- tc = GNUNET_new (struct TemplateClosure);
- tc->cfg = cfg;
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "taler",
- "CURRENCY",
- &tc->currency))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler",
- "CURRENCY");
- GNUNET_free (tc);
- return NULL;
- }
-
- plugin = GNUNET_new (struct TALER_WIRE_Plugin);
- plugin->cls = tc;
- plugin->method = "FIXME-REPLACE-BY-METHOD";
- plugin->amount_round = &template_amount_round;
- plugin->wire_validate = &template_wire_validate;
- plugin->prepare_wire_transfer = &template_prepare_wire_transfer;
- plugin->prepare_wire_transfer_cancel = &template_prepare_wire_transfer_cancel;
- plugin->execute_wire_transfer = &template_execute_wire_transfer;
- plugin->execute_wire_transfer_cancel = &template_execute_wire_transfer_cancel;
- plugin->get_history = &template_get_history;
- plugin->get_history_cancel = &template_get_history_cancel;
- plugin->reject_transfer = &template_reject_transfer;
- plugin->reject_transfer_cancel = &template_reject_transfer_cancel;
- return plugin;
-}
-
-
-/**
- * Shutdown Template wire subsystem.
- *
- * @param cls a `struct TALER_WIRE_Plugin`
- * @return NULL (always)
- */
-void *
-libtaler_plugin_wire_template_done (void *cls)
-{
- struct TALER_WIRE_Plugin *plugin = cls;
- struct TemplateClosure *tc = plugin->cls;
-
- GNUNET_free (tc->currency);
- GNUNET_free (tc);
- GNUNET_free (plugin);
- return NULL;
-}
-
-
-/* end of plugin_wire_template.c */
diff --git a/src/wire-plugins/test_wire_plugin.c b/src/wire-plugins/test_wire_plugin.c
deleted file mode 100644
index 65867113..00000000
--- a/src/wire-plugins/test_wire_plugin.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- This file is part of TALER
- (C) 2015, 2016, 2017 GNUnet e.V. and Inria
-
- 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 wire/test_wire_plugin.c
- * @brief Tests for wire plugins
- * @author Christian Grothoff
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- */
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_wire_lib.h"
-#include "taler_wire_plugin.h"
-#include <gnunet/gnunet_json_lib.h>
-
-
-/**
- * Definitions for a test with a plugin.
- */
-struct TestBlock
-{
-
- /**
- * Name of the plugin to test.
- */
- const char *plugin_name;
-
- /**
- * Amount to give to the rounding function.
- */
- const char *round_in;
-
- /**
- * Expected result from rounding.
- */
- const char *round_out;
-
- /**
- * Currency to give to the plugin.
- */
- const char *currency;
-};
-
-
-/**
- * List of plugins and (unsigned) JSON account definitions
- * to use for the tests.
- */
-static struct TestBlock tests[] = {
-#if HAVE_LIBCURL
- {
- .plugin_name = "taler_bank",
- .round_in = "KUDOS:0.123456",
- .round_out = "KUDOS:0.12",
- .currency = "KUDOS"
- },
-#endif
- {
- NULL, NULL, NULL, NULL
- }
-};
-
-
-/**
- * Our configuration.
- */
-static struct GNUNET_CONFIGURATION_Handle *cfg;
-
-
-/**
- * Run the test.
- *
- * @param test details of the test
- * @param plugin plugin to test
- * @return #GNUNET_OK on success
- */
-static int
-run_test (const struct TestBlock *test,
- struct TALER_WIRE_Plugin *plugin)
-{
- struct GNUNET_HashCode salt;
- struct TALER_Amount in;
- struct TALER_Amount expect;
-
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &salt,
- sizeof (salt));
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount (test->round_in,
- &in));
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount (test->round_out,
- &expect));
- if (GNUNET_OK !=
- plugin->amount_round (plugin->cls,
- &in))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (0 != TALER_amount_cmp (&in, &expect))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_NO !=
- plugin->amount_round (plugin->cls,
- &in))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- memset (&in, 0, sizeof (in));
- GNUNET_log_skip (GNUNET_ERROR_TYPE_ERROR, 1);
- if (GNUNET_SYSERR !=
- plugin->amount_round (plugin->cls,
- &in))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-int
-main (int argc,
- const char *const argv[])
-{
- int ret;
- struct TALER_WIRE_Plugin *plugin;
- const struct TestBlock *test;
-
- GNUNET_log_setup ("test-wire-plugin",
- "WARNING",
- NULL);
- cfg = GNUNET_CONFIGURATION_create ();
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONFIGURATION_load (cfg,
- "test_wire_plugin.conf"));
- ret = GNUNET_OK;
- for (unsigned int i = 0; NULL != (test = &tests[i])->plugin_name; i++)
- {
- GNUNET_CONFIGURATION_set_value_string (cfg,
- "taler",
- "CURRENCY",
- test->currency);
- plugin = TALER_WIRE_plugin_load (cfg,
- test->plugin_name);
- if (NULL == plugin)
- {
- TALER_LOG_ERROR ("Could not load plugin `%s'\n",
- test->plugin_name);
- return 77;
- }
-
- ret = run_test (test, plugin);
- TALER_WIRE_plugin_unload (plugin);
- if (GNUNET_OK != ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "%s FAILED\n",
- test->plugin_name);
- break;
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- "%s PASS\n",
- test->plugin_name);
- }
- }
- GNUNET_CONFIGURATION_destroy (cfg);
- if (GNUNET_OK != ret)
- return 1;
- return 0;
-}
diff --git a/src/wire-plugins/test_wire_plugin.conf b/src/wire-plugins/test_wire_plugin.conf
deleted file mode 100644
index d1d699b0..00000000
--- a/src/wire-plugins/test_wire_plugin.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-# This file is in the public domain.
-#
-[account-taler-bank]
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-WIRE_JSON = test_wire_plugin_test.json
-
-# Our bank account URL
-URL = payto://x-taler-bank/2
-
-# Which wire plugin should we used to access the account?
-PLUGIN = taler_bank
-
-
-[account-sepa]
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-WIRE_JSON = test_wire_plugin_sepa.json
-
-# Which wire plugin should we used to access the account?
-PLUGIN = ebics
-
-
-[taler]
-CURRENCY = "EUR"
diff --git a/src/wire-plugins/test_wire_plugin_transactions_taler-bank.c b/src/wire-plugins/test_wire_plugin_transactions_taler-bank.c
deleted file mode 100644
index 79700818..00000000
--- a/src/wire-plugins/test_wire_plugin_transactions_taler-bank.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- This file is part of TALER
- (C) 2015-2018 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 wire/test_wire_plugin_transactions_taler-bank.c
- * @brief Tests performing actual transactions with the taler-bank wire plugin against FAKEBANK
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_wire_lib.h"
-#include "taler_wire_plugin.h"
-#include "taler_fakebank_lib.h"
-#include <gnunet/gnunet_json_lib.h>
-
-
-/**
- * When does the test timeout? Right now, we expect this to be very
- * fast.
- */
-#define TIMEOUT GNUNET_TIME_UNIT_SECONDS
-
-
-/**
- * Destination account to use.
- */
-static const char *dest_account = "payto://x-taler-bank/localhost:8088/42";
-
-/**
- * Origin account, section in the configuration file.
- */
-static const char *my_account = "account-test";
-
-/**
- * Our configuration.
- */
-static struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * Set to #GNUNET_SYSERR if the test failed.
- */
-static int global_ret;
-
-/**
- * The 'test' plugin that we are using for the test.
- */
-static struct TALER_WIRE_Plugin *plugin;
-
-/**
- * Active preparation handle, or NULL if not active.
- */
-static struct TALER_WIRE_PrepareHandle *ph;
-
-/**
- * Active execution handle, or NULL if not active.
- */
-static struct TALER_WIRE_ExecuteHandle *eh;
-
-/**
- * Handle to the bank.
- */
-static struct TALER_FAKEBANK_Handle *fb;
-
-/**
- * Handle to the history request.
- */
-static struct TALER_WIRE_HistoryHandle *hh;
-
-/**
- * Handle to the history-range request (the "legacy" bank API).
- */
-static struct TALER_WIRE_HistoryHandle *hhr;
-
-/**
- * Handle for the timeout task.
- */
-static struct GNUNET_SCHEDULER_Task *tt;
-
-/**
- * Which serial ID do we expect to get from /history?
- */
-static uint64_t serial_target;
-
-/**
- * Wire transfer identifier we are using.
- */
-static struct TALER_WireTransferIdentifierRawP wtid;
-
-
-/**
- * Function called on shutdown (regular, error or CTRL-C).
- *
- * @param cls NULL
- */
-static void
-do_shutdown (void *cls)
-{
- (void) cls;
- TALER_FAKEBANK_stop (fb);
- fb = NULL;
- if (NULL != eh)
- {
- plugin->execute_wire_transfer_cancel (plugin->cls,
- eh);
- eh = NULL;
- }
- if (NULL != ph)
- {
- plugin->prepare_wire_transfer_cancel (plugin->cls,
- ph);
- ph = NULL;
- }
- if (NULL != hh)
- {
- plugin->get_history_cancel (plugin->cls,
- hh);
- hh = NULL;
- }
-
- if (NULL != hhr)
- {
- plugin->get_history_cancel (plugin->cls,
- hhr);
- hhr = NULL;
- }
-
- if (NULL != tt)
- {
- GNUNET_SCHEDULER_cancel (tt);
- tt = NULL;
- }
- TALER_WIRE_plugin_unload (plugin);
-}
-
-
-/**
- * Function called on timeout.
- *
- * @param cls NULL
- */
-static void
-timeout_cb (void *cls)
-{
- tt = NULL;
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Callbacks of this type are used to serve the result of asking
- * the bank for the transaction history.
- *
- * @param cls closure
- * @param ec taler status code
- * @param dir direction of the transfer
- * @param row_off identification of the position at
- * which we are querying
- * @param row_off_size number of bytes in @a row_off
- * @param details details about the wire transfer
- * @return #GNUNET_OK to continue, #GNUNET_SYSERR to
- * abort iteration
- */
-static int
-history_result_cb
- (void *cls,
- enum TALER_ErrorCode ec,
- enum TALER_BANK_Direction dir,
- const void *row_off,
- size_t row_off_size,
- const struct TALER_WIRE_TransferDetails *details)
-{
- uint64_t *serialp;
- uint64_t serialh;
- struct TALER_Amount amount;
-
- if ( (TALER_BANK_DIRECTION_NONE == dir) &&
- (GNUNET_OK == global_ret) )
- {
- GNUNET_SCHEDULER_shutdown ();
- hh = NULL;
- return GNUNET_OK;
- }
- if (sizeof (uint64_t) != row_off_size)
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_SYSERR;
- }
- serialp = (uint64_t *) row_off;
- serialh = GNUNET_ntohll (*serialp);
- if (serialh != serial_target)
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_SYSERR;
- }
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount ("KUDOS:5.01",
- &amount));
- if (0 != TALER_amount_cmp (&amount,
- &details->amount))
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_SYSERR;
- }
- if (0 != GNUNET_memcmp (&wtid,
- &details->wtid))
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_SYSERR;
- }
- global_ret = GNUNET_OK;
- return GNUNET_OK;
-}
-
-
-/**
- * Function called with the result from the execute step.
- *
- * @param cls closure
- * @param success #GNUNET_OK on success,
- * #GNUNET_SYSERR on failure
- * @param row_id ID of the fresh transaction,
- * in _network_ byte order.
- * @param emsg NULL on success, otherwise an error message
- */
-static void
-confirmation_cb (void *cls,
- int success,
- const void *row_id,
- size_t row_id_size,
- const char *emsg)
-{
- uint64_t tmp;
-
- eh = NULL;
- if (GNUNET_OK != success)
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- memcpy (&tmp,
- row_id,
- row_id_size);
- serial_target = GNUNET_ntohll (tmp);
- hh = plugin->get_history (plugin->cls,
- my_account,
- TALER_BANK_DIRECTION_BOTH,
- NULL,
- 0,
- 5,
- &history_result_cb,
- NULL);
-}
-
-
-/**
- * Callback with prepared transaction.
- *
- * @param cls closure
- * @param buf transaction data to persist, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-prepare_cb (void *cls,
- const char *buf,
- size_t buf_size)
-{
- ph = NULL;
- if (NULL == buf)
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- plugin->execute_wire_transfer (plugin->cls,
- buf,
- buf_size,
- &confirmation_cb,
- NULL);
-}
-
-
-/**
- * Run the test.
- *
- * @param cls NULL
- */
-static void
-run (void *cls)
-{
- struct TALER_Amount amount;
-
- GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
- NULL);
- tt = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
- &timeout_cb,
- NULL);
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
- &wtid,
- sizeof (wtid));
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount ("KUDOS:5.01",
- &amount));
- fb = TALER_FAKEBANK_start (8088);
- ph = plugin->prepare_wire_transfer (plugin->cls,
- my_account,
- dest_account,
- &amount,
- "https://exchange.net/",
- &wtid,
- &prepare_cb,
- NULL);
-}
-
-
-int
-main (int argc,
- const char *const argv[])
-{
-
- GNUNET_log_setup ("test-wire-plugin-transactions-test",
- "WARNING",
- NULL);
- cfg = GNUNET_CONFIGURATION_create ();
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONFIGURATION_load (cfg,
- "test_wire_plugin_transactions_taler-bank.conf"));
- global_ret = GNUNET_OK;
- plugin = TALER_WIRE_plugin_load (cfg,
- "taler_bank");
- GNUNET_assert (NULL != plugin);
- GNUNET_SCHEDULER_run (&run,
- NULL);
- GNUNET_CONFIGURATION_destroy (cfg);
- if (GNUNET_OK != global_ret)
- return 1;
- return 0;
-}
-
-
-/* end of test_wire_plugin_transactions_taler-bank.c */
diff --git a/src/wire-plugins/test_wire_plugin_transactions_taler-bank.conf b/src/wire-plugins/test_wire_plugin_transactions_taler-bank.conf
deleted file mode 100644
index d6d2e834..00000000
--- a/src/wire-plugins/test_wire_plugin_transactions_taler-bank.conf
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file is in the public domain.
-#
-[account-test]
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-
-TALER_BANK_AUTH_METHOD = NONE
-
-URL = payto://x-taler-bank/localhost:8088/2
-
-[taler]
-CURRENCY = "KUDOS"
diff --git a/src/wire/Makefile.am b/src/wire/Makefile.am
index 6bf38aa2..2a82282a 100644
--- a/src/wire/Makefile.am
+++ b/src/wire/Makefile.am
@@ -13,7 +13,6 @@ lib_LTLIBRARIES = \
libtalerwire_la_SOURCES = \
payto.c \
- wire.c \
wire_helper.c
libtalerwire_la_LIBADD = \
-lgnunetutil \
diff --git a/src/wire/payto.c b/src/wire/payto.c
index 74154977..0c3fce95 100644
--- a/src/wire/payto.c
+++ b/src/wire/payto.c
@@ -20,6 +20,7 @@
*/
#include "platform.h"
#include "taler_util.h"
+#include "taler_bank_service.h"
#include "taler_wire_lib.h"
/**
@@ -43,8 +44,8 @@ TALER_WIRE_account_free (struct TALER_Account *acc)
case TALER_PAC_X_TALER_BANK:
GNUNET_free (acc->details.x_taler_bank.hostname);
acc->details.x_taler_bank.hostname = NULL;
- GNUNET_free (acc->details.x_taler_bank.bank_base_url);
- acc->details.x_taler_bank.bank_base_url = NULL;
+ GNUNET_free (acc->details.x_taler_bank.account_base_url);
+ acc->details.x_taler_bank.account_base_url = NULL;
break;
case TALER_PAC_IBAN:
GNUNET_free (acc->details.iban.number);
@@ -410,7 +411,8 @@ parse_payto_x_taler_bank (const char *account_url,
const char *hostname;
const char *account;
const char *q;
- unsigned long long no;
+ unsigned int port;
+ char *p;
#define PREFIX "payto://x-taler-bank/"
if (0 != strncasecmp (account_url,
@@ -422,74 +424,52 @@ parse_payto_x_taler_bank (const char *account_url,
(unsigned char) '/')))
return TALER_EC_PAYTO_MALFORMED;
account++;
- if (NULL != (q = strchr (account,
- (unsigned char) '?')))
+ if (NULL == r_account)
+ return TALER_EC_NONE;
+ q = strchr (account,
+ (unsigned char) '?');
+ if (0 == q)
+ q = account + strlen (account);
+ r_account->details.x_taler_bank.hostname
+ = GNUNET_strndup (hostname,
+ account - hostname);
+ port = 443; /* if non given, equals 443. */
+ if (NULL != (p = strchr (r_account->details.x_taler_bank.hostname,
+ (unsigned char) ':')))
{
- char *s;
-
- s = GNUNET_strndup (account,
- q - account);
- if (1 != sscanf (s,
- "%llu",
- &no))
+ p++;
+ if (1 != sscanf (p,
+ "%u",
+ &port))
{
- GNUNET_free (s);
+ GNUNET_break (0);
+ TALER_LOG_ERROR ("Malformed host from payto:// URI\n");
+ GNUNET_free (r_account->details.x_taler_bank.hostname);
+ r_account->details.x_taler_bank.hostname = NULL;
return TALER_EC_PAYTO_MALFORMED;
}
- GNUNET_free (s);
}
- else if (1 != sscanf (account,
- "%llu",
- &no))
+ if (443 != port)
{
- return TALER_EC_PAYTO_MALFORMED;
+ GNUNET_assert
+ (GNUNET_SYSERR != GNUNET_asprintf
+ (&r_account->details.x_taler_bank.account_base_url,
+ "http://%s/%.*s",
+ r_account->details.x_taler_bank.hostname,
+ (int) (q - account),
+ account));
}
- if (no > MAX_ACCOUNT_NO)
- return TALER_EC_PAYTO_MALFORMED;
-
- if (NULL != r_account)
+ else
{
- long long unsigned port;
- char *p;
-
- r_account->details.x_taler_bank.hostname
- = GNUNET_strndup (hostname,
- account - hostname);
- r_account->details.x_taler_bank.no = no;
- port = 443; /* if non given, equals 443. */
- if (NULL != (p = strchr (r_account->details.x_taler_bank.hostname,
- (unsigned char) ':')))
- {
- p++;
- if (1 != sscanf (p,
- "%llu",
- &port))
- {
- GNUNET_break (0);
- TALER_LOG_ERROR ("Malformed host from payto:// URI\n");
- GNUNET_free (r_account->details.x_taler_bank.hostname);
- r_account->details.x_taler_bank.hostname = NULL;
- return TALER_EC_PAYTO_MALFORMED;
- }
- }
- if (443 != port)
- {
- GNUNET_assert
- (GNUNET_SYSERR != GNUNET_asprintf
- (&r_account->details.x_taler_bank.bank_base_url,
- "http://%s",
- r_account->details.x_taler_bank.hostname));
- }
- else
- {
- GNUNET_assert
- (GNUNET_SYSERR != GNUNET_asprintf
- (&r_account->details.x_taler_bank.bank_base_url,
- "https://%s",
- r_account->details.x_taler_bank.hostname));
- }
- r_account->type = TALER_PAC_X_TALER_BANK;
+ GNUNET_assert
+ (GNUNET_SYSERR != GNUNET_asprintf
+ (&r_account->details.x_taler_bank.account_base_url,
+ "https://%s/%.*s",
+ r_account->details.x_taler_bank.hostname,
+ (int) (q - account),
+ account));
}
+ r_account->type = TALER_PAC_X_TALER_BANK;
return TALER_EC_NONE;
}
diff --git a/src/wire/wire.c b/src/wire/wire.c
deleted file mode 100644
index 60ae9e6e..00000000
--- a/src/wire/wire.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- This file is part of TALER
- (C) 2015, 2016, 2017, 2018 GNUnet e.V.
-
- 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 wire/wire.c
- * @brief Functions for loading wire plugins
- * @author Christian Grothoff <christian@grothoff.org>
- */
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_wire_lib.h"
-
-
-/**
- * A wire plugin that we have loaded.
- */
-struct WirePlugin
-{
- /**
- * We keep these in a DLL.
- */
- struct WirePlugin *next;
-
- /**
- * We keep these in a DLL.
- */
- struct WirePlugin *prev;
-
- /**
- * Type of this wire plugin.
- */
- char *type;
-
- /**
- * Wire plugin
- */
- struct TALER_WIRE_Plugin *plugin;
-
- /**
- * Reference counter for the plugin.
- */
- unsigned int rc;
-};
-
-
-/**
- * Head of the DLL of loaded wire plugins.
- */
-static struct WirePlugin *wp_head;
-
-/**
- * Tail of the DLL of loaded wire plugins.
- */
-static struct WirePlugin *wp_tail;
-
-
-/**
- * Load a WIRE plugin.
- *
- * @param cfg configuration to use
- * @param plugin_name name of the plugin to load
- * @return the plugin object pointer, or NULL upon errors.
- */
-struct TALER_WIRE_Plugin *
-TALER_WIRE_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const char *plugin_name)
-{
- char *lib_name;
- struct TALER_WIRE_Plugin *plugin;
- struct WirePlugin *wp;
-
- for (wp = wp_head; NULL != wp; wp = wp->next)
- if (0 == strcasecmp (plugin_name,
- wp->type))
- {
- wp->rc++;
- return wp->plugin;
- }
- (void) GNUNET_asprintf (&lib_name,
- "libtaler_plugin_wire_%s",
- plugin_name);
- plugin = GNUNET_PLUGIN_load (lib_name,
- (void *) cfg);
- if (NULL != plugin)
- plugin->library_name = lib_name;
- else
- GNUNET_free (lib_name);
- if (NULL == plugin)
- return NULL;
- wp = GNUNET_new (struct WirePlugin);
- wp->plugin = plugin;
- wp->type = GNUNET_strdup (plugin_name);
- GNUNET_CONTAINER_DLL_insert (wp_head,
- wp_tail,
- wp);
- wp->rc = 1;
- return plugin;
-}
-
-
-/**
- * Unload a WIRE plugin.
- *
- * @param plugin the plugin to unload
- */
-void
-TALER_WIRE_plugin_unload (struct TALER_WIRE_Plugin *plugin)
-{
- struct WirePlugin *wp;
- char *lib_name;
-
- if (NULL == plugin)
- return;
- for (wp = wp_head; NULL != wp; wp = wp->next)
- {
- if (plugin == wp->plugin)
- {
- wp->rc--;
- if (0 < wp->rc)
- return;
- GNUNET_CONTAINER_DLL_remove (wp_head,
- wp_tail,
- wp);
- GNUNET_free (wp->type);
- GNUNET_free (wp);
- break;
- }
- }
- lib_name = plugin->library_name;
- GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name,
- plugin));
- GNUNET_free (lib_name);
-}
-
-
-/* end of wire.c */
diff --git a/src/wire/wire_helper.c b/src/wire/wire_helper.c
index e6253983..4b7f092a 100644
--- a/src/wire/wire_helper.c
+++ b/src/wire/wire_helper.c
@@ -20,6 +20,7 @@
/**
* @file wire/wire_helper.c
* @brief Helper functions for dealing with wire formats
+
* @author Christian Grothoff <christian@grothoff.org>
*/
#include "platform.h"
@@ -33,23 +34,6 @@
/**
- * Maps wire methods to plugin names.
- */
-struct ConversionTable
-{
-
- /**
- * Wire method (e.g. 'iban', 'x-taler-bank', ..)
- */
- const char *method;
-
- /**
- * Plugin name, e.g. 'taler_bank', ..
- */
- const char *plugin_name;
-};
-
-/**
* Obtain the payment method from a @a payto_url
*
* @param payto_url the URL to parse
@@ -76,35 +60,23 @@ TALER_WIRE_payto_get_method (const char *payto_url)
/**
- * Get the plugin name from the payment method.
+ * Round the amount to something that can be
+ * transferred on the wire.
*
- * FIXME: this is ugly, would be better to have
- * a way to iterate over all plugins and interrogate
- * them as to what wire method(s) they support!
- *
- * @param method the method implemented by the plugin (for
- * simplicity, we assume 1 method is implemented by 1 plugin).
- * @return the plugin name, NULL if not found.
+ * @param[in,out] amount amount to round down
+ * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
+ * #GNUNET_SYSERR if the amount or currency was invalid
*/
-const char *
-TALER_WIRE_get_plugin_from_method (const char *method)
+int
+TALER_WIRE_amount_round (struct TALER_Amount *amount)
{
- static const struct ConversionTable ct[] = {
- {"x-taler-bank", "taler_bank"},
- {"iban", "taler_bank"},
- {NULL, NULL}
- };
-
- for (unsigned int i = 0;
- NULL != ct[i].method;
- i++)
- {
- if (0 == strcmp (method,
- ct[i].method))
- return ct[i].plugin_name;
- }
+ uint32_t delta;
- return NULL;
+ delta = amount->fraction % (TALER_AMOUNT_FRAC_BASE / 100);
+ if (0 == delta)
+ return GNUNET_NO;
+ amount->fraction -= delta;
+ return GNUNET_OK;
}