summaryrefslogtreecommitdiff
path: root/src/exchange-lib/testing_api_cmd_fakebank_transfer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange-lib/testing_api_cmd_fakebank_transfer.c')
-rw-r--r--src/exchange-lib/testing_api_cmd_fakebank_transfer.c756
1 files changed, 0 insertions, 756 deletions
diff --git a/src/exchange-lib/testing_api_cmd_fakebank_transfer.c b/src/exchange-lib/testing_api_cmd_fakebank_transfer.c
deleted file mode 100644
index 43f72573b..000000000
--- a/src/exchange-lib/testing_api_cmd_fakebank_transfer.c
+++ /dev/null
@@ -1,756 +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 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;
-
- /**
- * Wire transfer subject.
- */
- const char *subject;
-
- /**
- * Base URL of the bank serving the request.
- */
- const char *bank_url;
-
- /**
- * Money sender account number.
- */
- uint64_t debit_account_no;
-
- /**
- * Money receiver account number.
- */
- uint64_t credit_account_no;
-
- /**
- * 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;
-
- /**
- * 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;
-
- /**
- * 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 full_response full response from the exchange (for
- * logging, in case of errors)
- */
-static void
-add_incoming_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- uint64_t serial_id,
- const json_t *full_response)
-{
- struct FakebankTransferState *fts = cls;
- struct TALER_TESTING_Interpreter *is = fts->is;
-
- fts->aih = NULL;
- fts->serial_id = serial_id;
- 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;
- }
- 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;
- char *subject;
- struct TALER_BANK_AuthenticationData auth;
- struct TALER_ReservePublicKeyP reserve_pub;
-
- if (NULL != fts->subject)
- {
- subject = GNUNET_strdup (fts->subject);
- }
- else
- {
- /* 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 (&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);
- if (NULL == priv)
- {
- GNUNET_log_config_invalid
- (GNUNET_ERROR_TYPE_ERROR,
- section,
- "TIP_RESERVE_PRIV_FILENAME",
- "Failed to read private key");
- GNUNET_free (keys);
- GNUNET_free (section);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- fts->reserve_priv.eddsa_priv = *priv;
- 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, &reserve_pub.eddsa_pub);
- subject = GNUNET_STRINGS_data_to_string_alloc
- (&reserve_pub, sizeof (reserve_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,
- &auth,
- fts->exchange_url,
- subject,
- &fts->amount,
- fts->debit_account_no,
- fts->credit_account_no,
- &add_incoming_cb,
- fts);
- GNUNET_free (subject);
- 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);
- }
- 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;
- #define MANDATORY 6
- 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),
- TALER_TESTING_make_trait_url (0, fts->exchange_url),
- TALER_TESTING_MAKE_TRAIT_ROW_ID (&fts->serial_id),
- TALER_TESTING_make_trait_amount_obj (0, &fts->amount),
- };
-
- /**
- * 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,
- 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 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 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 *auth_username,
- const char *auth_password,
- const char *exchange_url)
-{
- 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->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 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;
-}
-
-
-/**
- * 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 *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
- const char *auth_username,
- const char *auth_password,
- const char *ref,
- const char *exchange_url)
-{
- 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->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 *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
- 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->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->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 */