LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_insert_deposit.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 80.9 % 110 89
Test Date: 2025-12-26 23:00:34 Functions: 100.0 % 4 4

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2018, 2024 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
       7              :   by 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
      13              :   GNU 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,
      17              :   see <http://www.gnu.org/licenses/>
      18              : */
      19              : /**
      20              :  * @file testing/testing_api_cmd_insert_deposit.c
      21              :  * @brief deposit a coin directly into the database.
      22              :  * @author Marcello Stanisci
      23              :  * @author Christian Grothoff
      24              :  */
      25              : #include "taler/platform.h"
      26              : #include "taler/taler_util.h"
      27              : #include "taler/taler_json_lib.h"
      28              : #include <gnunet/gnunet_curl_lib.h>
      29              : #include "taler/taler_signatures.h"
      30              : #include "taler/taler_testing_lib.h"
      31              : #include "taler/taler_exchangedb_plugin.h"
      32              : #include "taler/taler_exchangedb_lib.h"
      33              : 
      34              : 
      35              : /**
      36              :  * State for a "insert-deposit" CMD.
      37              :  */
      38              : struct InsertDepositState
      39              : {
      40              :   /**
      41              :    * Database connection we use.
      42              :    */
      43              :   struct TALER_EXCHANGEDB_Plugin *plugin;
      44              : 
      45              :   /**
      46              :    * Human-readable name of the shop.
      47              :    */
      48              :   const char *merchant_name;
      49              : 
      50              :   /**
      51              :    * Merchant account name (NOT a payto-URI).
      52              :    */
      53              :   const char *merchant_account;
      54              : 
      55              :   /**
      56              :    * Deadline before which the aggregator should
      57              :    * send the payment to the merchant.
      58              :    */
      59              :   struct GNUNET_TIME_Relative wire_deadline;
      60              : 
      61              :   /**
      62              :    * When did the exchange receive the deposit?
      63              :    */
      64              :   struct GNUNET_TIME_Timestamp exchange_timestamp;
      65              : 
      66              :   /**
      67              :    * Amount to deposit, inclusive of deposit fee.
      68              :    */
      69              :   const char *amount_with_fee;
      70              : 
      71              :   /**
      72              :    * Deposit fee.
      73              :    */
      74              :   const char *deposit_fee;
      75              : 
      76              :   /**
      77              :    * Do we used a cached @e plugin?
      78              :    */
      79              :   bool cached;
      80              : };
      81              : 
      82              : /**
      83              :  * Setup (fake) information about a coin used in deposit.
      84              :  *
      85              :  * @param[out] issue information to initialize with "valid" data
      86              :  */
      87              : static void
      88           24 : fake_issue (struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
      89              : {
      90              :   struct GNUNET_TIME_Timestamp now;
      91              : 
      92           24 :   memset (issue,
      93              :           0,
      94              :           sizeof (*issue));
      95           24 :   now = GNUNET_TIME_timestamp_get ();
      96              :   issue->start
      97           24 :     = now;
      98              :   issue->expire_withdraw
      99           24 :     = GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_MINUTES);
     100              :   issue->expire_deposit
     101           24 :     = GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_HOURS);
     102              :   issue->expire_legal
     103           24 :     = GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_DAYS);
     104           24 :   GNUNET_assert (GNUNET_OK ==
     105              :                  TALER_string_to_amount ("EUR:1",
     106              :                                          &issue->value));
     107           24 :   GNUNET_assert (GNUNET_OK ==
     108              :                  TALER_string_to_amount ("EUR:0.1",
     109              :                                          &issue->fees.withdraw));
     110           24 :   GNUNET_assert (GNUNET_OK ==
     111              :                  TALER_string_to_amount ("EUR:0.1",
     112              :                                          &issue->fees.deposit));
     113           24 :   GNUNET_assert (GNUNET_OK ==
     114              :                  TALER_string_to_amount ("EUR:0.1",
     115              :                                          &issue->fees.refresh));
     116           24 :   GNUNET_assert (GNUNET_OK ==
     117              :                  TALER_string_to_amount ("EUR:0.1",
     118              :                                          &issue->fees.refund));
     119           24 : }
     120              : 
     121              : 
     122              : /**
     123              :  * Run the command.
     124              :  *
     125              :  * @param cls closure.
     126              :  * @param cmd the commaind being run.
     127              :  * @param is interpreter state.
     128              :  */
     129              : static void
     130           24 : insert_deposit_run (void *cls,
     131              :                     const struct TALER_TESTING_Command *cmd,
     132              :                     struct TALER_TESTING_Interpreter *is)
     133              : {
     134           24 :   struct InsertDepositState *ids = cls;
     135              :   struct TALER_EXCHANGEDB_CoinDepositInformation deposit;
     136              :   struct TALER_EXCHANGEDB_BatchDeposit bd;
     137              :   struct TALER_MerchantPrivateKeyP merchant_priv;
     138              :   struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
     139              :   struct TALER_DenominationPublicKey dpk;
     140              :   struct TALER_DenominationPrivateKey denom_priv;
     141              :   struct TALER_FullPayto receiver_wire_account;
     142              : 
     143              :   (void) cmd;
     144           24 :   if (NULL == ids->plugin)
     145              :   {
     146            0 :     GNUNET_break (0);
     147            0 :     TALER_TESTING_interpreter_fail (is);
     148            0 :     return;
     149              :   }
     150           24 :   if (GNUNET_OK !=
     151           24 :       ids->plugin->preflight (ids->plugin->cls))
     152              :   {
     153            0 :     GNUNET_break (0);
     154            0 :     TALER_TESTING_interpreter_fail (is);
     155            0 :     return;
     156              :   }
     157           24 :   fake_issue (&issue);
     158           24 :   GNUNET_assert (GNUNET_OK ==
     159              :                  TALER_denom_priv_create (&denom_priv,
     160              :                                           &dpk,
     161              :                                           GNUNET_CRYPTO_BSA_RSA,
     162              :                                           1024));
     163           24 :   TALER_denom_pub_hash (&dpk,
     164              :                         &issue.denom_hash);
     165              : 
     166           24 :   if ( (GNUNET_OK !=
     167           24 :         ids->plugin->start (ids->plugin->cls,
     168           24 :                             "talertestinglib: denomination insertion")) ||
     169              :        (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     170           24 :         ids->plugin->insert_denomination_info (ids->plugin->cls,
     171              :                                                &dpk,
     172           24 :                                                &issue)) ||
     173              :        (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     174           24 :         ids->plugin->commit (ids->plugin->cls)) )
     175              :   {
     176            0 :     TALER_TESTING_interpreter_fail (is);
     177            0 :     TALER_denom_pub_free (&dpk);
     178            0 :     TALER_denom_priv_free (&denom_priv);
     179            0 :     return;
     180              :   }
     181              : 
     182              :   /* prepare and store deposit now. */
     183           24 :   memset (&deposit,
     184              :           0,
     185              :           sizeof (deposit));
     186           24 :   memset (&bd,
     187              :           0,
     188              :           sizeof (bd));
     189           24 :   bd.cdis = &deposit;
     190           24 :   bd.num_cdis = 1;
     191              : 
     192           24 :   GNUNET_assert (
     193              :     GNUNET_YES ==
     194              :     GNUNET_CRYPTO_kdf (&merchant_priv,
     195              :                        sizeof (struct TALER_MerchantPrivateKeyP),
     196              :                        "merchant-priv",
     197              :                        strlen ("merchant-priv"),
     198              :                        ids->merchant_name,
     199              :                        strlen (ids->merchant_name),
     200              :                        NULL,
     201              :                        0));
     202           24 :   GNUNET_assert (
     203              :     GNUNET_YES ==
     204              :     GNUNET_CRYPTO_kdf (&bd.merchant_sig,
     205              :                        sizeof (struct TALER_MerchantSignatureP),
     206              :                        "merchant-sig",
     207              :                        strlen ("merchant-sig"),
     208              :                        ids->merchant_name,
     209              :                        strlen (ids->merchant_name),
     210              :                        NULL,
     211              :                        0));
     212           24 :   GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv.eddsa_priv,
     213              :                                       &bd.merchant_pub.eddsa_pub);
     214           24 :   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
     215              :                                     &bd.h_contract_terms.hash);
     216           24 :   if (GNUNET_OK !=
     217           24 :       TALER_string_to_amount (ids->amount_with_fee,
     218              :                               &deposit.amount_with_fee))
     219              :   {
     220            0 :     TALER_TESTING_interpreter_fail (is);
     221            0 :     TALER_denom_pub_free (&dpk);
     222            0 :     TALER_denom_priv_free (&denom_priv);
     223            0 :     return;
     224              :   }
     225              : 
     226           24 :   TALER_denom_pub_hash (&dpk,
     227              :                         &deposit.coin.denom_pub_hash);
     228           24 :   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
     229              :                               &deposit.coin.coin_pub,
     230              :                               sizeof (deposit.coin.coin_pub));
     231              :   {
     232              :     struct TALER_CoinPubHashP c_hash;
     233              :     struct TALER_PlanchetDetail pd;
     234              :     struct TALER_BlindedDenominationSignature bds;
     235              :     struct TALER_PlanchetMasterSecretP ps;
     236              :     union GNUNET_CRYPTO_BlindingSecretP bks;
     237              :     const struct TALER_ExchangeBlindingValues *alg_values;
     238              : 
     239           24 :     alg_values = TALER_denom_ewv_rsa_singleton ();
     240           24 :     TALER_planchet_blinding_secret_create (&ps,
     241              :                                            alg_values,
     242              :                                            &bks);
     243           24 :     GNUNET_assert (GNUNET_OK ==
     244              :                    TALER_denom_blind (&dpk,
     245              :                                       &bks,
     246              :                                       NULL, /* no age restriction active */
     247              :                                       NULL, /* no nonce needed */
     248              :                                       &deposit.coin.coin_pub,
     249              :                                       alg_values,
     250              :                                       &c_hash,
     251              :                                       &pd.blinded_planchet));
     252           24 :     GNUNET_assert (GNUNET_OK ==
     253              :                    TALER_denom_sign_blinded (&bds,
     254              :                                              &denom_priv,
     255              :                                              false,
     256              :                                              &pd.blinded_planchet));
     257           24 :     TALER_blinded_planchet_free (&pd.blinded_planchet);
     258           24 :     GNUNET_assert (GNUNET_OK ==
     259              :                    TALER_denom_sig_unblind (&deposit.coin.denom_sig,
     260              :                                             &bds,
     261              :                                             &bks,
     262              :                                             &c_hash,
     263              :                                             alg_values,
     264              :                                             &dpk));
     265           24 :     TALER_blinded_denom_sig_free (&bds);
     266              :   }
     267           24 :   GNUNET_asprintf (&receiver_wire_account.full_payto,
     268              :                    "payto://x-taler-bank/localhost/%s?receiver-name=%s",
     269              :                    ids->merchant_account,
     270              :                    ids->merchant_account);
     271           24 :   bd.receiver_wire_account = receiver_wire_account;
     272           24 :   TALER_full_payto_hash (bd.receiver_wire_account,
     273              :                          &bd.wire_target_h_payto);
     274           24 :   memset (&bd.wire_salt,
     275              :           46,
     276              :           sizeof (bd.wire_salt));
     277           24 :   bd.wallet_timestamp = GNUNET_TIME_timestamp_get ();
     278           24 :   bd.wire_deadline = GNUNET_TIME_relative_to_timestamp (
     279              :     ids->wire_deadline);
     280              :   /* finally, actually perform the DB operation */
     281              :   {
     282              :     uint64_t known_coin_id;
     283              :     struct TALER_DenominationHashP dph;
     284              :     struct TALER_AgeCommitmentHashP agh;
     285              :     bool balance_ok;
     286              :     uint32_t bad_index;
     287              :     bool ctr_conflict;
     288              : 
     289           24 :     if ( (GNUNET_OK !=
     290           24 :           ids->plugin->start (ids->plugin->cls,
     291           24 :                               "libtalertesting: insert deposit")) ||
     292              :          (0 >
     293           24 :           ids->plugin->ensure_coin_known (ids->plugin->cls,
     294              :                                           &deposit.coin,
     295              :                                           &known_coin_id,
     296              :                                           &dph,
     297           24 :                                           &agh)) ||
     298              :          (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     299           24 :           ids->plugin->do_deposit (ids->plugin->cls,
     300              :                                    &bd,
     301              :                                    &ids->exchange_timestamp,
     302              :                                    &balance_ok,
     303              :                                    &bad_index,
     304           24 :                                    &ctr_conflict)) ||
     305              :          (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     306           24 :           ids->plugin->commit (ids->plugin->cls)) )
     307              :     {
     308            0 :       GNUNET_break (0);
     309            0 :       ids->plugin->rollback (ids->plugin->cls);
     310            0 :       GNUNET_free (receiver_wire_account.full_payto);
     311            0 :       TALER_denom_pub_free (&dpk);
     312            0 :       TALER_denom_priv_free (&denom_priv);
     313            0 :       TALER_TESTING_interpreter_fail (is);
     314            0 :       return;
     315              :     }
     316              :   }
     317              : 
     318           24 :   TALER_denom_sig_free (&deposit.coin.denom_sig);
     319           24 :   TALER_denom_pub_free (&dpk);
     320           24 :   TALER_denom_priv_free (&denom_priv);
     321           24 :   GNUNET_free (receiver_wire_account.full_payto);
     322           24 :   TALER_TESTING_interpreter_next (is);
     323              : }
     324              : 
     325              : 
     326              : /**
     327              :  * Free the state of a "auditor-dbinit" CMD, and possibly kills its
     328              :  * process if it did not terminate correctly.
     329              :  *
     330              :  * @param cls closure.
     331              :  * @param cmd the command being freed.
     332              :  */
     333              : static void
     334           24 : insert_deposit_cleanup (void *cls,
     335              :                         const struct TALER_TESTING_Command *cmd)
     336              : {
     337           24 :   struct InsertDepositState *ids = cls;
     338              : 
     339              :   (void) cmd;
     340           24 :   if ( (NULL != ids->plugin) &&
     341           24 :        (! ids->cached) )
     342              :   {
     343              :     // FIXME: historically, we also did:
     344              :     // ids->plugin->drop_tables (ids->plugin->cls);
     345            1 :     TALER_EXCHANGEDB_plugin_unload (ids->plugin);
     346            1 :     ids->plugin = NULL;
     347              :   }
     348           24 :   GNUNET_free (ids);
     349           24 : }
     350              : 
     351              : 
     352              : struct TALER_TESTING_Command
     353           24 : TALER_TESTING_cmd_insert_deposit (
     354              :   const char *label,
     355              :   const struct GNUNET_CONFIGURATION_Handle *db_cfg,
     356              :   const char *merchant_name,
     357              :   const char *merchant_account,
     358              :   struct GNUNET_TIME_Timestamp exchange_timestamp,
     359              :   struct GNUNET_TIME_Relative wire_deadline,
     360              :   const char *amount_with_fee,
     361              :   const char *deposit_fee)
     362              : {
     363              :   static struct TALER_EXCHANGEDB_Plugin *pluginc;
     364              :   static const struct GNUNET_CONFIGURATION_Handle *db_cfgc;
     365              :   struct InsertDepositState *ids;
     366              : 
     367           24 :   ids = GNUNET_new (struct InsertDepositState);
     368           24 :   if (db_cfgc == db_cfg)
     369              :   {
     370           23 :     ids->plugin = pluginc;
     371           23 :     ids->cached = true;
     372              :   }
     373              :   else
     374              :   {
     375            1 :     ids->plugin = TALER_EXCHANGEDB_plugin_load (db_cfg,
     376              :                                                 false);
     377            1 :     pluginc = ids->plugin;
     378            1 :     db_cfgc = db_cfg;
     379              :   }
     380           24 :   ids->merchant_name = merchant_name;
     381           24 :   ids->merchant_account = merchant_account;
     382           24 :   ids->exchange_timestamp = exchange_timestamp;
     383           24 :   ids->wire_deadline = wire_deadline;
     384           24 :   ids->amount_with_fee = amount_with_fee;
     385           24 :   ids->deposit_fee = deposit_fee;
     386              : 
     387              :   {
     388           24 :     struct TALER_TESTING_Command cmd = {
     389              :       .cls = ids,
     390              :       .label = label,
     391              :       .run = &insert_deposit_run,
     392              :       .cleanup = &insert_deposit_cleanup
     393              :     };
     394              : 
     395           24 :     return cmd;
     396              :   }
     397              : }
     398              : 
     399              : 
     400              : /* end of testing_api_cmd_insert_deposit.c */
        

Generated by: LCOV version 2.0-1