diff options
| author | Özgür Kesim <oec-taler@kesim.org> | 2023-07-20 18:13:48 +0200 | 
|---|---|---|
| committer | Özgür Kesim <oec-taler@kesim.org> | 2023-07-20 18:13:48 +0200 | 
| commit | 430bb0624ae60e78c3e9855bd7827cc407471871 (patch) | |
| tree | d35009892e5c07069e112fe36735f4832df32b12 /src/testing | |
| parent | c424cf99abf8caae1106fe778c251aa469e0a308 (diff) | |
[age-withdraw] Added testing commands for age-withdraw and -reveal
Implemented
- TALER_TESTING_cmd_age_withdraw
- TALER_TESTING_cmd_age_withdraw_reveal
Note: No test is using those commands yet.
Diffstat (limited to 'src/testing')
| -rw-r--r-- | src/testing/testing_api_cmd_age_withdraw.c | 671 | ||||
| -rw-r--r-- | src/testing/testing_api_cmd_batch_withdraw.c | 8 | ||||
| -rw-r--r-- | src/testing/testing_api_cmd_common.c | 14 | ||||
| -rw-r--r-- | src/testing/testing_api_loop.c | 3 | 
4 files changed, 647 insertions, 49 deletions
| diff --git a/src/testing/testing_api_cmd_age_withdraw.c b/src/testing/testing_api_cmd_age_withdraw.c index 52efc5f7..edf29297 100644 --- a/src/testing/testing_api_cmd_age_withdraw.c +++ b/src/testing/testing_api_cmd_age_withdraw.c @@ -23,7 +23,9 @@   */  #include "platform.h" +#include "taler_exchange_service.h"  #include "taler_json_lib.h" +#include <gnunet/gnunet_common.h>  #include <microhttpd.h>  #include <gnunet/gnunet_curl_lib.h>  #include "taler_signatures.h" @@ -31,15 +33,26 @@  #include "taler_testing_lib.h"  /* - * The input and state of coin + * The output state of coin   */ -struct CoinState +struct CoinOutputState  { -  struct TALER_RefreshMasterSecretP secret; +  /** +   * The calculated details during "age-withdraw", for the selected coin. +   */    struct TALER_EXCHANGE_AgeWithdrawCoinPrivateDetails details; +  /** +   * The (wanted) value of the coin, MUST be the same as input.denom_pub.value; +   */    struct TALER_Amount amount; + +  /** +   * Reserve history entry that corresponds to this coin. +   * Will be of type #TALER_EXCHANGE_RTT_AGEWITHDRAWAL. +   */ +  struct TALER_EXCHANGE_ReserveHistoryEntry reserve_history;  };  /** @@ -48,7 +61,38 @@ struct CoinState  struct AgeWithdrawState  { -  /* + +  /** +   * Interpreter state (during command) +   */ +  struct TALER_TESTING_Interpreter *is; + +  /** +   * The age-withdraw handle +   */ +  struct TALER_EXCHANGE_AgeWithdrawHandle *handle; + +  /** +   * Exchange base URL.  Only used as offered trait. +   */ +  char *exchange_url; + +  /** +   * URI of the reserve we are withdrawing from. +   */ +  char *reserve_payto_uri; + +  /** +   * Private key of the reserve we are withdrawing from. +   */ +  struct TALER_ReservePrivateKeyP reserve_priv; + +  /** +   * Public key of the reserve we are withdrawing from. +   */ +  struct TALER_ReservePublicKeyP reserve_pub; + +  /**     * Which reserve should we withdraw from?     */    const char *reserve_reference; @@ -59,6 +103,11 @@ struct AgeWithdrawState    unsigned int expected_response_code;    /** +   * Age mask +   */ +  struct TALER_AgeMask mask; + +  /**     * The maximum age we commit to     */    uint8_t max_age; @@ -69,12 +118,336 @@ struct AgeWithdrawState    size_t num_coins;    /** -   * The input for the coins +   * The @e num_coins input that is provided to the +   * `TALER_EXCHANGE_age_withdraw` API. +   * Each contains kappa secrets, from which we will have +   * to disclose kappa-1 in a subsequent age-withdraw-reveal operation.     */ -  struct CoinState *coins; +  struct TALER_EXCHANGE_AgeWithdrawCoinInput *coin_inputs; + +  /** +   * The output state of @e num_coins coins, calculated during the +   * "age-withdraw" operation. +   */ +  struct CoinOutputState *coin_outputs; + +  /** +   * The index returned by the exchange for the "age-withdraw" operation, +   * of the kappa coin candidates that we do not disclose and keep. +   */ +  uint8_t noreveal_index; + +  /** +   * The blinded hashes of the non-revealed (to keep) @e num_coins coins. +   */ +  const struct TALER_BlindedCoinHashP *blinded_coin_hs; + +  /** +   * The hash of the commitment, needed for the reveal step. +   */ +  struct TALER_AgeWithdrawCommitmentHashP h_commitment; + +  /** +   * Set to the KYC requirement payto hash *if* the exchange replied with a +   * request for KYC. +   */ +  struct TALER_PaytoHashP h_payto; + +  /** +   * Set to the KYC requirement row *if* the exchange replied with +   * a request for KYC. +   */ +  uint64_t requirement_row;  }; +/** + * Callback for the "age-withdraw" ooperation;  It checks that the response + * code is expected and store the exchange signature in the state. + * + * @param cls Closure of type `struct AgeWithdrawState *` + * @param awr Repsonse details + */ +static void +age_withdraw_cb ( +  void *cls, +  const struct TALER_EXCHANGE_AgeWithdrawResponse *response) +{ +  struct AgeWithdrawState *aws = cls; +  struct TALER_TESTING_Interpreter *is = aws->is; + +  aws->handle = NULL; +  if (aws->expected_response_code != response->hr.http_status) +  { +    TALER_TESTING_unexpected_status_with_body (is, +                                               response->hr.http_status, +                                               aws->expected_response_code, +                                               response->hr.reply); +    return; +  } + +  switch (response->hr.http_status) +  { +  case MHD_HTTP_OK: +    aws->noreveal_index = response->details.ok.noreveal_index; +    aws->h_commitment = response->details.ok.h_commitment; + +    GNUNET_assert (aws->num_coins == response->details.ok.num_coins); +    for (size_t n = 0; n < aws->num_coins; n++) +    { +      aws->coin_outputs[n].details = response->details.ok.coin_details[n]; +      TALER_age_commitment_proof_deep_copy ( +        &response->details.ok.coin_details[n].age_commitment_proof, +        &aws->coin_outputs[n].details.age_commitment_proof); +    } +    aws->blinded_coin_hs = response->details.ok.blinded_coin_hs; +    break; +  case MHD_HTTP_FORBIDDEN: +  case MHD_HTTP_NOT_FOUND: +  case MHD_HTTP_GONE: +    /* nothing to check */ +    break; +  case MHD_HTTP_CONFLICT: +    /* TODO[oec]: Add this to the response-type and handle it here */ +    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, +                "Age withdraw test command does not YET support status code %u\n", +                response->hr.http_status); +    break; +  case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: +    /* TODO[oec]: Add this to response-type and handle it here  */ +    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, +                "Age withdraw test command does not YET support status code %u\n", +                response->hr.http_status); +    break; +  default: +    /* Unsupported status code (by test harness) */ +    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, +                "Age withdraw test command does not support status code %u\n", +                response->hr.http_status); +    GNUNET_break (0); +    break; +  } + +  /* We are done with this command, pick the next one */ +  TALER_TESTING_interpreter_next (is); +} + + +/** + * Run the command for age-withdraw. + */ +static void +age_withdraw_run ( +  void *cls, +  const struct TALER_TESTING_Command *cmd, +  struct TALER_TESTING_Interpreter *is) +{ +  struct AgeWithdrawState *aws = cls; +  struct TALER_EXCHANGE_Keys *keys = TALER_TESTING_get_keys (is); +  const struct TALER_ReservePrivateKeyP *rp; +  const struct TALER_TESTING_Command *create_reserve; +  const struct TALER_EXCHANGE_DenomPublicKey *dpk; + +  aws->is = is; + +  /* Prepare the reserve related data */ +  create_reserve +    = TALER_TESTING_interpreter_lookup_command ( +        is, +        aws->reserve_reference); + +  if (NULL == create_reserve) +  { +    GNUNET_break (0); +    TALER_TESTING_interpreter_fail (is); +    return; +  } +  if (GNUNET_OK != +      TALER_TESTING_get_trait_reserve_priv (create_reserve, +                                            &rp)) +  { +    GNUNET_break (0); +    TALER_TESTING_interpreter_fail (is); +    return; +  } +  if (NULL == aws->exchange_url) +    aws->exchange_url +      = GNUNET_strdup (TALER_TESTING_get_exchange_url (is)); +  aws->reserve_priv = *rp; +  GNUNET_CRYPTO_eddsa_key_get_public (&aws->reserve_priv.eddsa_priv, +                                      &aws->reserve_pub.eddsa_pub); +  aws->reserve_payto_uri +    = TALER_reserve_make_payto (aws->exchange_url, +                                &aws->reserve_pub); + +  aws->coin_inputs = GNUNET_new_array ( +    aws->num_coins, +    struct TALER_EXCHANGE_AgeWithdrawCoinInput); + +  for (unsigned int i = 0; i<aws->num_coins; i++) +  { +    struct TALER_EXCHANGE_AgeWithdrawCoinInput *input = &aws->coin_inputs[i]; +    struct CoinOutputState *cos = &aws->coin_outputs[i]; + +    /* randomly create the secrets for the kappa coin-candidates */ +    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, +                                &input->secrets, +                                sizeof(input->secrets)); +    /* Find denomination */ +    dpk = TALER_TESTING_find_pk (keys, +                                 &cos->amount, +                                 true); /* _always_ use denominations with age-striction */ +    if (NULL == dpk) +    { +      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                  "Failed to determine denomination key at %s\n", +                  (NULL != cmd) ? cmd->label : "<retried command>"); +      GNUNET_break (0); +      TALER_TESTING_interpreter_fail (is); +      return; +    } +    /* We copy the denomination key, as re-querying /keys +     * would free the old one. */ +    input->denom_pub = TALER_EXCHANGE_copy_denomination_key (dpk); +    cos->reserve_history.type = TALER_EXCHANGE_RTT_AGEWITHDRAWAL; +    GNUNET_assert (0 <= +                   TALER_amount_add (&cos->reserve_history.amount, +                                     &cos->amount, +                                     &input->denom_pub->fees.withdraw)); +    cos->reserve_history.details.withdraw.fee = input->denom_pub->fees.withdraw; +  } + +  /* Execute the age-withdraw protocol */ +  aws->handle = +    TALER_EXCHANGE_age_withdraw ( +      TALER_TESTING_interpreter_get_context (is), +      keys, +      TALER_TESTING_get_exchange_url (is), +      rp, +      aws->num_coins, +      aws->coin_inputs, +      aws->max_age, +      &age_withdraw_cb, +      aws); + +  if (NULL == aws->handle) +  { +    GNUNET_break (0); +    TALER_TESTING_interpreter_fail (is); +    return; +  } +} + + +/** + * Free the state of a "age withdraw" CMD, and possibly cancel a + * pending operation thereof + * + * @param cls Closure of type `struct AgeWithdrawState` + * @param cmd The command beeing freed. + */ +static void +age_withdraw_cleanup ( +  void *cls, +  const struct TALER_TESTING_Command *cmd) +{ +  struct AgeWithdrawState *aws = cls; + +  if (NULL != aws->handle) +  { +    TALER_TESTING_command_incomplete (aws->is, +                                      cmd->label); +    TALER_EXCHANGE_age_withdraw_cancel (aws->handle); +    aws->handle = NULL; +  } + +  for (size_t n = 0; n < aws->num_coins; n++) +  { +    struct TALER_EXCHANGE_AgeWithdrawCoinInput *in = &aws->coin_inputs[n]; +    struct CoinOutputState *out = &aws->coin_outputs[n]; + +    if (NULL != in->denom_pub) +    { +      TALER_EXCHANGE_destroy_denomination_key (in->denom_pub); +      in->denom_pub = NULL; +    } +    TALER_age_commitment_proof_free (&out->details.age_commitment_proof); +  } +  GNUNET_free (aws->coin_inputs); +  GNUNET_free (aws->coin_outputs); +  GNUNET_free (aws->exchange_url); +  GNUNET_free (aws->reserve_payto_uri); +  GNUNET_free (aws); +} + + +/** + * Offer internal data of a "age withdraw" CMD state to other commands. + * + * @param cls Closure of type `struct AgeWithdrawState` + * @param[out] ret result (could be anything) + * @param trait name of the trait + * @param idx index number of the object to offer. + * @return #GNUNET_OK on success + */ +static enum GNUNET_GenericReturnValue +age_withdraw_traits ( +  void *cls, +  const void **ret, +  const char *trait, +  unsigned int idx) +{ +  struct AgeWithdrawState *aws = cls; +  uint8_t k = aws->noreveal_index; +  struct TALER_EXCHANGE_AgeWithdrawCoinInput *in = &aws->coin_inputs[idx]; +  struct CoinOutputState *out = &aws->coin_outputs[idx]; +  struct TALER_EXCHANGE_AgeWithdrawCoinPrivateDetails *details = +    &aws->coin_outputs[idx].details; +  struct TALER_TESTING_Trait traits[] = { +    /* history entry MUST be first due to response code logic below! */ +    TALER_TESTING_make_trait_reserve_history (idx, +                                              &out->reserve_history), +    TALER_TESTING_make_trait_denom_pub (idx, +                                        in->denom_pub), +    TALER_TESTING_make_trait_reserve_priv (&aws->reserve_priv), +    TALER_TESTING_make_trait_reserve_pub (&aws->reserve_pub), +    TALER_TESTING_make_trait_amounts (idx, +                                      &out->amount), +    /* TODO[oec]: add legal requirement to response and handle it here, as well +    TALER_TESTING_make_trait_legi_requirement_row (&aws->requirement_row), +    TALER_TESTING_make_trait_h_payto (&aws->h_payto), +    */ +    TALER_TESTING_make_trait_h_blinded_coin (idx, +                                             &aws->blinded_coin_hs[idx]), +    TALER_TESTING_make_trait_payto_uri (aws->reserve_payto_uri), +    TALER_TESTING_make_trait_exchange_url (aws->exchange_url), +    TALER_TESTING_make_trait_coin_priv (idx, +                                        &details->coin_priv), +    TALER_TESTING_make_trait_planchet_secrets (idx, +                                               &in->secrets[k]), +    TALER_TESTING_make_trait_blinding_key (idx, +                                           &details->blinding_key), +    TALER_TESTING_make_trait_exchange_wd_value (idx, +                                                &details->alg_values), +    TALER_TESTING_make_trait_age_commitment_proof ( +      idx, +      &details->age_commitment_proof), +    TALER_TESTING_make_trait_h_age_commitment ( +      idx, +      &details->h_age_commitment), +  }; + +  if (idx >= aws->num_coins) +    return GNUNET_NO; + +  return TALER_TESTING_get_trait ((aws->expected_response_code == MHD_HTTP_OK) +                                  ? &traits[0] /* we have reserve history */ +                                  : &traits[1], /* skip reserve history */ +                                  ret, +                                  trait, +                                  idx); +} +  struct TALER_TESTING_Command  TALER_TESTING_cmd_age_withdraw (const char *label, @@ -89,55 +462,27 @@ TALER_TESTING_cmd_age_withdraw (const char *label,    va_list ap;    aws = GNUNET_new (struct AgeWithdrawState); -  aws->max_age = max_age;    aws->reserve_reference = reserve_reference;    aws->expected_response_code = expected_response_code; - -// TODO[oec]: check max_age!? +  aws->mask = TALER_extensions_get_age_restriction_mask (); +  aws->max_age = TALER_get_lowest_age (&aws->mask, max_age);    cnt = 1;    va_start (ap, amount);    while (NULL != (va_arg (ap, const char *)))      cnt++;    aws->num_coins = cnt; -  aws->coins = GNUNET_new_array (cnt, -                                 struct CoinState); +  aws->coin_outputs = GNUNET_new_array (cnt, +                                        struct CoinOutputState);    va_end (ap);    va_start (ap, amount); +    for (unsigned int i = 0; i<aws->num_coins; i++)    { -    struct CoinState *cs = &aws->coins[i]; -    if (0 < max_age) -    { -      struct GNUNET_HashCode seed; -      struct TALER_AgeMask mask; - -      mask = TALER_extensions_get_age_restriction_mask (); -      GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, -                                  &seed, -                                  sizeof(seed)); - -      if (GNUNET_OK != -          TALER_age_restriction_commit ( -            &mask, -            max_age, -            &seed, -            &cs->details.age_commitment_proof)) -      { -        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                    "Failed to generate age commitment for age %d at %s\n", -                    max_age, -                    label); -        GNUNET_assert (0); -      } - -      TALER_age_commitment_hash (&cs->details.age_commitment_proof.commitment, -                                 &cs->details.h_age_commitment); -    } - +    struct CoinOutputState *out = &aws->coin_outputs[i];      if (GNUNET_OK !=          TALER_string_to_amount (amount, -                                &cs->amount)) +                                &out->amount))      {        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,                    "Failed to parse amount `%s' at %s\n", @@ -145,9 +490,10 @@ TALER_TESTING_cmd_age_withdraw (const char *label,                    label);        GNUNET_assert (0);      } -    /* move on to next vararg! */ -    amount = va_arg (ap, const char *);    } + +  /* move on to next vararg! */ +  amount = va_arg (ap, const char *);    GNUNET_assert (NULL == amount);    va_end (ap); @@ -155,9 +501,9 @@ TALER_TESTING_cmd_age_withdraw (const char *label,      struct TALER_TESTING_Command cmd = {        .cls = aws,        .label = label, -      .run = NULL, // &age_withdraw_run, -      .cleanup = NULL, // &age_withdraw_cleanup, -      .traits = NULL, // &age_withdraw_traits +      .run = &age_withdraw_run, +      .cleanup = &age_withdraw_cleanup, +      .traits = &age_withdraw_traits,      };      return cmd; @@ -165,4 +511,237 @@ TALER_TESTING_cmd_age_withdraw (const char *label,  } +/** + * The state for the age-withdraw-reveal operation + */ +struct AgeWithdrawRevealState +{ +  /** +   * The reference to the CMD resembling the previous call to age-withdraw +   */ +  const char *age_withdraw_reference; + +  /** +   * The state to the previous age-withdraw command +   */ +  const struct AgeWithdrawState *aws; + +  /** +   * The expected response code from the call to the +   * age-withdraw-reveal operation +   */ +  unsigned int expected_response_code; + +  /** +   * Interpreter state (during command) +   */ +  struct TALER_TESTING_Interpreter *is; + +  /** +   * The handle to the reveal-operation +   */ +  struct TALER_EXCHANGE_AgeWithdrawRevealHandle *handle; + + +  /** +   * Number of coins, extracted form the age withdraw command +   */ +  size_t num_coins; + +  /** +   * The signatures of the @e num_coins coins returned +   */ +  struct TALER_DenominationSignature *denom_sigs; + +}; + +/* + * Callback for the reveal response + * + * @param cls Closure of type `struct AgeWithdrawRevealState` + * @param awr The response + */ +static void +age_withdraw_reveal_cb ( +  void *cls, +  const struct TALER_EXCHANGE_AgeWithdrawRevealResponse *response) +{ +  struct AgeWithdrawRevealState *awrs = cls; +  struct TALER_TESTING_Interpreter *is = awrs->is; + +  awrs->handle = NULL; +  if (awrs->expected_response_code != response->hr.http_status) +  { +    TALER_TESTING_unexpected_status_with_body (is, +                                               response->hr.http_status, +                                               awrs->expected_response_code, +                                               response->hr.reply); +    return; +  } +  switch (response->hr.http_status) +  { +  case MHD_HTTP_OK: +    { +      const struct AgeWithdrawState *aws = awrs->aws; +      GNUNET_log (GNUNET_ERROR_TYPE_INFO, +                  "Got age-withdraw reveal success!\n"); +      GNUNET_assert (awrs->num_coins == response->details.ok.num_sigs); +      for (size_t n = 0; n < awrs->num_coins; n++) +        TALER_denom_sig_unblind (&awrs->denom_sigs[n], +                                 &response->details.ok.blinded_denom_sigs[n], +                                 &aws->coin_outputs[n].details.blinding_key, +                                 &aws->coin_outputs[n].details.h_coin_pub, +                                 &aws->coin_outputs[n].details.alg_values, +                                 &aws->coin_inputs[n].denom_pub->key); +    } +    break; +  case MHD_HTTP_NOT_FOUND: +  case MHD_HTTP_FORBIDDEN: +    /* nothing to check */ +    break; +  /* TODO[oec]: handle more cases !? */ +  default: +    /* Unsupported status code (by test harness) */ +    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, +                "Age withdraw reveal test command does not support status code %u\n", +                response->hr.http_status); +    GNUNET_break (0); +    break; +  } + +  /* We are done with this command, pick the next one */ +  TALER_TESTING_interpreter_next (is); +} + + +/** + * Run the command for age-withdraw-reveal + */ +static void +age_withdraw_reveal_run ( +  void *cls, +  const struct TALER_TESTING_Command *cmd, +  struct TALER_TESTING_Interpreter *is) +{ +  struct AgeWithdrawRevealState *awrs = cls; +  const struct TALER_TESTING_Command *age_withdraw_cmd; +  const struct AgeWithdrawState *aws; + +  (void) cmd; +  awrs->is = is; + +  /* +   * Get the command and state for the previous call to "age witdraw" +   */ +  age_withdraw_cmd  = +    TALER_TESTING_interpreter_get_command (is, +                                           awrs->age_withdraw_reference); +  if (NULL == age_withdraw_cmd) +  { +    GNUNET_break (0); +    TALER_TESTING_interpreter_fail (is); +  } +  GNUNET_assert (age_withdraw_cmd->run == age_withdraw_run); +  aws = age_withdraw_cmd->cls; +  awrs->aws = aws; +  awrs->num_coins = aws->num_coins; + +  awrs->handle = +    TALER_EXCHANGE_age_withdraw_reveal ( +      TALER_TESTING_interpreter_get_context (is), +      TALER_TESTING_get_exchange_url (is), +      aws->num_coins, +      aws->coin_inputs, +      aws->noreveal_index, +      &aws->h_commitment, +      age_withdraw_reveal_cb, +      awrs); +} + + +/** + * Free the state of a "age-withdraw-reveal" CMD, and possibly + * cancel a pending operation thereof + * + * @param cls Closure of type `struct AgeWithdrawRevealState` + * @param cmd The command being freed. + */ +static void +age_withdraw_reveal_cleanup ( +  void *cls, +  const struct TALER_TESTING_Command *cmd) +{ +  struct AgeWithdrawRevealState *awrs = cls; + +  if (NULL != awrs->handle) +  { +    TALER_TESTING_command_incomplete (awrs->is, +                                      cmd->label); +    TALER_EXCHANGE_age_withdraw_reveal_cancel (awrs->handle); +    awrs->handle = NULL; +  } +  GNUNET_free (awrs->denom_sigs); +  awrs->denom_sigs = NULL; +  GNUNET_free (awrs); +} + + +/** + * Offer internal data of a "age withdraw reveal" CMD state to other commands. + * + * @param cls Closure of they `struct AgeWithdrawRevealState` + * @param[out] ret result (could be anything) + * @param trait name of the trait + * @param idx index number of the object to offer. + * @return #GNUNET_OK on success + */ +static enum GNUNET_GenericReturnValue +age_withdraw_reveal_traits ( +  void *cls, +  const void **ret, +  const char *trait, +  unsigned int idx) +{ +  struct AgeWithdrawRevealState *awrs = cls; +  struct TALER_TESTING_Trait traits[] = { +    TALER_TESTING_make_trait_denom_sig (idx, +                                        &awrs->denom_sigs[idx]), +    /* FIXME: shall we provide the traits from the previous +     * call to "age withdraw" as well? */ +  }; + +  if (idx >= awrs->num_coins) +    return GNUNET_NO; + +  return TALER_TESTING_get_trait (traits, +                                  ret, +                                  trait, +                                  idx); +} + + +struct TALER_TESTING_Command +TALER_TESTING_cmd_age_withdraw_reveal ( +  const char *label, +  const char *age_withdraw_reference, +  unsigned int expected_response_code) +{ +  struct AgeWithdrawRevealState *awrs = +    GNUNET_new (struct AgeWithdrawRevealState); + +  awrs->age_withdraw_reference = age_withdraw_reference; +  awrs->expected_response_code = expected_response_code; + +  struct TALER_TESTING_Command cmd = { +    .cls = awrs, +    .label = label, +    .run = age_withdraw_reveal_run, +    .cleanup = age_withdraw_reveal_cleanup, +    .traits = age_withdraw_reveal_traits, +  }; + +  return cmd; +} + +  /* end of testing_api_cmd_age_withdraw.c */ diff --git a/src/testing/testing_api_cmd_batch_withdraw.c b/src/testing/testing_api_cmd_batch_withdraw.c index da43a9aa..41c74c3e 100644 --- a/src/testing/testing_api_cmd_batch_withdraw.c +++ b/src/testing/testing_api_cmd_batch_withdraw.c @@ -23,6 +23,7 @@   * @author Marcello Stanisci   */  #include "platform.h" +#include "taler_exchange_service.h"  #include "taler_json_lib.h"  #include <microhttpd.h>  #include <gnunet/gnunet_curl_lib.h> @@ -217,7 +218,7 @@ reserve_batch_withdraw_cb (void *cls,      /* nothing to check */      break;    case MHD_HTTP_CONFLICT: -    /* nothing to check */ +    /* TODO[oec]: Check if age-requirement is the reason */      break;    case MHD_HTTP_GONE:      /* theoretically could check that the key was actually */ @@ -250,6 +251,7 @@ batch_withdraw_run (void *cls,                      struct TALER_TESTING_Interpreter *is)  {    struct BatchWithdrawState *ws = cls; +  const struct TALER_EXCHANGE_Keys *keys =  TALER_TESTING_get_keys (is);    const struct TALER_ReservePrivateKeyP *rp;    const struct TALER_TESTING_Command *create_reserve;    const struct TALER_EXCHANGE_DenomPublicKey *dpk; @@ -292,7 +294,7 @@ batch_withdraw_run (void *cls,      struct TALER_EXCHANGE_WithdrawCoinInput *wci = &wcis[i];      TALER_planchet_master_setup_random (&cs->ps); -    dpk = TALER_TESTING_find_pk (TALER_TESTING_get_keys (is), +    dpk = TALER_TESTING_find_pk (keys,                                   &cs->amount,                                   ws->age > 0);      if (NULL == dpk) @@ -321,7 +323,7 @@ batch_withdraw_run (void *cls,    ws->wsh = TALER_EXCHANGE_batch_withdraw (      TALER_TESTING_interpreter_get_context (is),      TALER_TESTING_get_exchange_url (is), -    TALER_TESTING_get_keys (is), +    keys,      rp,      ws->num_coins,      wcis, diff --git a/src/testing/testing_api_cmd_common.c b/src/testing/testing_api_cmd_common.c index 91138f36..2c29f4ec 100644 --- a/src/testing/testing_api_cmd_common.c +++ b/src/testing/testing_api_cmd_common.c @@ -59,6 +59,20 @@ TALER_TESTING_history_entry_cmp (           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) */ diff --git a/src/testing/testing_api_loop.c b/src/testing/testing_api_loop.c index 2a8e3d0b..781028bf 100644 --- a/src/testing/testing_api_loop.c +++ b/src/testing/testing_api_loop.c @@ -31,6 +31,9 @@  #include "taler_testing_lib.h" +/** + * The interpreter and its state + */  struct TALER_TESTING_Interpreter  { | 
