commit cbcc3727de347a2426ad6616ef577f0138b7d7e9
parent 9443c10d7feb0d91323869dd08ec61ca781564f4
Author: Christian Grothoff <christian@grothoff.org>
Date: Sat, 11 Jan 2020 23:06:10 +0100
add separate transfer and admin/add/incoming commands
Diffstat:
22 files changed, 1640 insertions(+), 1493 deletions(-)
diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am
@@ -41,7 +41,7 @@ libtalerbank_la_SOURCES = \
bank_api_common.c bank_api_common.h \
bank_api_credit.c \
bank_api_debit.c \
- bank_api_transaction.c \
+ bank_api_transfer.c \
bank_api_parse.c
libtalerbank_la_LIBADD = \
$(top_builddir)/src/json/libtalerjson.la \
@@ -70,8 +70,10 @@ libtalerbanktesting_la_LDFLAGS = \
-version-info 0:0:0 \
-no-undefined
libtalerbanktesting_la_SOURCES = \
+ testing_api_cmd_admin_add_incoming.c \
testing_api_cmd_history_credit.c \
testing_api_cmd_history_debit.c \
+ testing_api_cmd_transfer.c \
testing_api_helpers.c
libtalerbanktesting_la_LIBADD = \
$(top_builddir)/src/json/libtalerjson.la \
diff --git a/src/bank-lib/bank_api_transaction.c b/src/bank-lib/bank_api_transaction.c
@@ -1,368 +0,0 @@
-/*
- 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",
- ×tamp),
- 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/bank_api_transfer.c b/src/bank-lib/bank_api_transfer.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_transfer.c
+ * @brief Implementation of the /transfer/ 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 transfer 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 transfer 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 /transfer 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_transfer_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",
+ ×tamp),
+ 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 *transfer_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);
+ transfer_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 == transfer_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,
+ "/transfer");
+ 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,
+ transfer_obj)) )
+ {
+ GNUNET_break (0);
+ TALER_BANK_execute_wire_transfer_cancel (weh);
+ curl_easy_cleanup (eh);
+ json_decref (transfer_obj);
+ return NULL;
+ }
+ json_decref (transfer_obj);
+
+ weh->job = GNUNET_CURL_job_add2 (ctx,
+ eh,
+ weh->post_ctx.headers,
+ &handle_transfer_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_transfer.c */
diff --git a/src/bank-lib/fakebank_history.c b/src/bank-lib/fakebank_history.c
@@ -1,182 +0,0 @@
-/*
- This file is part of TALER
- (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 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/fakebank_history.c
- * @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"
-
-
-int
-TFH_build_history_response (struct MHD_Connection *connection,
- struct Transaction *pos,
- struct HistoryArgs *ha,
- Skip skip,
- Step step,
- CheckAdvance advance)
-{
-
- struct HistoryElement *history_results_head = NULL;
- struct HistoryElement *history_results_tail = NULL;
- struct HistoryElement *history_element = NULL;
- json_t *history;
- json_t *jresponse;
- int ret;
-
- while ( (NULL != pos) &&
- advance (ha,
- pos) )
- {
- json_t *trans;
- char *subject;
- const char *sign;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Found transaction over %s from %llu to %llu\n",
- TALER_amount2s (&pos->amount),
- (unsigned long long) pos->debit_account,
- (unsigned long long) pos->credit_account);
-
- if ( (! ( ( (ha->account_number == pos->debit_account) &&
- (0 != (ha->direction & TALER_BANK_DIRECTION_DEBIT)) ) ||
- ( (ha->account_number == pos->credit_account) &&
- (0 != (ha->direction & TALER_BANK_DIRECTION_CREDIT) ) ) ) ) ||
- ( (0 == (ha->direction & TALER_BANK_DIRECTION_CANCEL)) &&
- (GNUNET_YES == pos->rejected) ) )
- {
- pos = skip (ha,
- pos);
- continue;
- }
-
- GNUNET_asprintf (&subject,
- "%s %s",
- pos->subject,
- pos->exchange_base_url);
- sign =
- (ha->account_number == pos->debit_account)
- ? (pos->rejected ? "cancel-" : "-")
- : (pos->rejected ? "cancel+" : "+");
- trans = json_pack
- ("{s:I, s:o, s:o, s:s, s:I, 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),
- "sign", sign,
- "counterpart", (json_int_t)
- ( (ha->account_number == pos->debit_account)
- ? pos->credit_account
- : pos->debit_account),
- "wt_subject", subject);
- GNUNET_assert (NULL != trans);
- GNUNET_free (subject);
-
- history_element = GNUNET_new (struct HistoryElement);
- history_element->element = trans;
-
-
- /* XXX: the ordering feature is missing. */
-
- GNUNET_CONTAINER_DLL_insert_tail (history_results_head,
- history_results_tail,
- history_element);
- pos = step (ha, pos);
- }
-
- history = json_array ();
- if (NULL != history_results_head)
- history_element = history_results_head;
-
- while (NULL != history_element)
- {
- GNUNET_assert (0 ==
- json_array_append_new (history,
- history_element->element));
- history_element = history_element->next;
- if (NULL != history_element)
- GNUNET_free_non_null (history_element->prev);
- }
- GNUNET_free_non_null (history_results_tail);
-
- if (0 == json_array_size (history))
- {
- struct MHD_Response *resp;
-
- json_decref (history);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Returning empty transaction history\n");
- resp = MHD_create_response_from_buffer
- (0,
- "",
- MHD_RESPMEM_PERSISTENT);
- ret = MHD_queue_response (connection,
- MHD_HTTP_NO_CONTENT,
- resp);
- MHD_destroy_response (resp);
- return ret;
- }
-
- jresponse = json_pack ("{s:o}",
- "data",
- history);
- if (NULL == jresponse)
- {
- GNUNET_break (0);
- return MHD_NO;
- }
-
- /* Finally build response object */
- {
- struct MHD_Response *resp;
- void *json_str;
- size_t json_len;
-
- json_str = json_dumps (jresponse,
- JSON_INDENT (2));
- json_decref (jresponse);
- 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;
-}
diff --git a/src/bank-lib/test_bank_api.c b/src/bank-lib/test_bank_api.c
@@ -16,7 +16,6 @@
License along with TALER; see the file COPYING. If not,
see <http://www.gnu.org/licenses/>
*/
-
/**
* @file bank/test_bank_api.c
* @brief testcase to test bank's HTTP API
@@ -24,7 +23,6 @@
* @author Marcello Stanisci
* @author Christian Grothoff
*/
-
#include "platform.h"
#include "taler_util.h"
#include "taler_signatures.h"
@@ -45,6 +43,16 @@
static char *bank_url;
/**
+ * Account URL.
+ */
+static char *account_url;
+
+/**
+ * payto://-URL of another account.
+ */
+static char *payto_url;
+
+/**
* Handle to the Py-bank daemon.
*/
static struct GNUNET_OS_Process *bankd;
@@ -56,26 +64,6 @@ static struct GNUNET_OS_Process *bankd;
static int WITH_FAKEBANK;
/**
- * Transfer @a amount from @a src account to @a dst using
- * @a subject and the @a label for the command.
- */
-#define TRANSFER(label,amount,src,dst,subject) \
- TALER_TESTING_cmd_fakebank_transfer_with_subject (label, \
- amount, \
- bank_url, \
- src, \
- dst, \
- AUTHS[src \
- - 1].details.basic. \
- username, \
- AUTHS[src \
- - 1].details.basic. \
- password, \
- subject, \
- "http://exchange.net/")
-
-
-/**
* Main function that will tell the interpreter what commands to
* run.
*
@@ -85,89 +73,54 @@ static void
run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Bank serves at `%s'\n",
- bank_url);
- extern struct TALER_BANK_AuthenticationData AUTHS[];
struct TALER_TESTING_Command commands[] = {
- TALER_TESTING_cmd_bank_history ("history-0",
- bank_url,
- TALER_TESTING_BANK_ACCOUNT_NUMBER,
- TALER_BANK_DIRECTION_BOTH,
- GNUNET_YES,
+ TALER_TESTING_cmd_bank_credits ("history-0",
+ account_url,
NULL,
1),
- /* WARNING: old API has expected http response code among
- * the parameters, although it was always set as '200 OK' */
- TRANSFER ("debit-1",
- "KUDOS:5.01",
- TALER_TESTING_EXCHANGE_ACCOUNT_NUMBER,
- TALER_TESTING_BANK_ACCOUNT_NUMBER,
- "subject 1"),
- TALER_TESTING_cmd_bank_history ("history-1c",
- bank_url,
- TALER_TESTING_BANK_ACCOUNT_NUMBER,
- TALER_BANK_DIRECTION_CREDIT,
- GNUNET_YES,
- NULL,
- 5),
- TALER_TESTING_cmd_bank_history ("history-1d",
- bank_url,
- TALER_TESTING_BANK_ACCOUNT_NUMBER,
- TALER_BANK_DIRECTION_DEBIT,
- GNUNET_YES,
+ TALER_TESTING_cmd_admin_add_incoming ("debit-1",
+ "KUDOS:5.01",
+ account_url,
+ payto_url,
+ NULL,
+ NULL),
+ TALER_TESTING_cmd_bank_credits ("history-1c",
+ account_url,
NULL,
5),
- TRANSFER ("debit-2",
- "KUDOS:3.21",
- TALER_TESTING_EXCHANGE_ACCOUNT_NUMBER,
- TALER_TESTING_USER_ACCOUNT_NUMBER,
- "subject 2"),
+ TALER_TESTING_cmd_bank_debits ("history-1d",
+ account_url,
+ NULL,
+ 5),
+ TALER_TESTING_cmd_admin_add_incoming ("debit-2",
+ "KUDOS:3.21",
+ account_url,
+ payto_url,
+ NULL,
+ NULL),
TRANSFER ("credit-2",
"KUDOS:3.22",
TALER_TESTING_USER_ACCOUNT_NUMBER,
TALER_TESTING_EXCHANGE_ACCOUNT_NUMBER,
"credit 2"),
- TALER_TESTING_cmd_bank_history ("history-2b",
- bank_url,
- TALER_TESTING_EXCHANGE_ACCOUNT_NUMBER,
- TALER_BANK_DIRECTION_BOTH,
- GNUNET_YES,
- NULL,
- 5),
- TALER_TESTING_cmd_bank_history ("history-2bi",
- bank_url,
- TALER_TESTING_EXCHANGE_ACCOUNT_NUMBER,
- TALER_BANK_DIRECTION_BOTH,
- GNUNET_YES,
- "debit-1",
- 5),
- TRANSFER ("credit-for-reject-1",
- "KUDOS:1.01",
- TALER_TESTING_BANK_ACCOUNT_NUMBER,
- TALER_TESTING_EXCHANGE_ACCOUNT_NUMBER,
- "subject 3"),
- TALER_TESTING_cmd_bank_reject ("reject-1",
- bank_url,
- "credit-for-reject-1"),
- TALER_TESTING_cmd_bank_history ("history-r1",
- bank_url,
- TALER_TESTING_BANK_ACCOUNT_NUMBER,
- TALER_BANK_DIRECTION_BOTH,
- GNUNET_YES,
- NULL,
- 5),
- TALER_TESTING_cmd_bank_history ("history-r1c",
- bank_url,
- TALER_TESTING_BANK_ACCOUNT_NUMBER,
- TALER_BANK_DIRECTION_BOTH
- | TALER_BANK_DIRECTION_CANCEL,
- GNUNET_YES,
- NULL,
- 5),
+ TALER_TESTING_cmd_bank_debits ("history-2b",
+ account_url,
+ NULL,
+ 5),
TALER_TESTING_cmd_end ()
};
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Bank serves at `%s'\n",
+ bank_url);
+ GNUNET_asprintf (&account_url,
+ "%s/%s",
+ base_url,
+ "alice");
+ GNUNET_asprintf (&payto_url,
+ "payto://x-taler-bank/%s/%s",
+ base_url,
+ "bob");
if (GNUNET_YES == WITH_FAKEBANK)
TALER_TESTING_run_with_fakebank (is,
commands,
diff --git a/src/bank-lib/testing_api_cmd_admin_add_incoming.c b/src/bank-lib/testing_api_cmd_admin_add_incoming.c
@@ -0,0 +1,625 @@
+/*
+ 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_cmd_admin_add_incoming.c
+ * @brief implementation of a bank /admin/add-incoming command
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include "backoff.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_bank_service.h"
+#include "taler_fakebank_lib.h"
+#include "taler_signatures.h"
+#include "taler_testing_lib.h"
+#include "taler_testing_bank_lib.h"
+
+
+/**
+ * State for a "fakebank transfer" CMD.
+ */
+struct AdminAddIncomingState
+{
+
+ /**
+ * Label of any command that can trait-offer a reserve priv.
+ */
+ const char *reserve_reference;
+
+ /**
+ * Wire transfer amount.
+ */
+ struct TALER_Amount amount;
+
+ /**
+ * Base URL of the debit account.
+ */
+ const char *debit_url;
+
+ /**
+ * Money receiver account URL.
+ */
+ const char *payto_credit_account;
+
+ /**
+ * Username to use for authentication.
+ */
+ struct TALER_BANK_AuthenticationData auth;
+
+ /**
+ * Set (by the interpreter) to the reserve's private key
+ * we used to make a wire transfer subject line with.
+ */
+ 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;
+
+ /**
+ * Interpreter state.
+ */
+ struct TALER_TESTING_Interpreter *is;
+
+ /**
+ * Set to the wire transfer's unique ID.
+ */
+ uint64_t serial_id;
+
+ /**
+ * Timestamp of the transaction (as returned from the bank).
+ */
+ struct GNUNET_TIME_Absolute timestamp;
+
+ /**
+ * Merchant instance. Sometimes used to get the tip reserve
+ * private key by reading the appropriate config section.
+ */
+ const char *instance;
+
+ /**
+ * Configuration filename. Used to get the tip reserve key
+ * filename (used to obtain a public key to write in the
+ * transfer subject).
+ */
+ const char *config_filename;
+
+ /**
+ * Task scheduled to try later.
+ */
+ struct GNUNET_SCHEDULER_Task *retry_task;
+
+ /**
+ * How long do we wait until we retry?
+ */
+ struct GNUNET_TIME_Relative backoff;
+
+ /**
+ * Was this command modified via
+ * #TALER_TESTING_cmd_admin_add_incoming_with_retry to
+ * enable retries?
+ */
+ int do_retry;
+};
+
+
+/**
+ * Run the "fakebank transfer" CMD.
+ *
+ * @param cls closure.
+ * @param cmd CMD being run.
+ * @param is interpreter state.
+ */
+static void
+fakebank_transfer_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is);
+
+
+/**
+ * Task scheduled to re-try #fakebank_transfer_run.
+ *
+ * @param cls a `struct AdminAddIncomingState`
+ */
+static void
+do_retry (void *cls)
+{
+ struct AdminAddIncomingState *fts = cls;
+
+ fts->retry_task = NULL;
+ fakebank_transfer_run (fts,
+ NULL,
+ fts->is);
+}
+
+
+/**
+ * This callback will process the fakebank response to the wire
+ * transfer. It just checks whether the HTTP response code is
+ * acceptable.
+ *
+ * @param cls closure with the interpreter state
+ * @param http_status HTTP response code, #MHD_HTTP_OK (200) for
+ * successful status request; 0 if the exchange's reply is
+ * bogus (fails to follow the protocol)
+ * @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 json raw response
+ */
+static void
+confirmation_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 AdminAddIncomingState *fts = cls;
+ struct TALER_TESTING_Interpreter *is = fts->is;
+
+ fts->aih = NULL;
+ if (MHD_HTTP_OK != http_status)
+ {
+ if (GNUNET_YES == fts->do_retry)
+ {
+ if ( (0 == http_status) ||
+ (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
+ (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
+ {
+ GNUNET_log
+ (GNUNET_ERROR_TYPE_INFO,
+ "Retrying fakebank transfer failed with %u/%d\n",
+ http_status,
+ (int) ec);
+ /* on DB conflicts, do not use backoff */
+ if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
+ fts->backoff = GNUNET_TIME_UNIT_ZERO;
+ else
+ fts->backoff = EXCHANGE_LIB_BACKOFF (fts->backoff);
+ fts->retry_task = GNUNET_SCHEDULER_add_delayed
+ (fts->backoff,
+ &do_retry,
+ fts);
+ return;
+ }
+ }
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Fakebank returned HTTP status %u/%d\n",
+ http_status,
+ (int) ec);
+ TALER_TESTING_interpreter_fail (is);
+ return;
+ }
+
+ fts->serial_id = serial_id;
+ fts->timestamp = timestamp;
+ TALER_TESTING_interpreter_next (is);
+}
+
+
+/**
+ * Run the "fakebank transfer" CMD.
+ *
+ * @param cls closure.
+ * @param cmd CMD being run.
+ * @param is interpreter state.
+ */
+static void
+fakebank_transfer_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct AdminAddIncomingState *fts = cls;
+
+ /* Use reserve public key as subject */
+ if (NULL != fts->reserve_reference)
+ {
+ 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
+ {
+ if (NULL != fts->instance)
+ {
+ 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 (§ion,
+ "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_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);
+ }
+ }
+ GNUNET_CRYPTO_eddsa_key_get_public (&fts->reserve_priv.eddsa_priv,
+ &fts->reserve_pub.eddsa_pub);
+ fts->is = is;
+ fts->aih
+ = TALER_BANK_admin_add_incoming
+ (TALER_TESTING_interpreter_get_context (is),
+ fts->debit_url,
+ &fts->auth,
+ &fts->reserve_pub,
+ &fts->amount,
+ fts->payto_credit_account,
+ &confirmation_cb,
+ fts);
+ if (NULL == fts->aih)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (is);
+ return;
+ }
+}
+
+
+/**
+ * Free the state of a "fakebank transfer" CMD, and possibly
+ * cancel a pending operation thereof.
+ *
+ * @param cls closure
+ * @param cmd current CMD being cleaned up.
+ */
+static void
+fakebank_transfer_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct AdminAddIncomingState *fts = cls;
+
+ if (NULL != fts->aih)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Command %s did not complete\n",
+ cmd->label);
+ TALER_BANK_admin_add_incoming_cancel (fts->aih);
+ fts->aih = NULL;
+ }
+ if (NULL != fts->retry_task)
+ {
+ GNUNET_SCHEDULER_cancel (fts->retry_task);
+ fts->retry_task = NULL;
+ }
+ GNUNET_free (fts);
+}
+
+
+/**
+ * Offer internal data from a "fakebank transfer" CMD to other
+ * commands.
+ *
+ * @param cls closure.
+ * @param ret[out] result
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ * @return #GNUNET_OK on success.
+ */
+static int
+fakebank_transfer_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ struct AdminAddIncomingState *fts = cls;
+ struct TALER_TESTING_Trait traits[] = {
+ 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_reserve_priv (0,
+ &fts->reserve_priv),
+ TALER_TESTING_make_trait_reserve_pub (0,
+ &fts->reserve_pub),
+ TALER_TESTING_trait_end ()
+ };
+
+ return TALER_TESTING_get_trait (traits,
+ ret,
+ trait,
+ index);
+}
+
+
+/**
+ * Create fakebank_transfer command, the subject line will be
+ * derived from a randomly created reserve priv. Note that that
+ * reserve priv will then be offered as trait.
+ *
+ * @param label command label.
+ * @param amount amount to transfer.
+ * @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.
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_admin_add_incoming
+ (const char *label,
+ const char *amount,
+ const char *account_base_url,
+ const struct TALER_BANK_AuthenticationData *auth,
+ const char *payto_credit_account)
+{
+ struct AdminAddIncomingState *fts;
+
+ fts = GNUNET_new (struct AdminAddIncomingState);
+ fts->debit_url = account_base_url;
+ fts->payto_credit_account = payto_credit_account;
+ fts->auth = *auth;
+ 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;
+ }
+}
+
+
+/**
+ * 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
+ * of the wire transfer.
+ *
+ * @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 auth_username username identifying the @a
+ * debit_account_no at the bank.
+ * @param auth_password password for @a auth_username.
+ * @param ref reference to a command that can offer a reserve
+ * private key.
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_admin_add_incoming_with_ref
+ (const char *label,
+ const char *amount,
+ const char *account_base_url,
+ const struct TALER_BANK_AuthenticationData *auth,
+ const char *payto_credit_account,
+ const char *ref)
+{
+ struct AdminAddIncomingState *fts;
+
+ fts = GNUNET_new (struct AdminAddIncomingState);
+ fts->debit_url = account_base_url;
+ fts->payto_credit_account = payto_credit_account;
+ fts->auth = *auth;
+ fts->reserve_reference = ref;
+ 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;
+ }
+}
+
+
+/**
+ * Create "fakebank transfer" CMD, letting the caller specifying
+ * the merchant instance. This version is useful when a tip
+ * reserve should be topped up, in fact the interpreter will need
+ * the "tipping instance" in order to get the instance public key
+ * and make a wire transfer subject out of it.
+ *
+ * @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 instance the instance that runs the tipping. Under this
+ * instance, the configuration file will provide the private
+ * key of the tipping reserve. This data will then used to
+ * construct the wire transfer subject line.
+ * @param config_filename configuration file to use.
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_admin_add_incoming_with_instance
+ (const char *label,
+ const char *amount,
+ const char *account_base_url,
+ const struct TALER_BANK_AuthenticationData *auth,
+ const char *payto_credit_account,
+ const char *instance,
+ const char *config_filename)
+{
+ struct AdminAddIncomingState *fts;
+
+ fts = GNUNET_new (struct AdminAddIncomingState);
+ fts->debit_url = account_base_url;
+ fts->payto_credit_account = payto_credit_account;
+ fts->auth = *auth;
+ fts->instance = instance;
+ fts->config_filename = config_filename;
+ 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;
+ }
+}
+
+
+/**
+ * Modify a fakebank transfer command to enable retries when the
+ * reserve is not yet full or we get other transient errors from the
+ * fakebank.
+ *
+ * @param cmd a fakebank transfer command
+ * @return the command with retries enabled
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_admin_add_incoming_retry (struct TALER_TESTING_Command cmd)
+{
+ struct AdminAddIncomingState *fts;
+
+ GNUNET_assert (&fakebank_transfer_run == cmd.run);
+ fts = cmd.cls;
+ fts->do_retry = GNUNET_YES;
+ return cmd;
+}
+
+
+/* end of testing_api_cmd_admin_add_incoming.c */
diff --git a/src/bank-lib/testing_api_cmd_history_credit.c b/src/bank-lib/testing_api_cmd_history_credit.c
@@ -60,6 +60,11 @@ struct HistoryState
struct TALER_BANK_CreditHistoryHandle *hh;
/**
+ * Authentication data for the operation.
+ */
+ struct TALER_BANK_AuthenticationData auth;
+
+ /**
* Expected number of results (= rows).
*/
uint64_t results_obtained;
@@ -683,7 +688,7 @@ history_run (void *cls,
hs->hh = TALER_BANK_credit_history (is->ctx,
hs->account_url,
- NULL,
+ &hs->auth,
row_id,
hs->num_results,
&history_cb,
@@ -731,6 +736,8 @@ history_cleanup (void *cls,
struct TALER_TESTING_Command
TALER_TESTING_cmd_bank_credits (const char *label,
const char *account_url,
+ const struct
+ TALER_BANK_AuthenticationData *auth,
const char *start_row_reference,
long long num_results)
{
@@ -740,7 +747,7 @@ TALER_TESTING_cmd_bank_credits (const char *label,
hs->account_url = GNUNET_strdup (account_url);
hs->start_row_reference = start_row_reference;
hs->num_results = num_results;
-
+ hs->auth = *auth;
{
struct TALER_TESTING_Command cmd = {
.label = label,
diff --git a/src/bank-lib/testing_api_cmd_history_debit.c b/src/bank-lib/testing_api_cmd_history_debit.c
@@ -57,6 +57,11 @@ struct HistoryState
long long num_results;
/**
+ * Login data to use to authenticate.
+ */
+ struct TALER_BANK_AuthenticationData auth;
+
+ /**
* Handle to a pending "history" operation.
*/
struct TALER_BANK_DebitHistoryHandle *hh;
@@ -67,7 +72,7 @@ struct HistoryState
uint64_t results_obtained;
/**
- * Set to GNUNET_YES if the callback detects something
+ * Set to #GNUNET_YES if the callback detects something
* unexpected.
*/
int failed;
@@ -684,7 +689,7 @@ history_run (void *cls,
hs->hh = TALER_BANK_debit_history (is->ctx,
hs->account_url,
- NULL,
+ &hs->auth,
row_id,
hs->num_results,
&history_cb,
@@ -722,6 +727,7 @@ history_cleanup (void *cls,
* @param label command label.
* @param account_url base URL of the account offering the "history"
* operation.
+ * @param auth login data to use
* @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.
@@ -731,6 +737,7 @@ history_cleanup (void *cls,
struct TALER_TESTING_Command
TALER_TESTING_cmd_bank_debits (const char *label,
const char *account_url,
+ const struct TALER_BANK_AuthenticationData *auth,
const char *start_row_reference,
long long num_results)
{
@@ -740,6 +747,7 @@ TALER_TESTING_cmd_bank_debits (const char *label,
hs->account_url = account_url;
hs->start_row_reference = start_row_reference;
hs->num_results = num_results;
+ hs->auth = *auth;
{
struct TALER_TESTING_Command cmd = {
diff --git a/src/bank-lib/testing_api_cmd_transfer.c b/src/bank-lib/testing_api_cmd_transfer.c
@@ -0,0 +1,394 @@
+/*
+ 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_cmd_transfer.c
+ * @brief implementation of a bank /transfer command
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include "backoff.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_bank_service.h"
+#include "taler_fakebank_lib.h"
+#include "taler_signatures.h"
+#include "taler_testing_lib.h"
+#include "taler_testing_bank_lib.h"
+
+
+/**
+ * State for a "transfer" CMD.
+ */
+struct TransferState
+{
+
+ /**
+ * Wire transfer amount.
+ */
+ struct TALER_Amount amount;
+
+ /**
+ * Base URL of the debit account.
+ */
+ const char *account_debit_url;
+
+ /**
+ * Money receiver account URL.
+ */
+ const char *payto_credit_account;
+
+ /**
+ * Username to use for authentication.
+ */
+ struct TALER_BANK_AuthenticationData auth;
+
+ /**
+ * Base URL of the exchange.
+ */
+ const char *exchange_base_url;
+
+ /**
+ * Wire transfer identifier to use.
+ */
+ struct TALER_WireTransferIdentifierRawP wtid;
+
+ /**
+ * Handle to the pending request at the fakebank.
+ */
+ struct TALER_BANK_WireExecuteHandle *weh;
+
+ /**
+ * Interpreter state.
+ */
+ struct TALER_TESTING_Interpreter *is;
+
+ /**
+ * Set to the wire transfer's unique ID.
+ */
+ uint64_t serial_id;
+
+ /**
+ * Timestamp of the transaction (as returned from the bank).
+ */
+ struct GNUNET_TIME_Absolute timestamp;
+
+ /**
+ * Configuration filename. Used to get the tip reserve key
+ * filename (used to obtain a public key to write in the
+ * transfer subject).
+ */
+ const char *config_filename;
+
+ /**
+ * Task scheduled to try later.
+ */
+ struct GNUNET_SCHEDULER_Task *retry_task;
+
+ /**
+ * How long do we wait until we retry?
+ */
+ struct GNUNET_TIME_Relative backoff;
+
+ /**
+ * Was this command modified via
+ * #TALER_TESTING_cmd_admin_add_incoming_with_retry to
+ * enable retries?
+ */
+ int do_retry;
+};
+
+
+/**
+ * Run the "transfer" CMD.
+ *
+ * @param cls closure.
+ * @param cmd CMD being run.
+ * @param is interpreter state.
+ */
+static void
+transfer_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is);
+
+
+/**
+ * Task scheduled to re-try #transfer_run.
+ *
+ * @param cls a `struct TransferState`
+ */
+static void
+do_retry (void *cls)
+{
+ struct TransferState *fts = cls;
+
+ fts->retry_task = NULL;
+ transfer_run (fts,
+ NULL,
+ fts->is);
+}
+
+
+/**
+ * This callback will process the fakebank response to the wire
+ * transfer. It just checks whether the HTTP response code is
+ * acceptable.
+ *
+ * @param cls closure with the interpreter state
+ * @param http_status HTTP response code, #MHD_HTTP_OK (200) for
+ * successful status request; 0 if the exchange's reply is
+ * bogus (fails to follow the protocol)
+ * @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.
+ */
+static void
+confirmation_cb (void *cls,
+ unsigned int http_status,
+ enum TALER_ErrorCode ec,
+ uint64_t serial_id,
+ struct GNUNET_TIME_Absolute timestamp)
+{
+ struct TransferState *fts = cls;
+ struct TALER_TESTING_Interpreter *is = fts->is;
+
+ fts->weh = NULL;
+ if (MHD_HTTP_OK != http_status)
+ {
+ if (GNUNET_YES == fts->do_retry)
+ {
+ if ( (0 == http_status) ||
+ (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
+ (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Retrying transfer failed with %u/%d\n",
+ http_status,
+ (int) ec);
+ /* on DB conflicts, do not use backoff */
+ if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
+ fts->backoff = GNUNET_TIME_UNIT_ZERO;
+ else
+ fts->backoff = EXCHANGE_LIB_BACKOFF (fts->backoff);
+ fts->retry_task = GNUNET_SCHEDULER_add_delayed
+ (fts->backoff,
+ &do_retry,
+ fts);
+ return;
+ }
+ }
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Fakebank returned HTTP status %u/%d\n",
+ http_status,
+ (int) ec);
+ TALER_TESTING_interpreter_fail (is);
+ return;
+ }
+
+ fts->serial_id = serial_id;
+ fts->timestamp = timestamp;
+ TALER_TESTING_interpreter_next (is);
+}
+
+
+/**
+ * Run the "transfer" CMD.
+ *
+ * @param cls closure.
+ * @param cmd CMD being run.
+ * @param is interpreter state.
+ */
+static void
+transfer_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct TransferState *fts = cls;
+ void *buf;
+ size_t buf_size;
+
+ TALER_BANK_prepare_wire_transfer (fts->payto_credit_account,
+ &fts->amount,
+ fts->exchange_base_url,
+ &fts->wtid,
+ &buf,
+ &buf_size);
+ fts->is = is;
+ fts->weh
+ = TALER_BANK_execute_wire_transfer
+ (TALER_TESTING_interpreter_get_context (is),
+ fts->account_debit_url,
+ &fts->auth,
+ buf,
+ buf_size,
+ &confirmation_cb,
+ fts);
+ GNUNET_free (buf);
+ if (NULL == fts->weh)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (is);
+ return;
+ }
+}
+
+
+/**
+ * Free the state of a "fakebank transfer" CMD, and possibly
+ * cancel a pending operation thereof.
+ *
+ * @param cls closure
+ * @param cmd current CMD being cleaned up.
+ */
+static void
+transfer_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct TransferState *fts = cls;
+
+ if (NULL != fts->weh)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Command %s did not complete\n",
+ cmd->label);
+ TALER_BANK_execute_wire_transfer_cancel (fts->weh);
+ fts->weh = NULL;
+ }
+ if (NULL != fts->retry_task)
+ {
+ GNUNET_SCHEDULER_cancel (fts->retry_task);
+ fts->retry_task = NULL;
+ }
+ GNUNET_free (fts);
+}
+
+
+/**
+ * Offer internal data from a "fakebank transfer" CMD to other
+ * commands.
+ *
+ * @param cls closure.
+ * @param ret[out] result
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ * @return #GNUNET_OK on success.
+ */
+static int
+transfer_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ struct TransferState *fts = cls;
+ struct TALER_TESTING_Trait traits[] = {
+ TALER_TESTING_make_trait_url (1, fts->account_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->account_debit_url),
+ TALER_TESTING_make_trait_amount_obj (0, &fts->amount),
+ TALER_TESTING_make_trait_absolute_time (0, &fts->timestamp),
+ TALER_TESTING_make_trait_wtid (0,
+ &fts->wtid),
+ TALER_TESTING_trait_end ()
+ };
+
+ return TALER_TESTING_get_trait (traits,
+ ret,
+ trait,
+ index);
+}
+
+
+/**
+ * Create transfer command.
+ *
+ * @param label command label.
+ * @param amount amount to transfer.
+ * @param account_base_url base URL of the account that implements this
+ * wire transer (which account gives money).
+ * @param auth authentication data to use
+ * @param payto_credit_account which account receives money.
+ * @param wtid wire transfer identifier to use
+ * @param exchange_base_url exchange URL to use
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_transfer
+ (const char *label,
+ const char *amount,
+ const char *account_base_url,
+ const struct TALER_BANK_AuthenticationData *auth,
+ const char *payto_credit_account,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const char *exchange_base_url)
+{
+ struct TransferState *fts;
+
+ fts = GNUNET_new (struct TransferState);
+ fts->account_debit_url = account_base_url;
+ fts->exchange_base_url = exchange_base_url;
+ fts->payto_credit_account = payto_credit_account;
+ fts->auth = *auth;
+ fts->wtid = *wtid;
+ 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 = &transfer_run,
+ .cleanup = &transfer_cleanup,
+ .traits = &transfer_traits
+ };
+
+ return cmd;
+ }
+}
+
+
+/**
+ * Modify a transfer command to enable retries when the reserve is not yet
+ * full or we get other transient errors from the bank.
+ *
+ * @param cmd a fakebank transfer command
+ * @return the command with retries enabled
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_transfer_retry (struct TALER_TESTING_Command cmd)
+{
+ struct TransferState *fts;
+
+ GNUNET_assert (&transfer_run == cmd.run);
+ fts = cmd.cls;
+ fts->do_retry = GNUNET_YES;
+ return cmd;
+}
+
+
+/* end of testing_api_cmd_transfer.c */
diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c
@@ -59,14 +59,13 @@ enum BenchmarkError
#define FIRST_INSTRUCTION -1
#define CMD_TRANSFER_TO_EXCHANGE(label, amount) \
- TALER_TESTING_cmd_fakebank_transfer_retry \
- (TALER_TESTING_cmd_fakebank_transfer (label, amount, \
- user_bank_account.details. \
- x_taler_bank.account_base_url, \
- exchange_payto_url, \
- "dummy_user", \
- "dummy_password", \
- "http://example.com/"))
+ TALER_TESTING_cmd_admin_add_incoming_retry \
+ (TALER_TESTING_cmd_admin_add_incoming (label, amount, \
+ user_bank_account.details. \
+ x_taler_bank.account_base_url, \
+ exchange_payto_url, \
+ "dummy_user", \
+ "dummy_password"))
/**
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
@@ -35,4 +35,6 @@ talerinclude_HEADERS = \
endif
-EXTRA_DIST = gauger.h
+EXTRA_DIST = \
+ backoff.h \
+ gauger.h
diff --git a/src/include/backoff.h b/src/include/backoff.h
@@ -0,0 +1,33 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-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 lib/backoff.h
+ * @brief backoff computation for the exchange lib
+ * @author Florian Dold
+ */
+#ifndef _TALER_BACKOFF_H
+#define _TALER_BACKOFF_H
+
+/**
+ * Random exponential backoff used in the exchange lib.
+ */
+#define EXCHANGE_LIB_BACKOFF(r) GNUNET_TIME_randomized_backoff ( \
+ (r), \
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2));
+
+#endif
diff --git a/src/include/taler_bank_service.h b/src/include/taler_bank_service.h
@@ -204,7 +204,6 @@ typedef void
/**
-
* Execute a wire transfer.
*
* @param ctx context for HTTP interaction
diff --git a/src/include/taler_testing_bank_lib.h b/src/include/taler_testing_bank_lib.h
@@ -108,6 +108,7 @@ TALER_TESTING_has_in_name (const char *prog,
* @param label command label.
* @param account_url base URL of the account offering the "history"
* operation.
+ * @param auth login data to use
* @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.
@@ -118,6 +119,8 @@ TALER_TESTING_has_in_name (const char *prog,
struct TALER_TESTING_Command
TALER_TESTING_cmd_bank_credits (const char *label,
const char *account_url,
+ const struct
+ TALER_BANK_AuthenticationData *auth,
const char *start_row_reference,
long long num_results);
@@ -128,6 +131,7 @@ TALER_TESTING_cmd_bank_credits (const char *label,
* @param label command label.
* @param account_url base URL of the account offering the "history"
* operation.
+ * @param auth authentication data
* @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.
@@ -137,8 +141,124 @@ TALER_TESTING_cmd_bank_credits (const char *label,
struct TALER_TESTING_Command
TALER_TESTING_cmd_bank_debits (const char *label,
const char *account_url,
+ const struct TALER_BANK_AuthenticationData *auth,
const char *start_row_reference,
long long num_results);
+/**
+ * Create transfer command.
+ *
+ * @param label command label.
+ * @param amount amount to transfer.
+ * @param account_base_url base URL of the account that implements this
+ * wire transer (which account gives money).
+ * @param auth authentication data to use
+ * @param payto_credit_account which account receives money.
+ * @param wtid wire transfer identifier to use
+ * @param exchange_base_url exchange URL to use
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_transfer (const char *label,
+ const char *amount,
+ const char *account_base_url,
+ const struct TALER_BANK_AuthenticationData *auth,
+ const char *payto_credit_account,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const char *exchange_base_url);
+
+
+/**
+ * Create /admin/add-incoming command.
+ *
+ * @param label command label.
+ * @param amount amount to transfer.
+ * @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 authentication data
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_admin_add_incoming (const char *label,
+ const char *amount,
+ const char *account_base_url,
+ const struct
+ TALER_BANK_AuthenticationData *auth,
+ const char *payto_credit_account);
+
+
+/**
+ * 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
+ * of the wire transfer.
+ *
+ * @param label command label.
+ * @param amount the amount to transfer.
+ * @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 authentication data
+ * @param ref reference to a command that can offer a reserve
+ * private key.
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_admin_add_incoming_with_ref (const char *label,
+ const char *amount,
+ const char *account_base_url,
+ const struct
+ TALER_BANK_AuthenticationData *
+ auth,
+ const char *payto_credit_account,
+ const char *ref);
+
+
+/**
+ * Create "fakebank transfer" CMD, letting the caller specifying
+ * the merchant instance. This version is useful when a tip
+ * reserve should be topped up, in fact the interpreter will need
+ * the "tipping instance" in order to get the instance public key
+ * and make a wire transfer subject out of it.
+ *
+ * @param label command label.
+ * @param amount amount to transfer.
+ * @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 authentication data
+ * @param instance the instance that runs the tipping. Under this
+ * instance, the configuration file will provide the private
+ * key of the tipping reserve. This data will then used to
+ * construct the wire transfer subject line.
+ * @param config_filename configuration file to use.
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_admin_add_incoming_with_instance (const char *label,
+ const char *amount,
+ const char *account_base_url,
+ const struct
+ TALER_BANK_AuthenticationData
+ *auth,
+ const char *
+ payto_credit_account,
+ const char *instance,
+ const char *config_filename);
+
+
+/**
+ * Modify a fakebank transfer command to enable retries when the
+ * reserve is not yet full or we get other transient errors from
+ * the fakebank.
+ *
+ * @param cmd a fakebank transfer command
+ * @return the command with retries enabled
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_admin_add_incoming_retry (struct TALER_TESTING_Command cmd);
+
+
#endif
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
@@ -709,118 +709,6 @@ TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb,
/* ************** Specific interpreter commands ************ */
-/**
- * Create fakebank_transfer command, the subject line will be
- * derived from a randomly created reserve priv. Note that that
- * reserve priv will then be offered as trait.
- *
- * @param label command label.
- * @param amount amount to transfer.
- * @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.
- * This data is used for tracking purposes (FIXME: explain
- * _how_).
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer (const char *label,
- const char *amount,
- 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 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
- * of the wire transfer.
- *
- * @param label command label.
- * @param amount the amount to transfer.
- * @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 ref reference to a command that can offer a reserve
- * private key.
- * @param exchange_url the exchage involved in the transfer,
- * tipically receiving the money in order to fuel a reserve.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_with_ref (const char *label,
- const char *amount,
- const char *account_base_url,
- const char *payto_credit_account,
-
- const char *auth_username,
- const char *auth_password,
- const char *ref,
- const char *exchange_url);
-
-
-/**
- * Create "fakebank transfer" CMD, letting the caller specifying
- * the merchant instance. This version is useful when a tip
- * reserve should be topped up, in fact the interpreter will need
- * the "tipping instance" in order to get the instance public key
- * and make a wire transfer subject out of it.
- *
- * @param label command label.
- * @param amount amount to transfer.
- * @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 instance the instance that runs the tipping. Under this
- * instance, the configuration file will provide the private
- * key of the tipping reserve. This data will then used to
- * construct the wire transfer subject line.
- * @param exchange_url which exchange is involved in this transfer.
- * This data is used for tracking purposes (FIXME: explain
- * _how_).
- * @param config_filename configuration file to use.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_with_instance (const char *label,
- const char *amount,
- const char *account_base_url,
- const char *
- payto_credit_account,
- const char *auth_username,
- const char *auth_password,
- const char *instance,
- const char *exchange_url,
- const char *config_filename);
-
-
-/**
- * Modify a fakebank transfer command to enable retries when the
- * reserve is not yet full or we get other transient errors from
- * the fakebank.
- *
- * @param cmd a fakebank transfer command
- * @return the command with retries enabled
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_retry (struct TALER_TESTING_Command cmd);
-
/**
* Make a "wirewatch" CMD.
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
@@ -16,7 +16,6 @@ libtalerexchange_la_LDFLAGS = \
-version-info 4:0:0 \
-no-undefined
libtalerexchange_la_SOURCES = \
- backoff.h \
exchange_api_curl_defaults.c exchange_api_curl_defaults.h \
exchange_api_common.c \
exchange_api_handle.c exchange_api_handle.h \
@@ -77,7 +76,6 @@ libtalertesting_la_SOURCES = \
testing_api_cmd_exec_wirewatch.c \
testing_api_cmd_exec_keyup.c \
testing_api_cmd_exec_auditor-sign.c \
- testing_api_cmd_fakebank_transfer.c \
testing_api_cmd_withdraw.c \
testing_api_cmd_wire.c \
testing_api_cmd_refund.c \
diff --git a/src/lib/backoff.h b/src/lib/backoff.h
@@ -1,38 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-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 lib/backoff.h
- * @brief backoff computation for the exchange lib
- * @author Florian Dold
- */
-
-
-#ifndef _TALER_BACKOFF_H
-#define _TALER_BACKOFF_H
-
-#include "platform.h"
-#include <gnunet/gnunet_time_lib.h>
-
-/**
- * Random exponential backoff used in the exchange lib.
- */
-#define EXCHANGE_LIB_BACKOFF(r) GNUNET_TIME_randomized_backoff ( \
- (r), \
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2));
-
-#endif
diff --git a/src/lib/test_auditor_api.c b/src/lib/test_auditor_api.c
@@ -111,11 +111,11 @@ static char *exchange_url;
* @param amount amount to transfer, i.e. "EUR:1"
*/
#define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
- TALER_TESTING_cmd_fakebank_transfer (label, amount, \
- fakebank_url, USER_ACCOUNT_NO, \
- EXCHANGE_ACCOUNT_NO, \
- USER_LOGIN_NAME, USER_LOGIN_PASS, \
- exchange_url)
+ TALER_TESTING_cmd_admin_add_incoming (label, amount, \
+ fakebank_url, USER_ACCOUNT_NO, \
+ EXCHANGE_ACCOUNT_NO, \
+ USER_LOGIN_NAME, USER_LOGIN_PASS, \
+ exchange_url)
/**
* Run wire transfer of funds from some user's account to the
@@ -125,7 +125,7 @@ static char *exchange_url;
* @param amount amount to transfer, i.e. "EUR:1"
*/
#define CMD_TRANSFER_TO_EXCHANGE_SUBJECT(label,amount,subject) \
- TALER_TESTING_cmd_fakebank_transfer_with_subject \
+ TALER_TESTING_cmd_admin_add_incoming_with_subject \
(label, amount, fakebank_url, USER_ACCOUNT_NO, \
EXCHANGE_ACCOUNT_NO, USER_LOGIN_NAME, USER_LOGIN_PASS, \
subject, exchange_url)
diff --git a/src/lib/test_exchange_api.c b/src/lib/test_exchange_api.c
@@ -111,11 +111,11 @@ static char *auditor_url;
* @param amount amount to transfer, i.e. "EUR:1"
*/
#define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
- TALER_TESTING_cmd_fakebank_transfer (label, amount, \
- fakebank_url, USER_ACCOUNT_NO, \
- EXCHANGE_ACCOUNT_NO, \
- USER_LOGIN_NAME, USER_LOGIN_PASS, \
- exchange_url)
+ TALER_TESTING_cmd_admin_add_incoming (label, amount, \
+ fakebank_url, USER_ACCOUNT_NO, \
+ EXCHANGE_ACCOUNT_NO, \
+ USER_LOGIN_NAME, USER_LOGIN_PASS, \
+ exchange_url)
/**
* Run wire transfer of funds from some user's account to the
@@ -125,7 +125,7 @@ static char *auditor_url;
* @param amount amount to transfer, i.e. "EUR:1"
*/
#define CMD_TRANSFER_TO_EXCHANGE_SUBJECT(label,amount,subject) \
- TALER_TESTING_cmd_fakebank_transfer_with_subject \
+ TALER_TESTING_cmd_admin_add_incoming_with_subject \
(label, amount, fakebank_url, USER_ACCOUNT_NO, \
EXCHANGE_ACCOUNT_NO, USER_LOGIN_NAME, USER_LOGIN_PASS, \
subject, exchange_url)
diff --git a/src/lib/test_exchange_api_revocation.c b/src/lib/test_exchange_api_revocation.c
@@ -98,11 +98,11 @@ static char *auditor_url;
* @param amount amount to transfer, i.e. "EUR:1"
*/
#define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
- TALER_TESTING_cmd_fakebank_transfer (label, amount, \
- fakebank_url, USER_ACCOUNT_NO, \
- EXCHANGE_ACCOUNT_NO, \
- USER_LOGIN_NAME, USER_LOGIN_PASS, \
- exchange_url)
+ TALER_TESTING_cmd_admin_add_incoming (label, amount, \
+ fakebank_url, USER_ACCOUNT_NO, \
+ EXCHANGE_ACCOUNT_NO, \
+ USER_LOGIN_NAME, USER_LOGIN_PASS, \
+ exchange_url)
/**
* Main function that will tell the interpreter what commands to
diff --git a/src/lib/test_exchange_api_twisted.c b/src/lib/test_exchange_api_twisted.c
@@ -116,11 +116,11 @@ static struct GNUNET_OS_Process *twisterd;
* @param url exchange_url
*/
#define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
- TALER_TESTING_cmd_fakebank_transfer (label, amount, \
- fakebank_url, USER_ACCOUNT_NO, \
- EXCHANGE_ACCOUNT_NO, \
- USER_LOGIN_NAME, USER_LOGIN_PASS, \
- exchange_url)
+ TALER_TESTING_cmd_admin_add_incoming (label, amount, \
+ fakebank_url, USER_ACCOUNT_NO, \
+ EXCHANGE_ACCOUNT_NO, \
+ USER_LOGIN_NAME, USER_LOGIN_PASS, \
+ exchange_url)
/**
* Run wire transfer of funds from some user's account to the
@@ -130,7 +130,7 @@ static struct GNUNET_OS_Process *twisterd;
* @param amount amount to transfer, i.e. "EUR:1"
*/
#define CMD_TRANSFER_TO_EXCHANGE_SUBJECT(label,amount,subject) \
- TALER_TESTING_cmd_fakebank_transfer_with_subject \
+ TALER_TESTING_cmd_admin_add_incoming_with_subject \
(label, amount, fakebank_url, USER_ACCOUNT_NO, \
EXCHANGE_ACCOUNT_NO, USER_LOGIN_NAME, USER_LOGIN_PASS, \
subject)
diff --git a/src/lib/testing_api_cmd_fakebank_transfer.c b/src/lib/testing_api_cmd_fakebank_transfer.c
@@ -1,661 +0,0 @@
-/*
- 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_cmd_fakebank_transfer.c
- * @brief implementation of a fakebank wire transfer command
- * @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_bank_service.h"
-#include "taler_fakebank_lib.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-#include "taler_testing_bank_lib.h"
-#include "backoff.h"
-
-/**
- * State for a "fakebank transfer" CMD.
- */
-struct FakebankTransferState
-{
-
- /**
- * Label of any command that can trait-offer a reserve priv.
- */
- const char *reserve_reference;
-
- /**
- * Wire transfer amount.
- */
- struct TALER_Amount amount;
-
- /**
- * Base URL of the debit account.
- */
- const char *debit_url;
-
- /**
- * Money receiver account URL.
- */
- const char *payto_credit_account;
-
- /**
- * Username to use for authentication.
- */
- const char *auth_username;
-
- /**
- * Password to use for authentication.
- */
- const char *auth_password;
-
- /**
- * Set (by the interpreter) to the reserve's private key
- * we used to make a wire transfer subject line with.
- */
- 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;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * Set to the wire transfer's unique ID.
- */
- uint64_t serial_id;
-
- /**
- * Timestamp of the transaction (as returned from the bank).
- */
- struct GNUNET_TIME_Absolute timestamp;
-
- /**
- * Exchange URL. This value is fed to the bank when requesting
- * the wire transfer; note: the bank needs it because a merchant
- * might want to know which exchange performed a wire transfer to
- * them, just by looking at bank records.
- */
- const char *exchange_url;
-
- /**
- * Merchant instance. Sometimes used to get the tip reserve
- * private key by reading the appropriate config section.
- */
- const char *instance;
-
- /**
- * Configuration filename. Used to get the tip reserve key
- * filename (used to obtain a public key to write in the
- * transfer subject).
- */
- const char *config_filename;
-
- /**
- * Task scheduled to try later.
- */
- struct GNUNET_SCHEDULER_Task *retry_task;
-
- /**
- * How long do we wait until we retry?
- */
- struct GNUNET_TIME_Relative backoff;
-
- /**
- * Was this command modified via
- * #TALER_TESTING_cmd_fakebank_transfer_with_retry to
- * enable retries?
- */
- int do_retry;
-};
-
-
-/**
- * Run the "fakebank transfer" CMD.
- *
- * @param cls closure.
- * @param cmd CMD being run.
- * @param is interpreter state.
- */
-static void
-fakebank_transfer_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is);
-
-
-/**
- * Task scheduled to re-try #fakebank_transfer_run.
- *
- * @param cls a `struct FakebankTransferState`
- */
-static void
-do_retry (void *cls)
-{
- struct FakebankTransferState *fts = cls;
-
- fts->retry_task = NULL;
- fakebank_transfer_run (fts,
- NULL,
- fts->is);
-}
-
-
-/**
- * This callback will process the fakebank response to the wire
- * transfer. It just checks whether the HTTP response code is
- * acceptable.
- *
- * @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for
- * successful status request; 0 if the exchange's reply is
- * bogus (fails to follow the protocol)
- * @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 json raw response
- */
-static void
-confirmation_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 FakebankTransferState *fts = cls;
- struct TALER_TESTING_Interpreter *is = fts->is;
-
- fts->aih = NULL;
- if (MHD_HTTP_OK != http_status)
- {
- if (GNUNET_YES == fts->do_retry)
- {
- if ( (0 == http_status) ||
- (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
- (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
- {
- GNUNET_log
- (GNUNET_ERROR_TYPE_INFO,
- "Retrying fakebank transfer failed with %u/%d\n",
- http_status,
- (int) ec);
- /* on DB conflicts, do not use backoff */
- if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
- fts->backoff = GNUNET_TIME_UNIT_ZERO;
- else
- fts->backoff = EXCHANGE_LIB_BACKOFF (fts->backoff);
- fts->retry_task = GNUNET_SCHEDULER_add_delayed
- (fts->backoff,
- &do_retry,
- fts);
- return;
- }
- }
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Fakebank returned HTTP status %u/%d\n",
- http_status,
- (int) ec);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- fts->serial_id = serial_id;
- fts->timestamp = timestamp;
- TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Run the "fakebank transfer" CMD.
- *
- * @param cls closure.
- * @param cmd CMD being run.
- * @param is interpreter state.
- */
-static void
-fakebank_transfer_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct FakebankTransferState *fts = cls;
- struct TALER_BANK_AuthenticationData auth;
-
- /* Use reserve public key as subject */
- if (NULL != fts->reserve_reference)
- {
- 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
- {
- if (NULL != fts->instance)
- {
- 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 (§ion,
- "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_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);
- }
- }
- 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->debit_url,
- &auth,
- &fts->reserve_pub,
- &fts->amount,
- fts->payto_credit_account,
- &confirmation_cb,
- fts);
- if (NULL == fts->aih)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-}
-
-
-/**
- * Free the state of a "fakebank transfer" CMD, and possibly
- * cancel a pending operation thereof.
- *
- * @param cls closure
- * @param cmd current CMD being cleaned up.
- */
-static void
-fakebank_transfer_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct FakebankTransferState *fts = cls;
-
- if (NULL != fts->aih)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %s did not complete\n",
- cmd->label);
- TALER_BANK_admin_add_incoming_cancel (fts->aih);
- fts->aih = NULL;
- }
- if (NULL != fts->retry_task)
- {
- GNUNET_SCHEDULER_cancel (fts->retry_task);
- fts->retry_task = NULL;
- }
- GNUNET_free (fts);
-}
-
-
-/**
- * Offer internal data from a "fakebank transfer" CMD to other
- * commands.
- *
- * @param cls closure.
- * @param ret[out] result
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- * @return #GNUNET_OK on success.
- */
-static int
-fakebank_transfer_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct FakebankTransferState *fts = cls;
- 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_reserve_priv (0,
- &fts->reserve_priv),
- TALER_TESTING_make_trait_reserve_pub (0,
- &fts->reserve_pub),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Create fakebank_transfer command, the subject line will be
- * derived from a randomly created reserve priv. Note that that
- * reserve priv will then be offered as trait.
- *
- * @param label command label.
- * @param amount amount to transfer.
- * @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 *account_base_url,
- const char *payto_credit_account,
- const char *auth_username,
- const char *auth_password,
- const char *exchange_url)
-{
- struct FakebankTransferState *fts;
-
- fts = GNUNET_new (struct FakebankTransferState);
- 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;
- 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;
- }
-}
-
-
-/**
- * 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
- * of the wire transfer.
- *
- * @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 auth_username username identifying the @a
- * debit_account_no at the bank.
- * @param auth_password password for @a auth_username.
- * @param ref reference to a command that can offer a reserve
- * private key.
- * @param exchange_url the exchage involved in the transfer,
- * tipically receiving the money in order to fuel a reserve.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_with_ref
- (const char *label,
- const char *amount,
- const char *account_base_url,
- const char *payto_credit_account,
- const char *auth_username,
- const char *auth_password,
- const char *ref,
- const char *exchange_url)
-{
- struct FakebankTransferState *fts;
-
- fts = GNUNET_new (struct FakebankTransferState);
- 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;
- 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;
- }
-}
-
-
-/**
- * Create "fakebank transfer" CMD, letting the caller specifying
- * the merchant instance. This version is useful when a tip
- * reserve should be topped up, in fact the interpreter will need
- * the "tipping instance" in order to get the instance public key
- * and make a wire transfer subject out of it.
- *
- * @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 instance the instance that runs the tipping. Under this
- * instance, the configuration file will provide the private
- * key of the tipping reserve. This data will then used to
- * construct the wire transfer subject line.
- * @param exchange_url which exchange is involved in this transfer.
- * @param config_filename configuration file to use.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_with_instance
- (const char *label,
- const char *amount,
- const char *account_base_url,
- const char *payto_credit_account,
- const char *auth_username,
- const char *auth_password,
- const char *instance,
- const char *exchange_url,
- const char *config_filename)
-{
- struct FakebankTransferState *fts;
-
- fts = GNUNET_new (struct FakebankTransferState);
- 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;
- fts->exchange_url = exchange_url;
- fts->config_filename = config_filename;
- 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;
- }
-}
-
-
-/**
- * Modify a fakebank transfer command to enable retries when the
- * reserve is not yet full or we get other transient errors from the
- * fakebank.
- *
- * @param cmd a fakebank transfer command
- * @return the command with retries enabled
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_retry (struct TALER_TESTING_Command cmd)
-{
- struct FakebankTransferState *fts;
-
- GNUNET_assert (&fakebank_transfer_run == cmd.run);
- fts = cmd.cls;
- fts->do_retry = GNUNET_YES;
- return cmd;
-}
-
-
-/* end of testing_api_cmd_fakebank_transfer.c */