LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_deposit.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 0 226 0.0 %
Date: 2022-08-25 06:15:09 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2018-2021 Taler Systems SA
       4             : 
       5             :   TALER is free software; you can redistribute it and/or modify it
       6             :   under the terms of the GNU General Public License as published by
       7             :   the Free Software Foundation; either version 3, or (at your
       8             :   option) any later version.
       9             : 
      10             :   TALER is distributed in the hope that it will be useful, but
      11             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :   General Public License for more details.
      14             : 
      15             :   You should have received a copy of the GNU General Public
      16             :   License along with TALER; see the file COPYING.  If not, see
      17             :   <http://www.gnu.org/licenses/>
      18             : */
      19             : /**
      20             :  * @file testing/testing_api_cmd_deposit.c
      21             :  * @brief command for testing /deposit.
      22             :  * @author Marcello Stanisci
      23             :  */
      24             : #include "platform.h"
      25             : #include "taler_json_lib.h"
      26             : #include <gnunet/gnunet_curl_lib.h>
      27             : #include "taler_testing_lib.h"
      28             : #include "taler_signatures.h"
      29             : #include "backoff.h"
      30             : 
      31             : 
      32             : /**
      33             :  * How often do we retry before giving up?
      34             :  */
      35             : #define NUM_RETRIES 5
      36             : 
      37             : /**
      38             :  * How long do we wait AT MOST when retrying?
      39             :  */
      40             : #define MAX_BACKOFF GNUNET_TIME_relative_multiply ( \
      41             :     GNUNET_TIME_UNIT_MILLISECONDS, 100)
      42             : 
      43             : 
      44             : /**
      45             :  * State for a "deposit" CMD.
      46             :  */
      47             : struct DepositState
      48             : {
      49             : 
      50             :   /**
      51             :    * Amount to deposit.
      52             :    */
      53             :   struct TALER_Amount amount;
      54             : 
      55             :   /**
      56             :    * Deposit fee.
      57             :    */
      58             :   struct TALER_Amount deposit_fee;
      59             : 
      60             :   /**
      61             :    * Reference to any command that is able to provide a coin.
      62             :    */
      63             :   const char *coin_reference;
      64             : 
      65             :   /**
      66             :    * If @e coin_reference refers to an operation that generated
      67             :    * an array of coins, this value determines which coin to pick.
      68             :    */
      69             :   unsigned int coin_index;
      70             : 
      71             :   /**
      72             :    * Wire details of who is depositing -- this would be merchant
      73             :    * wire details in a normal scenario.
      74             :    */
      75             :   json_t *wire_details;
      76             : 
      77             :   /**
      78             :    * JSON string describing what a proposal is about.
      79             :    */
      80             :   json_t *contract_terms;
      81             : 
      82             :   /**
      83             :    * Refund deadline. Zero for no refunds.
      84             :    */
      85             :   struct GNUNET_TIME_Timestamp refund_deadline;
      86             : 
      87             :   /**
      88             :    * Wire deadline.
      89             :    */
      90             :   struct GNUNET_TIME_Timestamp wire_deadline;
      91             : 
      92             :   /**
      93             :    * Set (by the interpreter) to a fresh private key.  This
      94             :    * key will be used to sign the deposit request.
      95             :    */
      96             :   struct TALER_MerchantPrivateKeyP merchant_priv;
      97             : 
      98             :   /**
      99             :    * Deposit handle while operation is running.
     100             :    */
     101             :   struct TALER_EXCHANGE_DepositHandle *dh;
     102             : 
     103             :   /**
     104             :    * Timestamp of the /deposit operation in the wallet (contract signing time).
     105             :    */
     106             :   struct GNUNET_TIME_Timestamp wallet_timestamp;
     107             : 
     108             :   /**
     109             :    * Interpreter state.
     110             :    */
     111             :   struct TALER_TESTING_Interpreter *is;
     112             : 
     113             :   /**
     114             :    * Task scheduled to try later.
     115             :    */
     116             :   struct GNUNET_SCHEDULER_Task *retry_task;
     117             : 
     118             :   /**
     119             :    * How long do we wait until we retry?
     120             :    */
     121             :   struct GNUNET_TIME_Relative backoff;
     122             : 
     123             :   /**
     124             :    * Expected HTTP response code.
     125             :    */
     126             :   unsigned int expected_response_code;
     127             : 
     128             :   /**
     129             :    * How often should we retry on (transient) failures?
     130             :    */
     131             :   unsigned int do_retry;
     132             : 
     133             :   /**
     134             :    * Set to #GNUNET_YES if the /deposit succeeded
     135             :    * and we now can provide the resulting traits.
     136             :    */
     137             :   int deposit_succeeded;
     138             : 
     139             :   /**
     140             :    * When did the exchange receive the deposit?
     141             :    */
     142             :   struct GNUNET_TIME_Timestamp exchange_timestamp;
     143             : 
     144             :   /**
     145             :    * Signing key used by the exchange to sign the
     146             :    * deposit confirmation.
     147             :    */
     148             :   struct TALER_ExchangePublicKeyP exchange_pub;
     149             : 
     150             :   /**
     151             :    * Signature from the exchange on the
     152             :    * deposit confirmation.
     153             :    */
     154             :   struct TALER_ExchangeSignatureP exchange_sig;
     155             : 
     156             :   /**
     157             :    * Reference to previous deposit operation.
     158             :    * Only present if we're supposed to replay the previous deposit.
     159             :    */
     160             :   const char *deposit_reference;
     161             : 
     162             :   /**
     163             :    * Did we set the parameters for this deposit command?
     164             :    *
     165             :    * When we're referencing another deposit operation,
     166             :    * this will only be set after the command has been started.
     167             :    */
     168             :   int command_initialized;
     169             : 
     170             :   /**
     171             :    * Reference to fetch the merchant private key from.
     172             :    * If NULL, we generate our own, fresh merchant key.
     173             :    */
     174             :   const char *merchant_priv_reference;
     175             : };
     176             : 
     177             : 
     178             : /**
     179             :  * Run the command.
     180             :  *
     181             :  * @param cls closure.
     182             :  * @param cmd the command to execute.
     183             :  * @param is the interpreter state.
     184             :  */
     185             : static void
     186             : deposit_run (void *cls,
     187             :              const struct TALER_TESTING_Command *cmd,
     188             :              struct TALER_TESTING_Interpreter *is);
     189             : 
     190             : 
     191             : /**
     192             :  * Task scheduled to re-try #deposit_run.
     193             :  *
     194             :  * @param cls a `struct DepositState`
     195             :  */
     196             : static void
     197           0 : do_retry (void *cls)
     198             : {
     199           0 :   struct DepositState *ds = cls;
     200             : 
     201           0 :   ds->retry_task = NULL;
     202           0 :   ds->is->commands[ds->is->ip].last_req_time
     203           0 :     = GNUNET_TIME_absolute_get ();
     204           0 :   deposit_run (ds,
     205             :                NULL,
     206             :                ds->is);
     207           0 : }
     208             : 
     209             : 
     210             : /**
     211             :  * Callback to analyze the /deposit response, just used to
     212             :  * check if the response code is acceptable.
     213             :  *
     214             :  * @param cls closure.
     215             :  * @param dr deposit response details
     216             :  */
     217             : static void
     218           0 : deposit_cb (void *cls,
     219             :             const struct TALER_EXCHANGE_DepositResult *dr)
     220             : {
     221           0 :   struct DepositState *ds = cls;
     222             : 
     223           0 :   ds->dh = NULL;
     224           0 :   if (ds->expected_response_code != dr->hr.http_status)
     225             :   {
     226           0 :     if (0 != ds->do_retry)
     227             :     {
     228           0 :       ds->do_retry--;
     229           0 :       if ( (0 == dr->hr.http_status) ||
     230           0 :            (TALER_EC_GENERIC_DB_SOFT_FAILURE == dr->hr.ec) ||
     231           0 :            (MHD_HTTP_INTERNAL_SERVER_ERROR == dr->hr.http_status) )
     232             :       {
     233           0 :         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     234             :                     "Retrying deposit failed with %u/%d\n",
     235             :                     dr->hr.http_status,
     236             :                     (int) dr->hr.ec);
     237             :         /* on DB conflicts, do not use backoff */
     238           0 :         if (TALER_EC_GENERIC_DB_SOFT_FAILURE == dr->hr.ec)
     239           0 :           ds->backoff = GNUNET_TIME_UNIT_ZERO;
     240             :         else
     241           0 :           ds->backoff = GNUNET_TIME_randomized_backoff (ds->backoff,
     242             :                                                         MAX_BACKOFF);
     243           0 :         ds->is->commands[ds->is->ip].num_tries++;
     244           0 :         GNUNET_assert (NULL == ds->retry_task);
     245             :         ds->retry_task
     246           0 :           = GNUNET_SCHEDULER_add_delayed (ds->backoff,
     247             :                                           &do_retry,
     248             :                                           ds);
     249           0 :         return;
     250             :       }
     251             :     }
     252           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     253             :                 "Unexpected response code %u to command %s in %s:%u\n",
     254             :                 dr->hr.http_status,
     255             :                 ds->is->commands[ds->is->ip].label,
     256             :                 __FILE__,
     257             :                 __LINE__);
     258           0 :     json_dumpf (dr->hr.reply,
     259             :                 stderr,
     260             :                 JSON_INDENT (2));
     261           0 :     TALER_TESTING_interpreter_fail (ds->is);
     262           0 :     return;
     263             :   }
     264           0 :   if (MHD_HTTP_OK == dr->hr.http_status)
     265             :   {
     266           0 :     ds->deposit_succeeded = GNUNET_YES;
     267           0 :     ds->exchange_timestamp = dr->details.success.deposit_timestamp;
     268           0 :     ds->exchange_pub = *dr->details.success.exchange_pub;
     269           0 :     ds->exchange_sig = *dr->details.success.exchange_sig;
     270             :   }
     271           0 :   TALER_TESTING_interpreter_next (ds->is);
     272             : }
     273             : 
     274             : 
     275             : /**
     276             :  * Run the command.
     277             :  *
     278             :  * @param cls closure.
     279             :  * @param cmd the command to execute.
     280             :  * @param is the interpreter state.
     281             :  */
     282             : static void
     283           0 : deposit_run (void *cls,
     284             :              const struct TALER_TESTING_Command *cmd,
     285             :              struct TALER_TESTING_Interpreter *is)
     286             : {
     287           0 :   struct DepositState *ds = cls;
     288             :   const struct TALER_TESTING_Command *coin_cmd;
     289             :   const struct TALER_CoinSpendPrivateKeyP *coin_priv;
     290             :   struct TALER_CoinSpendPublicKeyP coin_pub;
     291           0 :   const struct TALER_AgeCommitmentProof *age_commitment_proof = NULL;
     292           0 :   struct TALER_AgeCommitmentHash h_age_commitment = {0};
     293             :   const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
     294             :   const struct TALER_DenominationSignature *denom_pub_sig;
     295             :   struct TALER_CoinSpendSignatureP coin_sig;
     296             :   struct TALER_MerchantPublicKeyP merchant_pub;
     297             :   struct TALER_PrivateContractHashP h_contract_terms;
     298             :   enum TALER_ErrorCode ec;
     299             :   struct TALER_WireSaltP wire_salt;
     300             :   const char *payto_uri;
     301             :   struct GNUNET_JSON_Specification spec[] = {
     302           0 :     GNUNET_JSON_spec_string ("payto_uri",
     303             :                              &payto_uri),
     304           0 :     GNUNET_JSON_spec_fixed_auto ("salt",
     305             :                                  &wire_salt),
     306           0 :     GNUNET_JSON_spec_end ()
     307             :   };
     308             : 
     309             :   (void) cmd;
     310           0 :   ds->is = is;
     311           0 :   if (NULL != ds->deposit_reference)
     312             :   {
     313             :     /* We're copying another deposit operation, initialize here. */
     314             :     const struct TALER_TESTING_Command *cmd;
     315             :     struct DepositState *ods;
     316             : 
     317           0 :     cmd = TALER_TESTING_interpreter_lookup_command (is,
     318             :                                                     ds->deposit_reference);
     319           0 :     if (NULL == cmd)
     320             :     {
     321           0 :       GNUNET_break (0);
     322           0 :       TALER_TESTING_interpreter_fail (is);
     323           0 :       return;
     324             :     }
     325           0 :     ods = cmd->cls;
     326           0 :     ds->coin_reference = ods->coin_reference;
     327           0 :     ds->coin_index = ods->coin_index;
     328           0 :     ds->wire_details = json_incref (ods->wire_details);
     329           0 :     GNUNET_assert (NULL != ds->wire_details);
     330           0 :     ds->contract_terms = json_incref (ods->contract_terms);
     331           0 :     ds->wallet_timestamp = ods->wallet_timestamp;
     332           0 :     ds->refund_deadline = ods->refund_deadline;
     333           0 :     ds->amount = ods->amount;
     334           0 :     ds->merchant_priv = ods->merchant_priv;
     335           0 :     ds->command_initialized = GNUNET_YES;
     336             :   }
     337           0 :   else if (NULL != ds->merchant_priv_reference)
     338             :   {
     339             :     /* We're copying the merchant key from another deposit operation */
     340             :     const struct TALER_MerchantPrivateKeyP *merchant_priv;
     341             :     const struct TALER_TESTING_Command *cmd;
     342             : 
     343           0 :     cmd = TALER_TESTING_interpreter_lookup_command (is,
     344             :                                                     ds->merchant_priv_reference);
     345           0 :     if (NULL == cmd)
     346             :     {
     347           0 :       GNUNET_break (0);
     348           0 :       TALER_TESTING_interpreter_fail (is);
     349           0 :       return;
     350             :     }
     351           0 :     if ( (GNUNET_OK !=
     352           0 :           TALER_TESTING_get_trait_merchant_priv (cmd,
     353             :                                                  &merchant_priv)) )
     354             :     {
     355           0 :       GNUNET_break (0);
     356           0 :       TALER_TESTING_interpreter_fail (is);
     357           0 :       return;
     358             :     }
     359           0 :     ds->merchant_priv = *merchant_priv;
     360             :   }
     361           0 :   GNUNET_assert (NULL != ds->wire_details);
     362           0 :   if (GNUNET_OK !=
     363           0 :       GNUNET_JSON_parse (ds->wire_details,
     364             :                          spec,
     365             :                          NULL, NULL))
     366             :   {
     367           0 :     json_dumpf (ds->wire_details,
     368             :                 stderr,
     369             :                 JSON_INDENT (2));
     370           0 :     GNUNET_break (0);
     371           0 :     TALER_TESTING_interpreter_fail (is);
     372           0 :     return;
     373             :   }
     374           0 :   GNUNET_assert (ds->coin_reference);
     375           0 :   coin_cmd = TALER_TESTING_interpreter_lookup_command (is,
     376             :                                                        ds->coin_reference);
     377           0 :   if (NULL == coin_cmd)
     378             :   {
     379           0 :     GNUNET_break (0);
     380           0 :     TALER_TESTING_interpreter_fail (is);
     381           0 :     return;
     382             :   }
     383             : 
     384           0 :   if ( (GNUNET_OK !=
     385           0 :         TALER_TESTING_get_trait_coin_priv (coin_cmd,
     386             :                                            ds->coin_index,
     387           0 :                                            &coin_priv)) ||
     388             :        (GNUNET_OK !=
     389           0 :         TALER_TESTING_get_trait_age_commitment_proof (coin_cmd,
     390             :                                                       ds->coin_index,
     391           0 :                                                       &age_commitment_proof)) ||
     392             :        (GNUNET_OK !=
     393           0 :         TALER_TESTING_get_trait_denom_pub (coin_cmd,
     394             :                                            ds->coin_index,
     395           0 :                                            &denom_pub)) ||
     396             :        (GNUNET_OK !=
     397           0 :         TALER_TESTING_get_trait_denom_sig (coin_cmd,
     398             :                                            ds->coin_index,
     399           0 :                                            &denom_pub_sig)) ||
     400             :        (GNUNET_OK !=
     401           0 :         TALER_JSON_contract_hash (ds->contract_terms,
     402             :                                   &h_contract_terms)) )
     403             :   {
     404           0 :     GNUNET_break (0);
     405           0 :     TALER_TESTING_interpreter_fail (is);
     406           0 :     return;
     407             :   }
     408             : 
     409           0 :   if (NULL != age_commitment_proof)
     410             :   {
     411           0 :     TALER_age_commitment_hash (&age_commitment_proof->commitment,
     412             :                                &h_age_commitment);
     413             :   }
     414           0 :   ds->deposit_fee = denom_pub->fees.deposit;
     415           0 :   GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
     416             :                                       &coin_pub.eddsa_pub);
     417             : 
     418           0 :   if (! GNUNET_TIME_absolute_is_zero (ds->refund_deadline.abs_time))
     419             :   {
     420             :     struct GNUNET_TIME_Relative refund_deadline;
     421             : 
     422             :     refund_deadline
     423           0 :       = GNUNET_TIME_absolute_get_remaining (ds->refund_deadline.abs_time);
     424             :     ds->wire_deadline
     425             :       =
     426           0 :         GNUNET_TIME_relative_to_timestamp (
     427             :           GNUNET_TIME_relative_multiply (refund_deadline,
     428             :                                          2));
     429             :   }
     430             :   else
     431             :   {
     432           0 :     ds->refund_deadline = ds->wallet_timestamp;
     433           0 :     ds->wire_deadline = GNUNET_TIME_timestamp_get ();
     434             :   }
     435           0 :   GNUNET_CRYPTO_eddsa_key_get_public (&ds->merchant_priv.eddsa_priv,
     436             :                                       &merchant_pub.eddsa_pub);
     437             :   {
     438             :     struct TALER_MerchantWireHashP h_wire;
     439             : 
     440           0 :     GNUNET_assert (GNUNET_OK ==
     441             :                    TALER_JSON_merchant_wire_signature_hash (ds->wire_details,
     442             :                                                             &h_wire));
     443           0 :     TALER_wallet_deposit_sign (&ds->amount,
     444           0 :                                &denom_pub->fees.deposit,
     445             :                                &h_wire,
     446             :                                &h_contract_terms,
     447             :                                &h_age_commitment,
     448             :                                NULL, /* FIXME #7270: add hash of extensions */
     449           0 :                                &denom_pub->h_key,
     450             :                                ds->wallet_timestamp,
     451             :                                &merchant_pub,
     452             :                                ds->refund_deadline,
     453             :                                coin_priv,
     454             :                                &coin_sig);
     455             :   }
     456           0 :   GNUNET_assert (NULL == ds->dh);
     457             :   {
     458           0 :     struct TALER_EXCHANGE_CoinDepositDetail cdd = {
     459             :       .amount = ds->amount,
     460             :       .h_age_commitment = h_age_commitment,
     461             :       .coin_pub = coin_pub,
     462             :       .coin_sig = coin_sig,
     463           0 :       .denom_sig = *denom_pub_sig,
     464           0 :       .h_denom_pub = denom_pub->h_key
     465             :     };
     466           0 :     struct TALER_EXCHANGE_DepositContractDetail dcd = {
     467             :       .wire_deadline = ds->wire_deadline,
     468             :       .merchant_payto_uri = payto_uri,
     469             :       .wire_salt = wire_salt,
     470             :       .h_contract_terms = h_contract_terms,
     471             :       .extension_details = NULL /* FIXME #7270-OEC */,
     472             :       .timestamp = ds->wallet_timestamp,
     473             :       .merchant_pub = merchant_pub,
     474             :       .refund_deadline = ds->refund_deadline
     475             :     };
     476             : 
     477           0 :     ds->dh = TALER_EXCHANGE_deposit (is->exchange,
     478             :                                      &dcd,
     479             :                                      &cdd,
     480             :                                      &deposit_cb,
     481             :                                      ds,
     482             :                                      &ec);
     483             :   }
     484           0 :   if (NULL == ds->dh)
     485             :   {
     486           0 :     GNUNET_break (0);
     487           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     488             :                 "Could not create deposit with EC %d\n",
     489             :                 (int) ec);
     490           0 :     TALER_TESTING_interpreter_fail (is);
     491           0 :     return;
     492             :   }
     493             : }
     494             : 
     495             : 
     496             : /**
     497             :  * Free the state of a "deposit" CMD, and possibly cancel a
     498             :  * pending operation thereof.
     499             :  *
     500             :  * @param cls closure, must be a `struct DepositState`.
     501             :  * @param cmd the command which is being cleaned up.
     502             :  */
     503             : static void
     504           0 : deposit_cleanup (void *cls,
     505             :                  const struct TALER_TESTING_Command *cmd)
     506             : {
     507           0 :   struct DepositState *ds = cls;
     508             : 
     509           0 :   if (NULL != ds->dh)
     510             :   {
     511           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     512             :                 "Command %u (%s) did not complete\n",
     513             :                 ds->is->ip,
     514             :                 cmd->label);
     515           0 :     TALER_EXCHANGE_deposit_cancel (ds->dh);
     516           0 :     ds->dh = NULL;
     517             :   }
     518           0 :   if (NULL != ds->retry_task)
     519             :   {
     520           0 :     GNUNET_SCHEDULER_cancel (ds->retry_task);
     521           0 :     ds->retry_task = NULL;
     522             :   }
     523           0 :   json_decref (ds->wire_details);
     524           0 :   json_decref (ds->contract_terms);
     525           0 :   GNUNET_free (ds);
     526           0 : }
     527             : 
     528             : 
     529             : /**
     530             :  * Offer internal data from a "deposit" CMD, to other commands.
     531             :  *
     532             :  * @param cls closure.
     533             :  * @param[out] ret result.
     534             :  * @param trait name of the trait.
     535             :  * @param index index number of the object to offer.
     536             :  * @return #GNUNET_OK on success.
     537             :  */
     538             : static enum GNUNET_GenericReturnValue
     539           0 : deposit_traits (void *cls,
     540             :                 const void **ret,
     541             :                 const char *trait,
     542             :                 unsigned int index)
     543             : {
     544           0 :   struct DepositState *ds = cls;
     545             :   const struct TALER_TESTING_Command *coin_cmd;
     546             :   /* Will point to coin cmd internals. */
     547             :   const struct TALER_CoinSpendPrivateKeyP *coin_spent_priv;
     548             :   const struct TALER_AgeCommitmentProof *age_commitment_proof;
     549             : 
     550           0 :   if (GNUNET_YES != ds->command_initialized)
     551             :   {
     552             :     /* No access to traits yet. */
     553           0 :     GNUNET_break (0);
     554           0 :     return GNUNET_NO;
     555             :   }
     556             : 
     557             :   coin_cmd
     558           0 :     = TALER_TESTING_interpreter_lookup_command (ds->is,
     559             :                                                 ds->coin_reference);
     560           0 :   if (NULL == coin_cmd)
     561             :   {
     562           0 :     GNUNET_break (0);
     563           0 :     TALER_TESTING_interpreter_fail (ds->is);
     564           0 :     return GNUNET_NO;
     565             :   }
     566           0 :   if ( (GNUNET_OK !=
     567           0 :         TALER_TESTING_get_trait_coin_priv (coin_cmd,
     568             :                                            ds->coin_index,
     569           0 :                                            &coin_spent_priv)) ||
     570             :        (GNUNET_OK !=
     571           0 :         TALER_TESTING_get_trait_age_commitment_proof (coin_cmd,
     572             :                                                       ds->coin_index,
     573             :                                                       &age_commitment_proof)) )
     574             :   {
     575           0 :     GNUNET_break (0);
     576           0 :     TALER_TESTING_interpreter_fail (ds->is);
     577           0 :     return GNUNET_NO;
     578             :   }
     579             :   {
     580             :     struct TALER_TESTING_Trait traits[] = {
     581             :       /* First two traits are only available if
     582             :          ds->traits is #GNUNET_YES */
     583           0 :       TALER_TESTING_make_trait_exchange_pub (0,
     584           0 :                                              &ds->exchange_pub),
     585           0 :       TALER_TESTING_make_trait_exchange_sig (0,
     586           0 :                                              &ds->exchange_sig),
     587             :       /* These traits are always available */
     588           0 :       TALER_TESTING_make_trait_coin_priv (0,
     589             :                                           coin_spent_priv),
     590           0 :       TALER_TESTING_make_trait_age_commitment_proof (0,
     591             :                                                      age_commitment_proof),
     592           0 :       TALER_TESTING_make_trait_wire_details (ds->wire_details),
     593           0 :       TALER_TESTING_make_trait_contract_terms (ds->contract_terms),
     594           0 :       TALER_TESTING_make_trait_merchant_priv (&ds->merchant_priv),
     595           0 :       TALER_TESTING_make_trait_deposit_amount (0,
     596           0 :                                                &ds->amount),
     597           0 :       TALER_TESTING_make_trait_deposit_fee_amount (0,
     598           0 :                                                    &ds->deposit_fee),
     599           0 :       TALER_TESTING_make_trait_timestamp (0,
     600           0 :                                           &ds->exchange_timestamp),
     601           0 :       TALER_TESTING_make_trait_wire_deadline (0,
     602           0 :                                               &ds->wire_deadline),
     603           0 :       TALER_TESTING_make_trait_refund_deadline (0,
     604           0 :                                                 &ds->refund_deadline),
     605           0 :       TALER_TESTING_trait_end ()
     606             :     };
     607             : 
     608           0 :     return TALER_TESTING_get_trait ((ds->deposit_succeeded)
     609             :                                     ? traits
     610             :                                     : &traits[2],
     611             :                                     ret,
     612             :                                     trait,
     613             :                                     index);
     614             :   }
     615             : }
     616             : 
     617             : 
     618             : struct TALER_TESTING_Command
     619           0 : TALER_TESTING_cmd_deposit (const char *label,
     620             :                            const char *coin_reference,
     621             :                            unsigned int coin_index,
     622             :                            const char *target_account_payto,
     623             :                            const char *contract_terms,
     624             :                            struct GNUNET_TIME_Relative refund_deadline,
     625             :                            const char *amount,
     626             :                            unsigned int expected_response_code)
     627             : {
     628             :   struct DepositState *ds;
     629             : 
     630           0 :   ds = GNUNET_new (struct DepositState);
     631           0 :   ds->coin_reference = coin_reference;
     632           0 :   ds->coin_index = coin_index;
     633           0 :   ds->wire_details = TALER_TESTING_make_wire_details (target_account_payto);
     634           0 :   GNUNET_assert (NULL != ds->wire_details);
     635           0 :   ds->contract_terms = json_loads (contract_terms,
     636             :                                    JSON_REJECT_DUPLICATES,
     637             :                                    NULL);
     638           0 :   GNUNET_CRYPTO_eddsa_key_create (&ds->merchant_priv.eddsa_priv);
     639           0 :   if (NULL == ds->contract_terms)
     640             :   {
     641           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     642             :                 "Failed to parse contract terms `%s' for CMD `%s'\n",
     643             :                 contract_terms,
     644             :                 label);
     645           0 :     GNUNET_assert (0);
     646             :   }
     647           0 :   ds->wallet_timestamp = GNUNET_TIME_timestamp_get ();
     648           0 :   GNUNET_assert (0 ==
     649             :                  json_object_set_new (ds->contract_terms,
     650             :                                       "timestamp",
     651             :                                       GNUNET_JSON_from_timestamp (
     652             :                                         ds->wallet_timestamp)));
     653           0 :   if (! GNUNET_TIME_relative_is_zero (refund_deadline))
     654             :   {
     655           0 :     ds->refund_deadline = GNUNET_TIME_relative_to_timestamp (refund_deadline);
     656           0 :     GNUNET_assert (0 ==
     657             :                    json_object_set_new (ds->contract_terms,
     658             :                                         "refund_deadline",
     659             :                                         GNUNET_JSON_from_timestamp (
     660             :                                           ds->refund_deadline)));
     661             :   }
     662           0 :   GNUNET_assert (GNUNET_OK ==
     663             :                  TALER_string_to_amount (amount,
     664             :                                          &ds->amount));
     665           0 :   ds->expected_response_code = expected_response_code;
     666           0 :   ds->command_initialized = GNUNET_YES;
     667             :   {
     668           0 :     struct TALER_TESTING_Command cmd = {
     669             :       .cls = ds,
     670             :       .label = label,
     671             :       .run = &deposit_run,
     672             :       .cleanup = &deposit_cleanup,
     673             :       .traits = &deposit_traits
     674             :     };
     675             : 
     676           0 :     return cmd;
     677             :   }
     678             : }
     679             : 
     680             : 
     681             : struct TALER_TESTING_Command
     682           0 : TALER_TESTING_cmd_deposit_with_ref (const char *label,
     683             :                                     const char *coin_reference,
     684             :                                     unsigned int coin_index,
     685             :                                     const char *target_account_payto,
     686             :                                     const char *contract_terms,
     687             :                                     struct GNUNET_TIME_Relative refund_deadline,
     688             :                                     const char *amount,
     689             :                                     unsigned int expected_response_code,
     690             :                                     const char *merchant_priv_reference)
     691             : {
     692             :   struct DepositState *ds;
     693             : 
     694           0 :   ds = GNUNET_new (struct DepositState);
     695           0 :   ds->merchant_priv_reference = merchant_priv_reference;
     696           0 :   ds->coin_reference = coin_reference;
     697           0 :   ds->coin_index = coin_index;
     698           0 :   ds->wire_details = TALER_TESTING_make_wire_details (target_account_payto);
     699           0 :   GNUNET_assert (NULL != ds->wire_details);
     700           0 :   ds->contract_terms = json_loads (contract_terms,
     701             :                                    JSON_REJECT_DUPLICATES,
     702             :                                    NULL);
     703           0 :   if (NULL == ds->contract_terms)
     704             :   {
     705           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     706             :                 "Failed to parse contract terms `%s' for CMD `%s'\n",
     707             :                 contract_terms,
     708             :                 label);
     709           0 :     GNUNET_assert (0);
     710             :   }
     711           0 :   ds->wallet_timestamp = GNUNET_TIME_timestamp_get ();
     712           0 :   json_object_set_new (ds->contract_terms,
     713             :                        "timestamp",
     714             :                        GNUNET_JSON_from_timestamp (ds->wallet_timestamp));
     715           0 :   if (0 != refund_deadline.rel_value_us)
     716             :   {
     717           0 :     ds->refund_deadline = GNUNET_TIME_relative_to_timestamp (refund_deadline);
     718           0 :     json_object_set_new (ds->contract_terms,
     719             :                          "refund_deadline",
     720             :                          GNUNET_JSON_from_timestamp (ds->refund_deadline));
     721             :   }
     722           0 :   GNUNET_assert (GNUNET_OK ==
     723             :                  TALER_string_to_amount (amount,
     724             :                                          &ds->amount));
     725           0 :   ds->expected_response_code = expected_response_code;
     726           0 :   ds->command_initialized = GNUNET_YES;
     727             :   {
     728           0 :     struct TALER_TESTING_Command cmd = {
     729             :       .cls = ds,
     730             :       .label = label,
     731             :       .run = &deposit_run,
     732             :       .cleanup = &deposit_cleanup,
     733             :       .traits = &deposit_traits
     734             :     };
     735             : 
     736           0 :     return cmd;
     737             :   }
     738             : }
     739             : 
     740             : 
     741             : struct TALER_TESTING_Command
     742           0 : TALER_TESTING_cmd_deposit_replay (const char *label,
     743             :                                   const char *deposit_reference,
     744             :                                   unsigned int expected_response_code)
     745             : {
     746             :   struct DepositState *ds;
     747             : 
     748           0 :   ds = GNUNET_new (struct DepositState);
     749           0 :   ds->deposit_reference = deposit_reference;
     750           0 :   ds->expected_response_code = expected_response_code;
     751             :   {
     752           0 :     struct TALER_TESTING_Command cmd = {
     753             :       .cls = ds,
     754             :       .label = label,
     755             :       .run = &deposit_run,
     756             :       .cleanup = &deposit_cleanup,
     757             :       .traits = &deposit_traits
     758             :     };
     759             : 
     760           0 :     return cmd;
     761             :   }
     762             : }
     763             : 
     764             : 
     765             : struct TALER_TESTING_Command
     766           0 : TALER_TESTING_cmd_deposit_with_retry (struct TALER_TESTING_Command cmd)
     767             : {
     768             :   struct DepositState *ds;
     769             : 
     770           0 :   GNUNET_assert (&deposit_run == cmd.run);
     771           0 :   ds = cmd.cls;
     772           0 :   ds->do_retry = NUM_RETRIES;
     773           0 :   return cmd;
     774             : }
     775             : 
     776             : 
     777             : /* end of testing_api_cmd_deposit.c */

Generated by: LCOV version 1.14