From c3243aa39f924921e8bf52fe6290e4d738d6a20e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 3 Feb 2023 14:06:17 +0100 Subject: [PATCH] implement testing_api_cmd_check_aml_decision --- src/include/taler_exchange_service.h | 16 +- src/include/taler_testing_lib.h | 2 + src/lib/exchange_api_lookup_aml_decision.c | 4 + src/testing/Makefile.am | 1 + .../testing_api_cmd_check_aml_decision.c | 141 +++++++++++++----- src/testing/testing_api_cmd_set_officer.c | 2 +- .../testing_api_cmd_take_aml_decision.c | 68 +++++++-- 7 files changed, 175 insertions(+), 59 deletions(-) diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index 7b301aec7..2d57b6530 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -4373,7 +4373,7 @@ typedef void /** - * @brief Handle for a POST /aml/$OFFICER_PUB/decisions request. + * @brief Handle for a POST /aml/$OFFICER_PUB/decisions/$STATUS request. */ struct TALER_EXCHANGE_LookupAmlDecisions; @@ -4423,6 +4423,16 @@ struct TALER_EXCHANGE_AmlDecisionDetail */ struct GNUNET_TIME_Timestamp decision_time; + /** + * New threshold set by this decision. + */ + struct TALER_Amount new_threshold; + + /** + * Who made the decision? + */ + struct TALER_AmlOfficerPublicKeyP decider_pub; + /** * Justification given for the decision. */ @@ -4481,7 +4491,7 @@ struct TALER_EXCHANGE_AmlDecisionResponse { /** - * Array of AML decision summaries returned by the exchange. + * Array of AML decision details returned by the exchange. */ const struct TALER_EXCHANGE_AmlDecisionDetail *aml_history; @@ -4520,7 +4530,7 @@ typedef void /** - * @brief Handle for a POST /aml/$OFFICER_PUB/decisions request. + * @brief Handle for a POST /aml/$OFFICER_PUB/decision/$H_PAYTO request. */ struct TALER_EXCHANGE_LookupAmlDecision; diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h index a54e05e53..940233232 100644 --- a/src/include/taler_testing_lib.h +++ b/src/include/taler_testing_lib.h @@ -2933,6 +2933,8 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits, op (officer_pub, const struct TALER_AmlOfficerPublicKeyP) \ op (officer_priv, const struct TALER_AmlOfficerPrivateKeyP) \ op (officer_name, const char *) \ + op (aml_decision, enum TALER_AmlDecisionState) \ + op (aml_justification, const char *) \ op (purse_priv, const struct TALER_PurseContractPrivateKeyP) \ op (purse_pub, const struct TALER_PurseContractPublicKeyP) \ op (merge_priv, const struct TALER_PurseMergePrivateKeyP) \ diff --git a/src/lib/exchange_api_lookup_aml_decision.c b/src/lib/exchange_api_lookup_aml_decision.c index 31c772a56..409a35c08 100644 --- a/src/lib/exchange_api_lookup_aml_decision.c +++ b/src/lib/exchange_api_lookup_aml_decision.c @@ -86,8 +86,12 @@ parse_aml_history (const json_t *aml_history, &aml->decision_time), GNUNET_JSON_spec_string ("justification", &aml->justification), + TALER_JSON_spec_amount_any ("new_threshold", + &aml->new_threshold), GNUNET_JSON_spec_uint32 ("new_state", &state32), + GNUNET_JSON_spec_fixed_auto ("decider_pub", + &aml->decider_pub), GNUNET_JSON_spec_end () }; diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am index f92de42dd..92997f26f 100644 --- a/src/testing/Makefile.am +++ b/src/testing/Makefile.am @@ -55,6 +55,7 @@ libtalertesting_la_SOURCES = \ testing_api_cmd_batch_deposit.c \ testing_api_cmd_batch_withdraw.c \ testing_api_cmd_change_auth.c \ + testing_api_cmd_check_aml_decision.c \ testing_api_cmd_check_keys.c \ testing_api_cmd_common.c \ testing_api_cmd_contract_get.c \ diff --git a/src/testing/testing_api_cmd_check_aml_decision.c b/src/testing/testing_api_cmd_check_aml_decision.c index 17e233c73..89939a41e 100644 --- a/src/testing/testing_api_cmd_check_aml_decision.c +++ b/src/testing/testing_api_cmd_check_aml_decision.c @@ -36,9 +36,9 @@ struct AmlCheckState { /** - * Auditor enable handle while operation is running. + * Handle while operation is running. */ - struct TALER_EXCHANGE_ManagementAuditorEnableHandle *dh; + struct TALER_EXCHANGE_LookupAmlDecision *dh; /** * Our interpreter. @@ -46,57 +46,106 @@ struct AmlCheckState struct TALER_TESTING_Interpreter *is; /** - * Reference to command to previous set officer - * to update, or NULL. + * Reference to command to previous set officer. */ - const char *ref_cmd; + const char *ref_officer; /** - * Name to use for the officer. + * Reference to command to the previous set AML status operation. */ - const char *name; + const char *ref_operation; /** - * Is the officer supposed to be enabled? + * Expected HTTP status. */ - bool is_active; - - /** - * Is access supposed to be read-only? - */ - bool read_only; + unsigned int expected_http_status; }; /** - * Callback to analyze the /management/XXX response, just used to check + * Callback to analyze the /aml/$OFFICER_PUB/$decision/$H_PAYTO response, just used to check * if the response code is acceptable. * * @param cls closure. - * @param hr HTTP response details + * @param adr response details */ static void check_aml_decision_cb (void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr) + const struct TALER_EXCHANGE_AmlDecisionResponse *adr) { struct AmlCheckState *ds = cls; ds->dh = NULL; - if (MHD_HTTP_NO_CONTENT != hr->response_code) + if (ds->expected_http_status != adr->hr.http_status) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unexpected response code %u to command %s in %s:%u\n", - hr->http_status, + adr->hr.http_status, ds->is->commands[ds->is->ip].label, __FILE__, __LINE__); - json_dumpf (hr->reply, + json_dumpf (adr->hr.reply, stderr, 0); TALER_TESTING_interpreter_fail (ds->is); return; } + if (MHD_HTTP_OK == adr->hr.http_status) + { + const struct TALER_TESTING_Command *ref; + const char **justification; + enum TALER_AmlDecisionState *new_state; + const struct TALER_Amount *amount; + const struct TALER_EXCHANGE_AmlDecisionDetail *oldest = NULL; + + ref = TALER_TESTING_interpreter_lookup_command (ds->is, + ds->ref_operation); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ds->is); + return; + } + // FIXME: check returned details... + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_aml_justification (ref, + &justification)); + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_aml_decision (ref, + &new_state)); + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_amount (ref, + &amount)); + for (unsigned int i = 1; idetails.success.aml_history_length; i++) + { + const struct TALER_EXCHANGE_AmlDecisionDetail *aml_history + = &adr->details.success.aml_history[i]; + + if ( (NULL == oldest) || + (0 != + TALER_amount_cmp (amount, + &oldest->new_threshold)) || + (GNUNET_TIME_timestamp_cmp (oldest->decision_time, + >, + aml_history->decision_time)) ) + oldest = aml_history; + } + if (NULL == oldest) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ds->is); + return; + } + if ( (oldest->new_state != *new_state) || + (0 != strcmp (oldest->justification, + *justification) ) ) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ds->is); + return; + } + } TALER_TESTING_interpreter_next (ds->is); } @@ -114,25 +163,40 @@ check_aml_decision_run (void *cls, struct TALER_TESTING_Interpreter *is) { struct AmlCheckState *ds = cls; - struct GNUNET_TIME_Timestamp now; - struct TALER_MasterSignatureP master_sig; + const struct TALER_PaytoHashP *h_payto; + const struct TALER_AmlOfficerPrivateKeyP *officer_priv; + const struct TALER_TESTING_Command *ref; (void) cmd; - now = GNUNET_TIME_timestamp_get (); ds->is = is; - TALER_exchange_offline_check_aml_decision_sign (&is->auditor_pub, - is->auditor_url, - now, - &is->master_priv, - &master_sig); - ds->dh = TALER_EXCHANGE_management_enable_auditor ( + ref = TALER_TESTING_interpreter_lookup_command (is, + ds->ref_operation); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_h_payto (ref, + &h_payto)); + ref = TALER_TESTING_interpreter_lookup_command (is, + ds->ref_officer); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_officer_priv (ref, + &officer_priv)); + ds->dh = TALER_EXCHANGE_lookup_aml_decision ( is->ctx, is->exchange_url, - &is->auditor_pub, - is->auditor_url, - "test-case auditor", /* human-readable auditor name */ - now, - &master_sig, + h_payto, + officer_priv, + true, /* history */ &check_aml_decision_cb, ds); if (NULL == ds->dh) @@ -163,7 +227,7 @@ check_aml_decision_cleanup (void *cls, "Command %u (%s) did not complete\n", ds->is->ip, cmd->label); - TALER_EXCHANGE_management_enable_auditor_cancel (ds->dh); + TALER_EXCHANGE_lookup_aml_decision_cancel (ds->dh); ds->dh = NULL; } GNUNET_free (ds); @@ -180,10 +244,9 @@ TALER_TESTING_cmd_check_aml_decision ( struct AmlCheckState *ds; ds = GNUNET_new (struct AmlCheckState); - ds->ref_cmd = ref_cmd; - ds->name = name; - ds->is_active = is_active; - ds->read_only = read_only; + ds->ref_officer = ref_officer; + ds->ref_operation = ref_operation; + ds->expected_http_status = expected_http_status; { struct TALER_TESTING_Command cmd = { .cls = ds, diff --git a/src/testing/testing_api_cmd_set_officer.c b/src/testing/testing_api_cmd_set_officer.c index a0170257a..0e6de262f 100644 --- a/src/testing/testing_api_cmd_set_officer.c +++ b/src/testing/testing_api_cmd_set_officer.c @@ -213,7 +213,7 @@ set_officer_cleanup (void *cls, /** - * Offer internal data to a "set officer" CMD state to other + * Offer internal data of a "set officer" CMD state to other * commands. * * @param cls closure diff --git a/src/testing/testing_api_cmd_take_aml_decision.c b/src/testing/testing_api_cmd_take_aml_decision.c index 2fc8a664f..0992945d6 100644 --- a/src/testing/testing_api_cmd_take_aml_decision.c +++ b/src/testing/testing_api_cmd_take_aml_decision.c @@ -57,6 +57,11 @@ struct AmlDecisionState */ const char *account_ref_cmd; + /** + * Payto hash of the account we are manipulating the AML settings for. + */ + struct TALER_PaytoHashP h_payto; + /** * New AML state to use. */ @@ -70,7 +75,7 @@ struct AmlDecisionState /** * Threshold transaction amount. */ - const char *new_threshold; + struct TALER_Amount new_threshold; /** * Expected response code. @@ -125,22 +130,11 @@ take_aml_decision_run (void *cls, { struct AmlDecisionState *ds = cls; struct GNUNET_TIME_Timestamp now; - struct TALER_Amount threshold; const struct TALER_PaytoHashP *h_payto; const struct TALER_AmlOfficerPrivateKeyP *officer_priv; const struct TALER_TESTING_Command *ref; (void) cmd; - if (GNUNET_OK != - TALER_string_to_amount (ds->new_threshold, - &threshold)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse amount `%s' at %s\n", - ds->new_threshold, - cmd->label); - GNUNET_assert (0); - } now = GNUNET_TIME_timestamp_get (); ds->is = is; ref = TALER_TESTING_interpreter_lookup_command (is, @@ -165,13 +159,13 @@ take_aml_decision_run (void *cls, GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_officer_priv (ref, &officer_priv)); - + ds->h_payto = *h_payto; ds->dh = TALER_EXCHANGE_add_aml_decision ( is->ctx, is->exchange_url, ds->justification, now, - &threshold, + &ds->new_threshold, h_payto, ds->new_state, officer_priv, @@ -212,6 +206,38 @@ take_aml_decision_cleanup (void *cls, } +/** + * Offer internal data of a "AML decision" CMD state to other + * commands. + * + * @param cls closure + * @param[out] ret result (could be anything) + * @param trait name of the trait + * @param index index number of the object to offer. + * @return #GNUNET_OK on success + */ +static enum GNUNET_GenericReturnValue +take_aml_decision_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct AmlDecisionState *ws = cls; + struct TALER_TESTING_Trait traits[] = { + TALER_TESTING_make_trait_h_payto (&ws->h_payto), + TALER_TESTING_make_trait_aml_justification (&ws->justification), + TALER_TESTING_make_trait_aml_decision (&ws->new_state), + TALER_TESTING_make_trait_amount (&ws->new_threshold), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); +} + + struct TALER_TESTING_Command TALER_TESTING_cmd_take_aml_decision ( const char *label, @@ -227,7 +253,16 @@ TALER_TESTING_cmd_take_aml_decision ( ds = GNUNET_new (struct AmlDecisionState); ds->officer_ref_cmd = ref_officer; ds->account_ref_cmd = ref_operation; - ds->new_threshold = new_threshold; + if (GNUNET_OK != + TALER_string_to_amount (new_threshold, + &ds->new_threshold)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to parse amount `%s' at %s\n", + new_threshold, + label); + GNUNET_assert (0); + } ds->new_state = new_state; ds->justification = justification; ds->expected_response = expected_response; @@ -236,7 +271,8 @@ TALER_TESTING_cmd_take_aml_decision ( .cls = ds, .label = label, .run = &take_aml_decision_run, - .cleanup = &take_aml_decision_cleanup + .cleanup = &take_aml_decision_cleanup, + .traits = &take_aml_decision_traits }; return cmd;