diff options
Diffstat (limited to 'src/auditor-lib')
5 files changed, 380 insertions, 7 deletions
diff --git a/src/auditor-lib/Makefile.am b/src/auditor-lib/Makefile.am index 4589bc975..44849da22 100644 --- a/src/auditor-lib/Makefile.am +++ b/src/auditor-lib/Makefile.am @@ -41,6 +41,7 @@ libtalerauditortesting_la_LDFLAGS = \ -no-undefined libtalerauditortesting_la_SOURCES = \ testing_auditor_api_helpers.c \ + testing_auditor_api_cmd_deposit_confirmation.c \ testing_auditor_api_cmd_exec_auditor.c \ testing_auditor_api_cmd_exec_wire_auditor.c libtalerauditortesting_la_LIBADD = \ diff --git a/src/auditor-lib/auditor_api_deposit_confirmation.c b/src/auditor-lib/auditor_api_deposit_confirmation.c index 1ad6ddad7..736f326dd 100644 --- a/src/auditor-lib/auditor_api_deposit_confirmation.c +++ b/src/auditor-lib/auditor_api_deposit_confirmation.c @@ -156,7 +156,7 @@ verify_signatures (const struct GNUNET_HashCode *h_wire, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_CoinSpendSignatureP *exchange_sig, + const struct TALER_ExchangeSignatureP *exchange_sig, const struct TALER_MasterPublicKeyP *master_pub, struct GNUNET_TIME_Absolute ep_start, struct GNUNET_TIME_Absolute ep_expire, @@ -181,7 +181,7 @@ verify_signatures (const struct GNUNET_HashCode *h_wire, &dc.purpose, &exchange_sig->eddsa_signature, &exchange_pub->eddsa_pub)) - { + { GNUNET_break_op (0); TALER_LOG_WARNING ("Invalid signature on /deposit-confirmation request!\n"); { @@ -261,7 +261,7 @@ TALER_AUDITOR_deposit_confirmation (struct TALER_AUDITOR_Handle *auditor, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_CoinSpendSignatureP *exchange_sig, + const struct TALER_ExchangeSignatureP *exchange_sig, const struct TALER_MasterPublicKeyP *master_pub, struct GNUNET_TIME_Absolute ep_start, struct GNUNET_TIME_Absolute ep_expire, diff --git a/src/auditor-lib/testing_auditor_api_cmd_deposit_confirmation.c b/src/auditor-lib/testing_auditor_api_cmd_deposit_confirmation.c new file mode 100644 index 000000000..3509fec52 --- /dev/null +++ b/src/auditor-lib/testing_auditor_api_cmd_deposit_confirmation.c @@ -0,0 +1,374 @@ +/* + 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 auditor-lib/testing_auditor_api_cmd_deposit_confirmation.c + * @brief command for testing /deposit_confirmation. + * @author Christian Grothoff + */ + +#include "platform.h" +#include "taler_json_lib.h" +#include <gnunet/gnunet_curl_lib.h> +#include "taler_auditor_service.h" +#include "taler_testing_lib.h" +#include "taler_signatures.h" +#include "backoff.h" + + +/** + * State for a "deposit confirmation" CMD. + */ +struct DepositConfirmationState +{ + + /** + * Reference to any command that is able to provide a deposit. + */ + const char *deposit_reference; + + /** + * Which coin of the @e deposit_reference should we confirm. + */ + unsigned int coin_index; + + /** + * DepositConfirmation handle while operation is running. + */ + struct TALER_AUDITOR_DepositConfirmationHandle *dc; + + /** + * Auditor connection. + */ + struct TALER_AUDITOR_Handle *auditor; + + /** + * Interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * Task scheduled to try later. + */ + struct GNUNET_SCHEDULER_Task *retry_task; + + /** + * How long do we wait until we retry? + */ + struct GNUNET_TIME_Relative backoff; + + /** + * Expected HTTP response code. + */ + unsigned int expected_response_code; + + /** + * Should we retry on (transient) failures? + */ + int do_retry; + +}; + + +/** + * Run the command. + * + * @param cls closure. + * @param cmd the command to execute. + * @param is the interpreter state. + */ +static void +deposit_confirmation_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is); + + +/** + * Task scheduled to re-try #deposit_confirmation_run. + * + * @param cls a `struct DepositConfirmationState` + */ +static void +do_retry (void *cls) +{ + struct DepositConfirmationState *dcs = cls; + + dcs->retry_task = NULL; + deposit_confirmation_run (dcs, + NULL, + dcs->is); +} + + +/** + * Callback to analyze the /deposit-confirmation response, just used + * to check if the response code is acceptable. + * + * @param cls closure. + * @param http_status HTTP response code. + * @param ec taler-specific error code. + * @param obj raw response from the auditor. + */ +static void +deposit_confirmation_cb (void *cls, + unsigned int http_status, + enum TALER_ErrorCode ec, + const json_t *obj) +{ + struct DepositConfirmationState *dcs = cls; + + dcs->dc = NULL; + if (dcs->expected_response_code != http_status) + { + if (GNUNET_YES == dcs->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 deposit confirmation 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) + dcs->backoff = GNUNET_TIME_UNIT_ZERO; + else + dcs->backoff = AUDITOR_LIB_BACKOFF (dcs->backoff); + dcs->retry_task = GNUNET_SCHEDULER_add_delayed (dcs->backoff, + &do_retry, + dcs); + return; + } + } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u to command %s in %s:%u\n", + http_status, + dcs->is->commands[dcs->is->ip].label, + __FILE__, + __LINE__); + json_dumpf (obj, stderr, 0); + TALER_TESTING_interpreter_fail (dcs->is); + return; + } + TALER_TESTING_interpreter_next (dcs->is); +} + + +/** + * Run the command. + * + * @param cls closure. + * @param cmd the command to execute. + * @param is the interpreter state. + */ +static void +deposit_confirmation_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct DepositConfirmationState *dcs = cls; + const struct TALER_TESTING_Command *deposit_cmd; + struct TALER_TESTING_Command *this_cmd; + struct GNUNET_HashCode h_wire; + struct GNUNET_HashCode h_contract_terms; + struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Absolute refund_deadline; + const struct TALER_Amount *amount_without_fee; + const struct TALER_CoinSpendPublicKeyP *coin_pub; + const struct TALER_MerchantPublicKeyP *merchant_pub; + const struct TALER_ExchangePublicKeyP *exchange_pub; + const struct TALER_ExchangeSignatureP *exchange_sig; + const struct TALER_MasterPublicKeyP *master_pub; + struct GNUNET_TIME_Absolute ep_start; + struct GNUNET_TIME_Absolute ep_expire; + struct GNUNET_TIME_Absolute ep_end; + const struct TALER_MasterSignatureP *master_sig; + const json_t *wire_details; + const json_t *contract_terms; + + dcs->is = is; + this_cmd = &is->commands[is->ip]; // use this_cmd->label for logging! + GNUNET_assert (NULL != dcs->deposit_reference); + deposit_cmd + = TALER_TESTING_interpreter_lookup_command (is, + dcs->deposit_reference); + if (NULL == deposit_cmd) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + + + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_exchange_pub (deposit_cmd, + dcs->coin_index, + &exchange_pub)); + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_exchange_sig (deposit_cmd, + dcs->coin_index, + &exchange_sig)); + +#if 0 + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_contract_terms (deposit_cmd, + dcs->coin_index, + &contract_terms)); + TALER_JSON_hash (contract_terms, + &h_contract_terms); +#endif + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_wire_details (deposit_cmd, + dcs->coin_index, + &wire_details)); + TALER_JSON_hash (wire_details, + &h_wire); + +#if 0 + // FIXME: extract from deposit trait! + /* Fixme: do prefer "interpreter fail" over assertions, + * as the former takes care of shutting down processes, too */ + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_coin_priv (deposit_cmd, + ds->coin_index, + &coin_priv)); +#endif + + dcs->dc = TALER_AUDITOR_deposit_confirmation + (dcs->auditor, + &h_wire, + &h_contract_terms, + timestamp, + refund_deadline, + amount_without_fee, + coin_pub, + merchant_pub, + exchange_pub, + exchange_sig, + master_pub, + ep_start, + ep_expire, + ep_end, + master_sig, + &deposit_confirmation_cb, + dcs); + + if (NULL == dcs->dc) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + return; +} + + +/** + * Free the state of a "deposit_confirmation" CMD, and possibly cancel a + * pending operation thereof. + * + * @param cls closure, a `struct DepositConfirmationState` + * @param cmd the command which is being cleaned up. + */ +static void +deposit_confirmation_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct DepositConfirmationState *dcs = cls; + + if (NULL != dcs->dc) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command %u (%s) did not complete\n", + dcs->is->ip, + cmd->label); + TALER_AUDITOR_deposit_confirmation_cancel (dcs->dc); + dcs->dc = NULL; + } + if (NULL != dcs->retry_task) + { + GNUNET_SCHEDULER_cancel (dcs->retry_task); + dcs->retry_task = NULL; + } + GNUNET_free (dcs); +} + + +/** + * Create a "deposit-confirmation" command. + * + * @param label command label. + * @param auditor auditor connection. + * @param deposit_reference reference to any operation that can + * provide a coin. + * @param coin_index if @a deposit_reference offers an array of + * coins, this parameter selects which one in that array. + * This value is currently ignored, as only one-coin + * deposits are implemented. + * @param expected_response_code expected HTTP response code. + * + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_deposit_confirmation + (const char *label, + struct TALER_AUDITOR_Handle *auditor, + const char *deposit_reference, + unsigned int coin_index, + unsigned int expected_response_code) +{ + struct TALER_TESTING_Command cmd = {0}; /* need explicit zeroing..*/ + struct DepositConfirmationState *dcs; + + dcs = GNUNET_new (struct DepositConfirmationState); + dcs->auditor = auditor; + dcs->deposit_reference = deposit_reference; + dcs->coin_index = coin_index; + dcs->expected_response_code = expected_response_code; + + cmd.cls = dcs; + cmd.label = label; + cmd.run = &deposit_confirmation_run; + cmd.cleanup = &deposit_confirmation_cleanup; + + return cmd; +} + + +/** + * Modify a deposit confirmation command to enable retries when we get + * transient errors from the auditor. + * + * @param cmd a deposit confirmation command + * @return the command with retries enabled + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_deposit_confirmation_with_retry (struct TALER_TESTING_Command cmd) +{ + struct DepositConfirmationState *dcs; + + GNUNET_assert (&deposit_confirmation_run == cmd.run); + dcs = cmd.cls; + dcs->do_retry = GNUNET_YES; + return cmd; +} + + +/* end of testing_auditor_api_cmd_deposit_confirmation.c */ diff --git a/src/auditor-lib/testing_auditor_api_cmd_exec_auditor.c b/src/auditor-lib/testing_auditor_api_cmd_exec_auditor.c index 37d51b781..273612497 100644 --- a/src/auditor-lib/testing_auditor_api_cmd_exec_auditor.c +++ b/src/auditor-lib/testing_auditor_api_cmd_exec_auditor.c @@ -137,11 +137,10 @@ auditor_traits (void *cls, /** - * Make the "auditor" CMD. + * Make the "exec-auditor" CMD. * * @param label command label. * @param config_filename configuration filename. - * * @return the command. */ struct TALER_TESTING_Command diff --git a/src/auditor-lib/testing_auditor_api_cmd_exec_wire_auditor.c b/src/auditor-lib/testing_auditor_api_cmd_exec_wire_auditor.c index 3f7b2ee31..c32130397 100644 --- a/src/auditor-lib/testing_auditor_api_cmd_exec_wire_auditor.c +++ b/src/auditor-lib/testing_auditor_api_cmd_exec_wire_auditor.c @@ -137,11 +137,10 @@ wire_auditor_traits (void *cls, /** - * Make the "wire-auditor" CMD. + * Make the "exec wire-auditor" CMD. * * @param label command label. * @param config_filename configuration filename. - * * @return the command. */ struct TALER_TESTING_Command |