donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

test_donaudb.c (14599B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2024 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file donaudb/test_donaudb.c
     18  * @brief test cases for DB interaction functions
     19  * @author Johannes Casaburi
     20  */
     21 #include "donau_config.h"
     22 #include <taler/taler_json_lib.h>
     23 #include "donaudb_lib.h"
     24 #include "donau_util.h"
     25 #include "donaudb_plugin.h"
     26 
     27 /**
     28  * Global result from the testcase.
     29  */
     30 static int result;
     31 
     32 /**
     33  * Report line of error if @a cond is true, and jump to label "drop".
     34  */
     35 #define FAILIF(cond)                              \
     36   do {                                          \
     37     if (! (cond)) { break;}                      \
     38     GNUNET_break (0);                           \
     39     goto drop;                                  \
     40   } while (0)
     41 
     42 
     43 /**
     44  * Initializes @a ptr with random data.
     45  */
     46 #define RND_BLK(ptr)                                                    \
     47   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (* \
     48                                                                        ptr))
     49 
     50 /**
     51  * Initializes @a ptr with zeros.
     52  */
     53 #define ZR_BLK(ptr) \
     54   memset (ptr, 0, sizeof (*ptr))
     55 
     56 /**
     57  * How big do we make the RSA keys?
     58  */
     59 #define RSA_KEY_SIZE 1024
     60 
     61 /**
     62  * Currency we use.  Must match test-donau-db-*.conf.
     63  */
     64 #define CURRENCY "EUR"
     65 
     66 /**
     67  * Database plugin under test.
     68  */
     69 static struct DONAUDB_Plugin *plugin;
     70 
     71 /**
     72  * Return charities information.
     73  *
     74  * @param cls closure
     75  */
     76 static enum GNUNET_GenericReturnValue
     77 charities_cb (
     78   void *cls,
     79   uint64_t charity_id,
     80   const struct DONAU_CharityPublicKeyP *charity_pub,
     81   const char *charity_name,
     82   const struct TALER_Amount *max_per_year,
     83   uint32_t current_year,
     84   const struct TALER_Amount *receipts_to_date)
     85 {
     86   (void) cls;
     87   (void) charity_id;
     88   (void) charity_name;
     89   (void) max_per_year;
     90   (void) current_year;
     91   (void) receipts_to_date;
     92   return GNUNET_OK;
     93 }
     94 
     95 
     96 /**
     97  * Function called with information about the donau's donation_unit keys.
     98  *
     99  * @param cls NULL
    100  * @param donation_unit_pub public key of the donation_unit
    101  * @param h_donation_unit_pub hash of @a donation_unit_pub
    102  * @param validity_year of the donation unit
    103  * @param value of the donation unit
    104  */
    105 static enum GNUNET_GenericReturnValue
    106 donation_unit_info_cb (
    107   void *cls,
    108   const struct DONAU_DonationUnitHashP *h_donation_unit_pub,
    109   const struct DONAU_DonationUnitPublicKey *donation_unit_pub,
    110   uint64_t validity_year,
    111   struct TALER_Amount *value)
    112 {
    113   (void) cls;
    114   (void) h_donation_unit_pub;
    115   (void) donation_unit_pub;
    116   (void) validity_year;
    117   (void) value;
    118   return GNUNET_OK;
    119 }
    120 
    121 
    122 /**
    123  * Function called with information about the donau's online signing keys.
    124  *
    125  * @param cls NULL
    126  * @param donau_pub the public key
    127  * @param meta meta data information about the denomination type (expirations)
    128  */
    129 static void
    130 iterate_active_signing_keys_cb (
    131   void *cls,
    132   const struct DONAU_DonauPublicKeyP *donau_pub,
    133   struct DONAUDB_SignkeyMetaData *meta)
    134 {
    135   (void) cls;
    136   (void) donau_pub;
    137   (void) meta;
    138 }
    139 
    140 
    141 /**
    142  * Main function that will be run by the scheduler.
    143  *
    144  * @param cls closure with config
    145  */
    146 static void
    147 run (void *cls)
    148 {
    149   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
    150   struct GNUNET_TIME_Timestamp now;
    151 
    152   // Charity information
    153   json_t *charities;
    154   struct DONAU_CharityPublicKeyP charity_pub;
    155   struct DONAUDB_CharityMetaData charity_meta;
    156   const char *charity_name;
    157   const char *charity_url;
    158   struct TALER_Amount max_per_year;
    159   struct TALER_Amount receipts_to_date;
    160   uint64_t charity_id;
    161 
    162   // Donation unit information
    163   struct DONAU_DonationUnitHashP h_donation_unit_pub;
    164   uint64_t validity_year;
    165   struct TALER_Amount du_value;
    166 
    167   // Signing key information
    168   struct DONAU_DonauPublicKeyP donau_pub;
    169   struct DONAUDB_SignkeyMetaData sk_meta;
    170 
    171   // Issued receipts information
    172   size_t num_b_sigs = 1;
    173   struct DONAU_BlindedDonationUnitSignature du_sigs[num_b_sigs];
    174   struct DONAU_DonationReceiptHashP h_receipt;
    175   struct TALER_Amount amount_receipts;
    176   bool smaller_than_max_per_year;
    177   struct TALER_DenominationPrivateKey denom_priv;
    178   struct TALER_DenominationPublicKey denom_pub;
    179   struct DONAU_DonationUnitPublicKey du_pub;
    180   struct GNUNET_CRYPTO_BlindedMessage *rp;
    181   struct GNUNET_CRYPTO_RsaBlindedMessage *rsa;
    182 
    183   if (NULL ==
    184       (plugin = DONAUDB_plugin_load (cfg)))
    185   {
    186     fprintf (stderr,
    187              "Failed to load DB plugin\n");
    188     result = 77;
    189     return;
    190   }
    191   (void) plugin->drop_tables (plugin->cls);
    192   if (GNUNET_OK !=
    193       plugin->create_tables (plugin->cls))
    194   {
    195     fprintf (stderr,
    196              "Failed to create DB tables\n");
    197     result = 77;
    198     goto cleanup;
    199   }
    200   plugin->preflight (plugin->cls);
    201   FAILIF (GNUNET_OK !=
    202           plugin->start (plugin->cls,
    203                          "test-1"));
    204 
    205   fprintf (stderr,
    206            "Running DB tests\n");
    207 
    208   /* test DB is empty */
    209   charity_id = 1;
    210   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    211           plugin->lookup_charity (plugin->cls,
    212                                   charity_id,
    213                                   &charity_meta));
    214 
    215   /* test insert charity */
    216   charity_name = "charity_name";
    217   charity_url = "charity_url";
    218   charities = json_array ();
    219   RND_BLK (&charity_pub);
    220   GNUNET_assert (GNUNET_OK ==
    221                  TALER_string_to_amount (CURRENCY ":1.000010",
    222                                          &max_per_year));
    223   GNUNET_assert (GNUNET_OK ==
    224                  TALER_string_to_amount (CURRENCY ":0.000010",
    225                                          &receipts_to_date));
    226 
    227   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    228           plugin->insert_charity (plugin->cls,
    229                                   &charity_pub,
    230                                   charity_name,
    231                                   charity_url,
    232                                   &max_per_year,
    233                                   &charity_id));
    234 
    235   /* test get charities */
    236   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    237           plugin->get_charities (plugin->cls,
    238                                  &charities_cb,
    239                                  charities));
    240 
    241   {
    242     /* Update the charity and verify the new key and metadata persist. */
    243     const char *updated_charity_name = "charity_name_updated";
    244     const char *updated_charity_url = "charity_url_updated";
    245     struct TALER_Amount updated_max;
    246     struct DONAU_CharityPrivateKeyP updated_charity_priv;
    247     struct DONAU_CharityPublicKeyP updated_charity_pub;
    248 
    249     GNUNET_CRYPTO_eddsa_key_create (&updated_charity_priv.eddsa_priv);
    250     GNUNET_CRYPTO_eddsa_key_get_public (&updated_charity_priv.eddsa_priv,
    251                                         &updated_charity_pub.eddsa_pub);
    252 
    253     GNUNET_assert (GNUNET_OK ==
    254                    TALER_string_to_amount (CURRENCY ":2.000000",
    255                                            &updated_max));
    256     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    257             plugin->update_charity (plugin->cls,
    258                                     charity_id,
    259                                     &updated_charity_pub,
    260                                     updated_charity_name,
    261                                     updated_charity_url,
    262                                     &updated_max));
    263 
    264     ZR_BLK (&charity_meta);
    265     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    266             plugin->lookup_charity (plugin->cls,
    267                                     charity_id,
    268                                     &charity_meta));
    269     GNUNET_assert (0 == GNUNET_memcmp (&charity_meta.charity_pub,
    270                                        &updated_charity_pub));
    271     GNUNET_assert (0 == strcmp (charity_meta.charity_name,
    272                                 updated_charity_name));
    273     GNUNET_assert (0 == strcmp (charity_meta.charity_url,
    274                                 updated_charity_url));
    275     GNUNET_assert (0 == TALER_amount_cmp (&charity_meta.max_per_year,
    276                                           &updated_max));
    277     GNUNET_free (charity_meta.charity_name);
    278     GNUNET_free (charity_meta.charity_url);
    279 
    280     charity_name = updated_charity_name;
    281     charity_url = updated_charity_url;
    282     max_per_year = updated_max;
    283     charity_pub = updated_charity_pub;
    284   }
    285 
    286   /* test delete charity */
    287   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    288           plugin->do_charity_delete (plugin->cls,
    289                                      charity_id));
    290 
    291   /* test insert donation unit */
    292   RND_BLK (&h_donation_unit_pub);
    293   GNUNET_assert (GNUNET_OK ==
    294                  TALER_denom_priv_create (&denom_priv,
    295                                           &denom_pub,
    296                                           GNUNET_CRYPTO_BSA_RSA,
    297                                           RSA_KEY_SIZE));
    298   du_pub.bsign_pub_key = denom_pub.bsign_pub_key;
    299   validity_year = 2024;
    300   GNUNET_assert (GNUNET_OK ==
    301                  TALER_string_to_amount (CURRENCY ":1.000010",
    302                                          &du_value));
    303 
    304   /* test iterate donation units */
    305   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    306           plugin->iterate_donation_units (plugin->cls,
    307                                           &donation_unit_info_cb,
    308                                           NULL));
    309 
    310   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    311           plugin->insert_donation_unit (plugin->cls,
    312                                         &h_donation_unit_pub,
    313                                         &du_pub,
    314                                         validity_year,
    315                                         &du_value));
    316 
    317   /* test iterate donation units */
    318   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    319           plugin->iterate_donation_units (plugin->cls,
    320                                           &donation_unit_info_cb,
    321                                           NULL));
    322 
    323   TALER_denom_pub_free (&denom_pub);
    324 
    325   /* test insert signing key */
    326   RND_BLK (&donau_pub);
    327   now = GNUNET_TIME_timestamp_get ();
    328   sk_meta.expire_legal = now;
    329   sk_meta.expire_sign = now;
    330   sk_meta.valid_from = now;
    331 
    332   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    333           plugin->insert_signing_key (plugin->cls,
    334                                       &donau_pub,
    335                                       &sk_meta));
    336 
    337   /* test iterate signing key */
    338   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    339           plugin->iterate_active_signing_keys (plugin->cls,
    340                                                &iterate_active_signing_keys_cb,
    341                                                NULL));
    342 
    343   /* test insert issued receipt */
    344   rp = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage);
    345   rp->cipher = GNUNET_CRYPTO_BSA_RSA;
    346   rp->rc = 1;
    347   rsa = &rp->details.rsa_blinded_message;
    348   rsa->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
    349     GNUNET_CRYPTO_QUALITY_WEAK,
    350     (RSA_KEY_SIZE / 8) - 1);
    351   rsa->blinded_msg = GNUNET_malloc (rsa->blinded_msg_size);
    352   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
    353                               rsa->blinded_msg,
    354                               rsa->blinded_msg_size);
    355   smaller_than_max_per_year = false;
    356   GNUNET_assert (GNUNET_OK ==
    357                  TALER_string_to_amount (CURRENCY ":1.000010",
    358                                          &amount_receipts));
    359 
    360   du_sigs[0].blinded_sig =
    361     GNUNET_CRYPTO_blind_sign (denom_priv.bsign_priv_key,
    362                               "rw",
    363                               rp);
    364 
    365   GNUNET_assert (NULL != du_sigs[0].blinded_sig);
    366   TALER_denom_priv_free (&denom_priv);
    367 
    368   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    369           plugin->insert_issued_receipt (plugin->cls,
    370                                          num_b_sigs,
    371                                          du_sigs,
    372                                          charity_id,
    373                                          &h_receipt,
    374                                          &amount_receipts,
    375                                          &smaller_than_max_per_year));
    376 
    377   // FIXME
    378   // FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    379   //         plugin->lookup_issued_receipts (plugin->cls,
    380   //                                         &h_receipt,
    381   //                                         &ir_meta));
    382 
    383   /* test insert submitted receipts */
    384   // RND_BLK (&h_donor_tax_id);
    385   // RND_BLK (&donation_receipts[0].h_donation_unit_pub);
    386   // RND_BLK (&donation_receipts[0].nonce);
    387   // RND_BLK (&donation_receipts[0].donation_unit_sig);
    388   // FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    389   //         plugin->insert_submitted_receipts (plugin->cls,
    390   //                                            &h_donor_tax_id,
    391   //                                            num_dr,
    392   //                                            donation_receipts,
    393   //                                            current_year));
    394 
    395   plugin->preflight (plugin->cls);
    396 
    397   result = 0;
    398 
    399 drop:
    400   if (0 != result)
    401     plugin->rollback (plugin->cls);
    402   GNUNET_break (GNUNET_OK ==
    403                 plugin->drop_tables (plugin->cls));
    404 cleanup:
    405   DONAUDB_plugin_unload (plugin);
    406   plugin = NULL;
    407 }
    408 
    409 
    410 int
    411 main (int argc,
    412       char *const argv[])
    413 {
    414   const char *plugin_name;
    415   char *config_filename;
    416   char *testname;
    417   struct GNUNET_CONFIGURATION_Handle *cfg;
    418 
    419   (void) argc;
    420   result = -1;
    421   if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
    422   {
    423     GNUNET_break (0);
    424     return -1;
    425   }
    426   GNUNET_log_setup (argv[0],
    427                     "WARNING",
    428                     NULL);
    429   plugin_name++;
    430   (void) GNUNET_asprintf (&testname,
    431                           "test-donau-db-%s",
    432                           plugin_name);
    433   (void) GNUNET_asprintf (&config_filename,
    434                           "%s.conf",
    435                           testname);
    436   cfg = GNUNET_CONFIGURATION_create (DONAU_project_data ());
    437   if (GNUNET_OK !=
    438       GNUNET_CONFIGURATION_parse (cfg,
    439                                   config_filename))
    440   {
    441     GNUNET_break (0);
    442     GNUNET_free (config_filename);
    443     GNUNET_free (testname);
    444     return 2;
    445   }
    446   GNUNET_SCHEDULER_run (&run,
    447                         cfg);
    448   GNUNET_CONFIGURATION_destroy (cfg);
    449   GNUNET_free (config_filename);
    450   GNUNET_free (testname);
    451   return result;
    452 }
    453 
    454 
    455 /* end of test_donaudb.c */