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 */