From e18e0809b7657688c8301632f3e803686610fa6f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 9 Nov 2023 13:29:40 +0100 Subject: towards testing coin history API properly --- src/include/taler_testing_lib.h | 14 +-- src/testing/testing_api_cmd_coin_history.c | 161 +++++++++++++++++++------- src/testing/testing_api_cmd_common.c | 149 ------------------------ src/testing/testing_api_cmd_deposit.c | 36 ++++-- src/testing/testing_api_cmd_reserve_history.c | 160 ++++++++++++++++++++++++- 5 files changed, 304 insertions(+), 216 deletions(-) (limited to 'src') diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h index 136967187..2d002abe2 100644 --- a/src/include/taler_testing_lib.h +++ b/src/include/taler_testing_lib.h @@ -591,19 +591,6 @@ TALER_TESTING_parse_coin_reference ( unsigned int *idx); -/** - * Compare @a h1 and @a h2. - * - * @param h1 a history entry - * @param h2 a history entry - * @return 0 if @a h1 and @a h2 are equal - */ -int -TALER_TESTING_history_entry_cmp ( - const struct TALER_EXCHANGE_ReserveHistoryEntry *h1, - const struct TALER_EXCHANGE_ReserveHistoryEntry *h2); - - /* ************** Specific interpreter commands ************ */ @@ -2721,6 +2708,7 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits, op (age_commitment_proof, const struct TALER_AgeCommitmentProof) \ op (h_age_commitment, const struct TALER_AgeCommitmentHash) \ op (reserve_history, const struct TALER_EXCHANGE_ReserveHistoryEntry) \ + op (coin_history, const struct TALER_EXCHANGE_CoinHistoryEntry) \ op (planchet_secrets, const struct TALER_PlanchetMasterSecretP) \ op (exchange_wd_value, const struct TALER_ExchangeWithdrawValues) \ op (coin_priv, const struct TALER_CoinSpendPrivateKeyP) \ diff --git a/src/testing/testing_api_cmd_coin_history.c b/src/testing/testing_api_cmd_coin_history.c index 2de125932..d4b95fb48 100644 --- a/src/testing/testing_api_cmd_coin_history.c +++ b/src/testing/testing_api_cmd_coin_history.c @@ -104,7 +104,85 @@ struct AnalysisContext }; -#if 0 +/** + * Compare @a h1 and @a h2. + * + * @param h1 a history entry + * @param h2 a history entry + * @return 0 if @a h1 and @a h2 are equal + */ +static int +history_entry_cmp ( + const struct TALER_EXCHANGE_CoinHistoryEntry *h1, + const struct TALER_EXCHANGE_CoinHistoryEntry *h2) +{ + if (h1->type != h2->type) + return 1; + if (0 != TALER_amount_cmp (&h1->amount, + &h2->amount)) + return 1; + switch (h1->type) + { + case TALER_EXCHANGE_CTT_NONE: + GNUNET_break (0); + break; + case TALER_EXCHANGE_CTT_DEPOSIT: + if (0 != GNUNET_memcmp (&h1->details.deposit.sig, + &h2->details.deposit.sig)) + return 1; + return 0; + case TALER_EXCHANGE_CTT_MELT: + if (0 != GNUNET_memcmp (&h1->details.melt.sig, + &h2->details.melt.sig)) + return 1; + return 0; + case TALER_EXCHANGE_CTT_REFUND: + if (0 != GNUNET_memcmp (&h1->details.refund.sig, + &h2->details.refund.sig)) + return 1; + return 0; + case TALER_EXCHANGE_CTT_RECOUP: + if (0 != GNUNET_memcmp (&h1->details.recoup.coin_sig, + &h2->details.recoup.coin_sig)) + return 1; + if (0 != GNUNET_memcmp (&h1->details.recoup.exchange_sig, + &h2->details.recoup.exchange_sig)) + return 1; + return 0; + case TALER_EXCHANGE_CTT_RECOUP_REFRESH: + if (0 != GNUNET_memcmp (&h1->details.recoup_refresh.coin_sig, + &h2->details.recoup_refresh.coin_sig)) + return 1; + if (0 != GNUNET_memcmp (&h1->details.recoup_refresh.exchange_sig, + &h2->details.recoup_refresh.exchange_sig)) + return 1; + return 0; + case TALER_EXCHANGE_CTT_OLD_COIN_RECOUP: + if (0 != GNUNET_memcmp (&h1->details.old_coin_recoup.exchange_sig, + &h2->details.old_coin_recoup.exchange_sig)) + return 1; + return 0; + case TALER_EXCHANGE_CTT_PURSE_DEPOSIT: + if (0 != GNUNET_memcmp (&h1->details.purse_deposit.coin_sig, + &h2->details.purse_deposit.coin_sig)) + return 1; + return 0; + case TALER_EXCHANGE_CTT_PURSE_REFUND: + if (0 != GNUNET_memcmp (&h1->details.purse_refund.exchange_sig, + &h2->details.purse_refund.exchange_sig)) + return 1; + return 0; + case TALER_EXCHANGE_CTT_RESERVE_OPEN_DEPOSIT: + if (0 != GNUNET_memcmp (&h1->details.reserve_open_deposit.coin_sig, + &h2->details.reserve_open_deposit.coin_sig)) + return 1; + return 0; + } + GNUNET_assert (0); + return -1; +} + + /** * Check if @a cmd changed the coin, if so, find the * entry in our history and set the respective index in found @@ -156,64 +234,59 @@ analyze_command (void *cls, return; } + for (unsigned int j = 0; true; j++) { - const struct TALER_CoinPublicKeyP *rp; + const struct TALER_CoinSpendPublicKeyP *rp; + const struct TALER_EXCHANGE_CoinHistoryEntry *he; + bool matched = false; if (GNUNET_OK != TALER_TESTING_get_trait_coin_pub (cmd, + j, &rp)) - return; /* command does nothing for coins */ + break; /* command does nothing for coins */ if (0 != GNUNET_memcmp (rp, coin_pub)) - return; /* command affects some _other_ coin */ - for (unsigned int j = 0; true; j++) + continue; /* command affects some _other_ coin */ + if (GNUNET_OK != + TALER_TESTING_get_trait_coin_history (cmd, + j, + &he)) { - const struct TALER_EXCHANGE_CoinHistoryEntry *he; - bool matched = false; - - if (GNUNET_OK != - TALER_TESTING_get_trait_coin_history (cmd, - j, - &he)) - { - /* NOTE: only for debugging... */ - if (0 == j) - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Command `%s' has the coin_pub, but lacks coin history trait\n", - cmd->label); - return; /* command does nothing for coins */ - } - for (unsigned int i = 0; ilabel); + return; /* command does nothing for coins */ + } + for (unsigned int i = 0; ilabel, - j); - ac->failure = true; - return; + found[i] = true; + matched = true; + break; } } + if (! matched) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Command `%s' coin history entry #%u not found\n", + cmd->label, + j); + ac->failure = true; + return; + } } } -#endif - - /** * Check that the coin balance and HTTP response code are * both acceptable. @@ -325,7 +398,6 @@ coin_history_cb (void *cls, return; } (void) ac; -#if FIXME TALER_TESTING_iterate (is, true, &analyze_command, @@ -338,6 +410,7 @@ coin_history_cb (void *cls, TALER_TESTING_interpreter_fail (ss->is); return; } +#if FIXME for (unsigned int i = 0; idetails.ok.history_len; i++) { if (found[i]) diff --git a/src/testing/testing_api_cmd_common.c b/src/testing/testing_api_cmd_common.c index 9ed0f16b6..2d828a2b0 100644 --- a/src/testing/testing_api_cmd_common.c +++ b/src/testing/testing_api_cmd_common.c @@ -25,155 +25,6 @@ #include "taler_testing_lib.h" -int -TALER_TESTING_history_entry_cmp ( - const struct TALER_EXCHANGE_ReserveHistoryEntry *h1, - const struct TALER_EXCHANGE_ReserveHistoryEntry *h2) -{ - if (h1->type != h2->type) - return 1; - switch (h1->type) - { - case TALER_EXCHANGE_RTT_CREDIT: - if ( (0 == - TALER_amount_cmp (&h1->amount, - &h2->amount)) && - (0 == strcasecmp (h1->details.in_details.sender_url, - h2->details.in_details.sender_url)) && - (h1->details.in_details.wire_reference == - h2->details.in_details.wire_reference) && - (GNUNET_TIME_timestamp_cmp (h1->details.in_details.timestamp, - ==, - h2->details.in_details.timestamp)) ) - return 0; - return 1; - case TALER_EXCHANGE_RTT_WITHDRAWAL: - if ( (0 == - TALER_amount_cmp (&h1->amount, - &h2->amount)) && - (0 == - TALER_amount_cmp (&h1->details.withdraw.fee, - &h2->details.withdraw.fee)) ) - /* testing_api_cmd_withdraw doesn't set the out_authorization_sig, - so we cannot test for it here. but if the amount matches, - that should be good enough. */ - return 0; - return 1; - case TALER_EXCHANGE_RTT_AGEWITHDRAWAL: - /* testing_api_cmd_age_withdraw doesn't set the out_authorization_sig, - so we cannot test for it here. but if the amount matches, - that should be good enough. */ - if ( (0 == - TALER_amount_cmp (&h1->amount, - &h2->amount)) && - (0 == - TALER_amount_cmp (&h1->details.age_withdraw.fee, - &h2->details.age_withdraw.fee)) && - (h1->details.age_withdraw.max_age == - h2->details.age_withdraw.max_age)) - return 0; - return 1; - case TALER_EXCHANGE_RTT_RECOUP: - /* exchange_sig, exchange_pub and timestamp are NOT available - from the original recoup response, hence here NOT check(able/ed) */ - if ( (0 == - TALER_amount_cmp (&h1->amount, - &h2->amount)) && - (0 == - GNUNET_memcmp (&h1->details.recoup_details.coin_pub, - &h2->details.recoup_details.coin_pub)) ) - return 0; - return 1; - case TALER_EXCHANGE_RTT_CLOSING: - /* testing_api_cmd_exec_closer doesn't set the - receiver_account_details, exchange_sig, exchange_pub or wtid or timestamp - so we cannot test for it here. but if the amount matches, - that should be good enough. */ - if ( (0 == - TALER_amount_cmp (&h1->amount, - &h2->amount)) && - (0 == - TALER_amount_cmp (&h1->details.close_details.fee, - &h2->details.close_details.fee)) ) - return 0; - return 1; - case TALER_EXCHANGE_RTT_MERGE: - if ( (0 == - TALER_amount_cmp (&h1->amount, - &h2->amount)) && - (0 == - TALER_amount_cmp (&h1->details.merge_details.purse_fee, - &h2->details.merge_details.purse_fee)) && - (GNUNET_TIME_timestamp_cmp (h1->details.merge_details.merge_timestamp, - ==, - h2->details.merge_details.merge_timestamp)) - && - (GNUNET_TIME_timestamp_cmp (h1->details.merge_details.purse_expiration, - ==, - h2->details.merge_details.purse_expiration)) - && - (0 == - GNUNET_memcmp (&h1->details.merge_details.merge_pub, - &h2->details.merge_details.merge_pub)) && - (0 == - GNUNET_memcmp (&h1->details.merge_details.h_contract_terms, - &h2->details.merge_details.h_contract_terms)) && - (0 == - GNUNET_memcmp (&h1->details.merge_details.purse_pub, - &h2->details.merge_details.purse_pub)) && - (0 == - GNUNET_memcmp (&h1->details.merge_details.reserve_sig, - &h2->details.merge_details.reserve_sig)) && - (h1->details.merge_details.min_age == - h2->details.merge_details.min_age) && - (h1->details.merge_details.flags == - h2->details.merge_details.flags) ) - return 0; - return 1; - case TALER_EXCHANGE_RTT_OPEN: - if ( (0 == - TALER_amount_cmp (&h1->amount, - &h2->amount)) && - (GNUNET_TIME_timestamp_cmp ( - h1->details.open_request.request_timestamp, - ==, - h2->details.open_request.request_timestamp)) && - (GNUNET_TIME_timestamp_cmp ( - h1->details.open_request.reserve_expiration, - ==, - h2->details.open_request.reserve_expiration)) && - (h1->details.open_request.purse_limit == - h2->details.open_request.purse_limit) && - (0 == - TALER_amount_cmp (&h1->details.open_request.reserve_payment, - &h2->details.open_request.reserve_payment)) && - (0 == - GNUNET_memcmp (&h1->details.open_request.reserve_sig, - &h2->details.open_request.reserve_sig)) ) - return 0; - return 1; - case TALER_EXCHANGE_RTT_CLOSE: - if ( (0 == - TALER_amount_cmp (&h1->amount, - &h2->amount)) && - (GNUNET_TIME_timestamp_cmp ( - h1->details.close_request.request_timestamp, - ==, - h2->details.close_request.request_timestamp)) && - (0 == - GNUNET_memcmp (&h1->details.close_request.target_account_h_payto, - &h2->details.close_request.target_account_h_payto)) && - (0 == - GNUNET_memcmp (&h1->details.close_request.reserve_sig, - &h2->details.close_request.reserve_sig)) ) - return 0; - return 1; - } - GNUNET_assert (0); - return 1; -} - - enum GNUNET_GenericReturnValue TALER_TESTING_parse_coin_reference ( const char *coin_reference, diff --git a/src/testing/testing_api_cmd_deposit.c b/src/testing/testing_api_cmd_deposit.c index a80b44868..0b908cc66 100644 --- a/src/testing/testing_api_cmd_deposit.c +++ b/src/testing/testing_api_cmd_deposit.c @@ -136,10 +136,16 @@ struct DepositState unsigned int do_retry; /** - * Set to #GNUNET_YES if the /deposit succeeded + * Set to true if the /deposit succeeded * and we now can provide the resulting traits. */ - int deposit_succeeded; + bool deposit_succeeded; + + /** + * Expected entry in the coin history created by this + * operation. + */ + struct TALER_EXCHANGE_CoinHistoryEntry che; /** * When did the exchange receive the deposit? @@ -170,7 +176,7 @@ struct DepositState * When we're referencing another deposit operation, * this will only be set after the command has been started. */ - int command_initialized; + bool command_initialized; /** * Reference to fetch the merchant private key from. @@ -263,7 +269,7 @@ deposit_cb (void *cls, } if (MHD_HTTP_OK == dr->hr.http_status) { - ds->deposit_succeeded = GNUNET_YES; + ds->deposit_succeeded = true; ds->exchange_timestamp = dr->details.ok.deposit_timestamp; ds->exchange_pub = *dr->details.ok.exchange_pub; ds->exchange_sig = *dr->details.ok.exchange_sig; @@ -354,7 +360,7 @@ deposit_run (void *cls, ds->wire_deadline = ods->wire_deadline; ds->amount = ods->amount; ds->merchant_priv = ods->merchant_priv; - ds->command_initialized = GNUNET_YES; + ds->command_initialized = true; } else if (NULL != ds->merchant_priv_reference) { @@ -453,6 +459,18 @@ deposit_run (void *cls, ds->refund_deadline, coin_priv, &ds->coin_sig); + ds->che.type = TALER_EXCHANGE_CTT_DEPOSIT; + ds->che.amount = ds->amount; + ds->che.details.deposit.h_wire = h_wire; + ds->che.details.deposit.h_contract_terms = h_contract_terms; + ds->che.details.deposit.no_h_policy = true; + ds->che.details.deposit.no_wallet_data_hash = true; + ds->che.details.deposit.wallet_timestamp = ds->wallet_timestamp; + ds->che.details.deposit.merchant_pub = merchant_pub; + ds->che.details.deposit.refund_deadline = ds->refund_deadline; + ds->che.details.deposit.sig = ds->coin_sig; + ds->che.details.deposit.no_hac = true; + ds->che.details.deposit.deposit_fee = denom_pub->fees.deposit; } GNUNET_assert (NULL == ds->dh); { @@ -553,7 +571,7 @@ deposit_traits (void *cls, const struct TALER_AgeCommitmentProof *age_commitment_proof; const struct TALER_AgeCommitmentHash *h_age_commitment; - if (GNUNET_YES != ds->command_initialized) + if (! ds->command_initialized) { /* No access to traits yet. */ GNUNET_break (0); @@ -596,6 +614,8 @@ deposit_traits (void *cls, TALER_TESTING_make_trait_exchange_sig (0, &ds->exchange_sig), /* These traits are always available */ + TALER_TESTING_make_trait_coin_history (0, + &ds->che), TALER_TESTING_make_trait_coin_priv (0, coin_spent_priv), TALER_TESTING_make_trait_coin_sig (0, @@ -679,7 +699,7 @@ TALER_TESTING_cmd_deposit ( TALER_string_to_amount (amount, &ds->amount)); ds->expected_response_code = expected_response_code; - ds->command_initialized = GNUNET_YES; + ds->command_initialized = true; { struct TALER_TESTING_Command cmd = { .cls = ds, @@ -744,7 +764,7 @@ TALER_TESTING_cmd_deposit_with_ref ( TALER_string_to_amount (amount, &ds->amount)); ds->expected_response_code = expected_response_code; - ds->command_initialized = GNUNET_YES; + ds->command_initialized = true; { struct TALER_TESTING_Command cmd = { .cls = ds, diff --git a/src/testing/testing_api_cmd_reserve_history.c b/src/testing/testing_api_cmd_reserve_history.c index 4b08e78e8..ecb236a54 100644 --- a/src/testing/testing_api_cmd_reserve_history.c +++ b/src/testing/testing_api_cmd_reserve_history.c @@ -104,6 +104,162 @@ struct AnalysisContext }; +/** + * Compare @a h1 and @a h2. + * + * @param h1 a history entry + * @param h2 a history entry + * @return 0 if @a h1 and @a h2 are equal + */ +static int +history_entry_cmp ( + const struct TALER_EXCHANGE_ReserveHistoryEntry *h1, + const struct TALER_EXCHANGE_ReserveHistoryEntry *h2) +{ + if (h1->type != h2->type) + return 1; + switch (h1->type) + { + case TALER_EXCHANGE_RTT_CREDIT: + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (0 == strcasecmp (h1->details.in_details.sender_url, + h2->details.in_details.sender_url)) && + (h1->details.in_details.wire_reference == + h2->details.in_details.wire_reference) && + (GNUNET_TIME_timestamp_cmp (h1->details.in_details.timestamp, + ==, + h2->details.in_details.timestamp)) ) + return 0; + return 1; + case TALER_EXCHANGE_RTT_WITHDRAWAL: + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (0 == + TALER_amount_cmp (&h1->details.withdraw.fee, + &h2->details.withdraw.fee)) ) + /* testing_api_cmd_withdraw doesn't set the out_authorization_sig, + so we cannot test for it here. but if the amount matches, + that should be good enough. */ + return 0; + return 1; + case TALER_EXCHANGE_RTT_AGEWITHDRAWAL: + /* testing_api_cmd_age_withdraw doesn't set the out_authorization_sig, + so we cannot test for it here. but if the amount matches, + that should be good enough. */ + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (0 == + TALER_amount_cmp (&h1->details.age_withdraw.fee, + &h2->details.age_withdraw.fee)) && + (h1->details.age_withdraw.max_age == + h2->details.age_withdraw.max_age)) + return 0; + return 1; + case TALER_EXCHANGE_RTT_RECOUP: + /* exchange_sig, exchange_pub and timestamp are NOT available + from the original recoup response, hence here NOT check(able/ed) */ + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (0 == + GNUNET_memcmp (&h1->details.recoup_details.coin_pub, + &h2->details.recoup_details.coin_pub)) ) + return 0; + return 1; + case TALER_EXCHANGE_RTT_CLOSING: + /* testing_api_cmd_exec_closer doesn't set the + receiver_account_details, exchange_sig, exchange_pub or wtid or timestamp + so we cannot test for it here. but if the amount matches, + that should be good enough. */ + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (0 == + TALER_amount_cmp (&h1->details.close_details.fee, + &h2->details.close_details.fee)) ) + return 0; + return 1; + case TALER_EXCHANGE_RTT_MERGE: + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (0 == + TALER_amount_cmp (&h1->details.merge_details.purse_fee, + &h2->details.merge_details.purse_fee)) && + (GNUNET_TIME_timestamp_cmp (h1->details.merge_details.merge_timestamp, + ==, + h2->details.merge_details.merge_timestamp)) + && + (GNUNET_TIME_timestamp_cmp (h1->details.merge_details.purse_expiration, + ==, + h2->details.merge_details.purse_expiration)) + && + (0 == + GNUNET_memcmp (&h1->details.merge_details.merge_pub, + &h2->details.merge_details.merge_pub)) && + (0 == + GNUNET_memcmp (&h1->details.merge_details.h_contract_terms, + &h2->details.merge_details.h_contract_terms)) && + (0 == + GNUNET_memcmp (&h1->details.merge_details.purse_pub, + &h2->details.merge_details.purse_pub)) && + (0 == + GNUNET_memcmp (&h1->details.merge_details.reserve_sig, + &h2->details.merge_details.reserve_sig)) && + (h1->details.merge_details.min_age == + h2->details.merge_details.min_age) && + (h1->details.merge_details.flags == + h2->details.merge_details.flags) ) + return 0; + return 1; + case TALER_EXCHANGE_RTT_OPEN: + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (GNUNET_TIME_timestamp_cmp ( + h1->details.open_request.request_timestamp, + ==, + h2->details.open_request.request_timestamp)) && + (GNUNET_TIME_timestamp_cmp ( + h1->details.open_request.reserve_expiration, + ==, + h2->details.open_request.reserve_expiration)) && + (h1->details.open_request.purse_limit == + h2->details.open_request.purse_limit) && + (0 == + TALER_amount_cmp (&h1->details.open_request.reserve_payment, + &h2->details.open_request.reserve_payment)) && + (0 == + GNUNET_memcmp (&h1->details.open_request.reserve_sig, + &h2->details.open_request.reserve_sig)) ) + return 0; + return 1; + case TALER_EXCHANGE_RTT_CLOSE: + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (GNUNET_TIME_timestamp_cmp ( + h1->details.close_request.request_timestamp, + ==, + h2->details.close_request.request_timestamp)) && + (0 == + GNUNET_memcmp (&h1->details.close_request.target_account_h_payto, + &h2->details.close_request.target_account_h_payto)) && + (0 == + GNUNET_memcmp (&h1->details.close_request.reserve_sig, + &h2->details.close_request.reserve_sig)) ) + return 0; + return 1; + } + GNUNET_assert (0); + return 1; +} + + /** * Check if @a cmd changed the reserve, if so, find the * entry in our history and set the respective index in found @@ -188,8 +344,8 @@ analyze_command (void *cls, if (found[i]) continue; /* already found, skip */ if (0 == - TALER_TESTING_history_entry_cmp (he, - &history[i])) + history_entry_cmp (he, + &history[i])) { found[i] = true; matched = true; -- cgit v1.2.3