diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-01-11 21:27:34 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-01-11 21:43:15 +0100 |
commit | 54fc83ee6b910d482948c6ec8185df7aab1b0cb1 (patch) | |
tree | 10c04cad1392659a9ccef469271f866e393ebb48 /src/exchange-lib/testing_api_cmd_fakebank_transfer.c | |
parent | 57ab9f9fdba607fcc3817adf58f37c5390f8d220 (diff) | |
download | exchange-54fc83ee6b910d482948c6ec8185df7aab1b0cb1.tar.xz |
fix cyclic dependency by combining exchange-lib and auditor-lib directories
Diffstat (limited to 'src/exchange-lib/testing_api_cmd_fakebank_transfer.c')
-rw-r--r-- | src/exchange-lib/testing_api_cmd_fakebank_transfer.c | 756 |
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 (§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); - 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 */ |