report-lib.c (25670B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2016-2020 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero 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 Affero Public License for more details. 12 13 You should have received a copy of the GNU Affero Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file auditor/report-lib.c 18 * @brief helper library to facilitate generation of audit reports 19 * @author Christian Grothoff 20 */ 21 #include "platform.h" 22 #include "report-lib.h" 23 #include "auditor-database/preflight.h" 24 #include "auditor-database/start.h" 25 #include "exchange-database/commit.h" 26 #include "exchange-database/get_denomination_by_serial.h" 27 #include "exchange-database/get_denomination_info.h" 28 #include "exchange-database/iterate_denomination_info.h" 29 #include "exchange-database/preflight.h" 30 #include "exchange-database/rollback.h" 31 #include "exchange-database/start.h" 32 33 /** 34 * Handle to access the exchange's database. 35 */ 36 struct TALER_EXCHANGEDB_PostgresContext *TALER_ARL_edb; 37 38 /** 39 * Which currency are we doing the audit for? 40 */ 41 char *TALER_ARL_currency; 42 43 /** 44 * How many fractional digits does the currency use? 45 */ 46 struct TALER_Amount TALER_ARL_currency_round_unit; 47 48 /** 49 * Our configuration. 50 */ 51 const struct GNUNET_CONFIGURATION_Handle *TALER_ARL_cfg; 52 53 /** 54 * Handle to access the auditor's database. 55 */ 56 struct TALER_AUDITORDB_PostgresContext *TALER_ARL_adb; 57 58 /** 59 * Master public key of the exchange to audit. 60 */ 61 struct TALER_MasterPublicKeyP TALER_ARL_master_pub; 62 63 /** 64 * Public key of the auditor. 65 */ 66 struct TALER_AuditorPublicKeyP TALER_ARL_auditor_pub; 67 68 /** 69 * REST API endpoint of the auditor. 70 */ 71 char *TALER_ARL_auditor_url; 72 73 /** 74 * REST API endpoint of the exchange. 75 */ 76 char *TALER_ARL_exchange_url; 77 78 /** 79 * At what time did the auditor process start? 80 */ 81 struct GNUNET_TIME_Absolute start_time; 82 83 /** 84 * Results about denominations, cached per-transaction, maps denomination pub hashes 85 * to `const struct TALER_EXCHANGEDB_DenominationKeyInformation`. 86 */ 87 static struct GNUNET_CONTAINER_MultiHashMap *denominations; 88 89 /** 90 * Results about denominations, cached per-transaction, maps row/serial ID's 91 * to `const struct TALER_EXCHANGEDB_DenominationKeyInformation`. 92 */ 93 static struct GNUNET_CONTAINER_MultiUuidmap *denominations_by_serial; 94 95 /** 96 * Helper to convert a serial/row id to a uuid for the lookup 97 * in a uuid hash table. 98 * 99 * @param serial serial id of entry 100 * @param[out] uuid uuid to write 101 */ 102 static void 103 serial_to_uuid ( 104 uint64_t serial, 105 struct GNUNET_Uuid *uuid) 106 { 107 uuid->value[0] = serial; 108 uuid->value[1] = serial >> 32; 109 uuid->value[2] = 0; 110 uuid->value[3] = 0; 111 } 112 113 114 /** 115 * Function called with the results of iterate_denomination_info(), 116 * or directly (!). Used to check and add the respective denomination 117 * to our hash table. 118 * 119 * @param cls closure, NULL 120 * @param denom_serial table row of the denomaination 121 * @param denom_pub public key, sometimes NULL (!) 122 * @param issue issuing information with value, fees and other info about the denomination. 123 */ 124 static void 125 add_denomination ( 126 void *cls, 127 uint64_t denom_serial, 128 const struct TALER_DenominationPublicKey *denom_pub, 129 const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue) 130 { 131 (void) cls; 132 (void) denom_pub; 133 if (NULL != 134 GNUNET_CONTAINER_multihashmap_get (denominations, 135 &issue->denom_hash.hash)) 136 return; /* value already known */ 137 #if GNUNET_EXTRA_LOGGING >= 1 138 { 139 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 140 "Tracking denomination `%s' (%s)\n", 141 GNUNET_h2s (&issue->denom_hash.hash), 142 TALER_amount2s (&issue->value)); 143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 144 "Withdraw fee is %s\n", 145 TALER_amount2s (&issue->fees.withdraw)); 146 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 147 "Start time is %s\n", 148 GNUNET_TIME_timestamp2s (issue->start)); 149 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 150 "Expire deposit time is %s\n", 151 GNUNET_TIME_timestamp2s (issue->expire_deposit)); 152 } 153 #endif 154 { 155 struct TALER_EXCHANGEDB_DenominationKeyInformation *i; 156 struct GNUNET_Uuid uuid; 157 158 i = GNUNET_new (struct TALER_EXCHANGEDB_DenominationKeyInformation); 159 *i = *issue; 160 GNUNET_assert (GNUNET_OK == 161 GNUNET_CONTAINER_multihashmap_put (denominations, 162 &issue->denom_hash.hash, 163 i, 164 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 165 serial_to_uuid (denom_serial, &uuid); 166 GNUNET_assert (GNUNET_OK == 167 GNUNET_CONTAINER_multiuuidmap_put (denominations_by_serial, 168 &uuid, 169 i, 170 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 171 } 172 } 173 174 175 enum GNUNET_DB_QueryStatus 176 TALER_ARL_get_denomination_info_by_hash ( 177 const struct TALER_DenominationHashP *dh, 178 const struct TALER_EXCHANGEDB_DenominationKeyInformation **issuep) 179 { 180 enum GNUNET_DB_QueryStatus qs; 181 182 *issuep = NULL; 183 if (NULL == denominations) 184 { 185 denominations = GNUNET_CONTAINER_multihashmap_create (256, 186 GNUNET_NO); 187 if (NULL == denominations_by_serial) 188 denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256, 189 GNUNET_NO) 190 ; 191 192 qs = TALER_EXCHANGEDB_iterate_denomination_info (TALER_ARL_edb, 193 &add_denomination, 194 NULL); 195 if (0 > qs) 196 { 197 GNUNET_break (0); 198 *issuep = NULL; 199 return qs; 200 } 201 } 202 { 203 const struct TALER_EXCHANGEDB_DenominationKeyInformation *i; 204 205 i = GNUNET_CONTAINER_multihashmap_get (denominations, 206 &dh->hash); 207 if (NULL != i) 208 { 209 /* cache hit */ 210 *issuep = i; 211 return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; 212 } 213 } 214 /* maybe database changed since we last iterated, give it one more shot */ 215 { 216 struct TALER_EXCHANGEDB_DenominationKeyInformation issue; 217 uint64_t denom_serial; 218 219 qs = TALER_EXCHANGEDB_get_denomination_info (TALER_ARL_edb, 220 dh, 221 &denom_serial, 222 &issue); 223 if (qs <= 0) 224 { 225 GNUNET_break (qs >= 0); 226 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 227 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 228 "Denomination %s not found\n", 229 TALER_B2S (dh)); 230 return qs; 231 } 232 233 add_denomination (NULL, 234 denom_serial, 235 NULL, 236 &issue); 237 } 238 { 239 const struct TALER_EXCHANGEDB_DenominationKeyInformation *i; 240 241 i = GNUNET_CONTAINER_multihashmap_get (denominations, 242 &dh->hash); 243 if (NULL != i) 244 { 245 /* cache hit */ 246 *issuep = i; 247 return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; 248 } 249 } 250 /* We found more keys, but not the denomination we are looking for :-( */ 251 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 252 "Denomination %s not found\n", 253 TALER_B2S (dh)); 254 return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; 255 } 256 257 258 enum GNUNET_DB_QueryStatus 259 TALER_ARL_get_denomination_info_by_serial ( 260 uint64_t denom_serial, 261 const struct TALER_EXCHANGEDB_DenominationKeyInformation **issuep) 262 { 263 enum GNUNET_DB_QueryStatus qs; 264 struct GNUNET_Uuid uuid; 265 266 *issuep = NULL; 267 serial_to_uuid (denom_serial, 268 &uuid); 269 if (NULL == denominations_by_serial) 270 { 271 denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256, 272 GNUNET_NO); 273 if (NULL == denominations) 274 denominations = GNUNET_CONTAINER_multihashmap_create (256, 275 GNUNET_NO); 276 277 qs = TALER_EXCHANGEDB_iterate_denomination_info (TALER_ARL_edb, 278 &add_denomination, 279 NULL); 280 if (0 > qs) 281 { 282 GNUNET_break (0); 283 *issuep = NULL; 284 return qs; 285 } 286 } 287 { 288 const struct TALER_EXCHANGEDB_DenominationKeyInformation *i; 289 290 i = GNUNET_CONTAINER_multiuuidmap_get (denominations_by_serial, 291 &uuid); 292 if (NULL != i) 293 { 294 /* cache hit */ 295 *issuep = i; 296 return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; 297 } 298 } 299 /* maybe database changed since we last iterated, give it one more shot */ 300 { 301 struct TALER_EXCHANGEDB_DenominationKeyInformation issue; 302 303 qs = TALER_EXCHANGEDB_get_denomination_by_serial (TALER_ARL_edb, 304 denom_serial, 305 &issue); 306 if (qs <= 0) 307 { 308 GNUNET_break (qs >= 0); 309 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 310 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 311 "Denomination with serial %lu not found\n", 312 denom_serial); 313 return qs; 314 } 315 316 add_denomination (NULL, 317 denom_serial, 318 NULL, 319 &issue); 320 } 321 322 { 323 const struct TALER_EXCHANGEDB_DenominationKeyInformation *i; 324 325 i = GNUNET_CONTAINER_multiuuidmap_get (denominations_by_serial, 326 &uuid); 327 if (NULL != i) 328 { 329 /* cache hit */ 330 *issuep = i; 331 return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; 332 } 333 } 334 /* We found more keys, but not the denomination we are looking for :-( */ 335 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 336 "Denomination with serial %lu not found\n", 337 denom_serial); 338 return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; 339 } 340 341 342 enum GNUNET_DB_QueryStatus 343 TALER_ARL_get_denomination_info ( 344 const struct TALER_DenominationPublicKey *denom_pub, 345 const struct TALER_EXCHANGEDB_DenominationKeyInformation **issue, 346 struct TALER_DenominationHashP *dh) 347 { 348 struct TALER_DenominationHashP hc; 349 350 if (NULL == dh) 351 dh = &hc; 352 TALER_denom_pub_hash (denom_pub, 353 dh); 354 return TALER_ARL_get_denomination_info_by_hash (dh, 355 issue); 356 } 357 358 359 /** 360 * Perform the given @a analysis within a transaction scope. 361 * Commit on success. 362 * 363 * @param analysis analysis to run 364 * @param analysis_cls closure for @a analysis 365 * @return #GNUNET_OK if @a analysis successfully committed, 366 * #GNUNET_NO if we had an error on commit (retry may help) 367 * #GNUNET_SYSERR on hard errors 368 */ 369 static enum GNUNET_GenericReturnValue 370 transact (TALER_ARL_Analysis analysis, 371 void *analysis_cls) 372 { 373 int ret; 374 enum GNUNET_DB_QueryStatus qs; 375 376 ret = TALER_AUDITORDB_start (TALER_ARL_adb, 377 "auditor-analysis"); 378 if (GNUNET_OK != ret) 379 { 380 GNUNET_break (0); 381 return GNUNET_SYSERR; 382 } 383 if (GNUNET_OK != 384 TALER_EXCHANGEDB_preflight (TALER_ARL_edb)) 385 { 386 GNUNET_break (0); 387 return GNUNET_SYSERR; 388 } 389 ret = TALER_EXCHANGEDB_start (TALER_ARL_edb, 390 "auditor"); 391 if (GNUNET_OK != ret) 392 { 393 GNUNET_break (0); 394 TALER_EXCHANGEDB_rollback (TALER_ARL_edb); 395 return GNUNET_SYSERR; 396 } 397 qs = analysis (analysis_cls); 398 if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) 399 { 400 qs = TALER_EXCHANGEDB_commit (TALER_ARL_edb); 401 if (0 > qs) 402 { 403 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); 404 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 405 "Exchange DB commit failed, rolling back transaction\n"); 406 TALER_AUDITORDB_rollback (TALER_ARL_adb); 407 } 408 else 409 { 410 qs = TALER_AUDITORDB_commit (TALER_ARL_adb); 411 if (0 > qs) 412 { 413 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); 414 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 415 "Auditor DB commit failed!\n"); 416 } 417 } 418 } 419 else 420 { 421 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 422 "Processing failed; rolling back transaction\n"); 423 TALER_AUDITORDB_rollback (TALER_ARL_adb); 424 TALER_EXCHANGEDB_rollback (TALER_ARL_edb); 425 } 426 switch (qs) 427 { 428 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 429 return GNUNET_OK; 430 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 431 return GNUNET_OK; 432 case GNUNET_DB_STATUS_SOFT_ERROR: 433 return GNUNET_NO; 434 case GNUNET_DB_STATUS_HARD_ERROR: 435 return GNUNET_SYSERR; 436 } 437 return GNUNET_OK; 438 } 439 440 441 enum GNUNET_GenericReturnValue 442 TALER_ARL_setup_sessions_and_run (TALER_ARL_Analysis ana, 443 void *ana_cls) 444 { 445 enum GNUNET_GenericReturnValue ret; 446 447 if (GNUNET_SYSERR == 448 TALER_EXCHANGEDB_preflight (TALER_ARL_edb)) 449 { 450 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 451 "Failed to initialize exchange connection.\n"); 452 return GNUNET_SYSERR; 453 } 454 if (GNUNET_SYSERR == 455 TALER_AUDITORDB_preflight (TALER_ARL_adb)) 456 { 457 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 458 "Failed to initialize auditor session.\n"); 459 return GNUNET_SYSERR; 460 } 461 462 for (unsigned int retries = 0; retries<3; retries++) 463 { 464 ret = transact (ana, 465 ana_cls); 466 if (GNUNET_NO != ret) 467 break; 468 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 469 "Serialization issue, trying again\n"); 470 } 471 if (GNUNET_OK != ret) 472 { 473 /* Includes the retries running out: the analysis was rolled back every 474 time, so there is nothing committed to report success about. */ 475 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 476 "Analysis failed, not recording progress\n"); 477 return GNUNET_SYSERR; 478 } 479 return GNUNET_OK; 480 } 481 482 483 void 484 TALER_ARL_amount_add_ (struct TALER_Amount *sum, 485 const struct TALER_Amount *a1, 486 const struct TALER_Amount *a2, 487 const char *filename, 488 const char *functionname, 489 unsigned int line) 490 { 491 enum TALER_AmountArithmeticResult aar; 492 const char *msg; 493 char *a2s; 494 495 aar = TALER_amount_add (sum, 496 a1, 497 a2); 498 if (aar >= 0) 499 return; 500 switch (aar) 501 { 502 case TALER_AAR_INVALID_RESULT_OVERFLOW: 503 msg = 504 "arithmetic overflow in amount addition (likely the database is corrupt, see manual)"; 505 break; 506 case TALER_AAR_INVALID_NORMALIZATION_FAILED: 507 msg = 508 "normalization failed in amount addition (likely the database is corrupt, see manual)"; 509 break; 510 case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE: 511 msg = 512 "incompatible currencies in amount addition (likely bad configuration and auditor code missing a sanity check, see manual)"; 513 break; 514 default: 515 GNUNET_assert (0); /* should be impossible */ 516 } 517 a2s = TALER_amount_to_string (a2); 518 fprintf (stderr, 519 "Aborting audit due to fatal error in function %s at %s:%d trying to add %s to %s: %s\n", 520 functionname, 521 filename, 522 line, 523 TALER_amount2s (a1), 524 a2s, 525 msg); 526 GNUNET_free (a2s); 527 exit (42); 528 } 529 530 531 void 532 TALER_ARL_amount_subtract_ (struct TALER_Amount *diff, 533 const struct TALER_Amount *a1, 534 const struct TALER_Amount *a2, 535 const char *filename, 536 const char *functionname, 537 unsigned int line) 538 { 539 enum TALER_AmountArithmeticResult aar; 540 const char *msg; 541 char *a2s; 542 543 aar = TALER_amount_subtract (diff, 544 a1, 545 a2); 546 if (aar >= 0) 547 return; 548 switch (aar) 549 { 550 case TALER_AAR_INVALID_NEGATIVE_RESULT: 551 msg = 552 "negative result in amount subtraction (likely the database is corrupt, see manual)"; 553 break; 554 case TALER_AAR_INVALID_NORMALIZATION_FAILED: 555 msg = 556 "normalization failed in amount subtraction (likely the database is corrupt, see manual)"; 557 break; 558 case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE: 559 msg = 560 "currencies incompatible in amount subtraction (likely bad configuration and auditor code missing a sanity check, see manual)"; 561 break; 562 default: 563 GNUNET_assert (0); /* should be impossible */ 564 } 565 a2s = TALER_amount_to_string (a2); 566 fprintf (stderr, 567 "Aborting audit due to fatal error in function %s at %s:%d trying to subtract %s from %s: %s\n", 568 functionname, 569 filename, 570 line, 571 a2s, 572 TALER_amount2s (a1), 573 msg); 574 GNUNET_free (a2s); 575 exit (42); 576 } 577 578 579 enum TALER_ARL_SubtractionResult 580 TALER_ARL_amount_subtract_neg_ (struct TALER_Amount *diff, 581 const struct TALER_Amount *a1, 582 const struct TALER_Amount *a2, 583 const char *filename, 584 const char *functionname, 585 unsigned int line) 586 { 587 enum TALER_AmountArithmeticResult aar; 588 const char *msg; 589 char *a2s; 590 591 aar = TALER_amount_subtract (diff, 592 a1, 593 a2); 594 switch (aar) 595 { 596 case TALER_AAR_RESULT_POSITIVE: 597 return TALER_ARL_SR_POSITIVE; 598 case TALER_AAR_RESULT_ZERO: 599 return TALER_ARL_SR_ZERO; 600 case TALER_AAR_INVALID_NEGATIVE_RESULT: 601 return TALER_ARL_SR_INVALID_NEGATIVE; 602 case TALER_AAR_INVALID_NORMALIZATION_FAILED: 603 msg = 604 "normalization failed in amount subtraction (likely the database is corrupt, see manual)"; 605 break; 606 case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE: 607 msg = 608 "currencies incompatible in amount subtraction (likely bad configuration and auditor code missing a sanity check, see manual)"; 609 break; 610 default: 611 GNUNET_assert (0); /* should be impossible */ 612 } 613 a2s = TALER_amount_to_string (a2); 614 fprintf (stderr, 615 "Aborting audit due to fatal error in function %s at %s:%d trying to subtract %s from %s: %s\n", 616 functionname, 617 filename, 618 line, 619 a2s, 620 TALER_amount2s (a1), 621 msg); 622 GNUNET_free (a2s); 623 exit (42); 624 } 625 626 627 int 628 TALER_ARL_init (const struct GNUNET_CONFIGURATION_Handle *c) 629 { 630 TALER_ARL_cfg = c; 631 start_time = GNUNET_TIME_absolute_get (); 632 633 if (GNUNET_OK != 634 GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg, 635 "auditor", 636 "BASE_URL", 637 &TALER_ARL_auditor_url)) 638 { 639 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 640 "auditor", 641 "BASE_URL"); 642 return EXIT_NOTCONFIGURED; 643 } 644 if (GNUNET_OK != 645 GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg, 646 "exchange", 647 "BASE_URL", 648 &TALER_ARL_exchange_url)) 649 { 650 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 651 "exchange", 652 "BASE_URL"); 653 return EXIT_NOTCONFIGURED; 654 } 655 656 if (GNUNET_is_zero (&TALER_ARL_master_pub)) 657 { 658 /* -m option not given, try configuration */ 659 char *master_public_key_str; 660 661 if (GNUNET_OK != 662 GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg, 663 "exchange", 664 "MASTER_PUBLIC_KEY", 665 &master_public_key_str)) 666 { 667 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 668 "Pass option -m or set MASTER_PUBLIC_KEY in the configuration!\n"); 669 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 670 "exchange", 671 "MASTER_PUBLIC_KEY"); 672 return EXIT_NOTCONFIGURED; 673 } 674 if (GNUNET_OK != 675 GNUNET_CRYPTO_eddsa_public_key_from_string ( 676 master_public_key_str, 677 strlen (master_public_key_str), 678 &TALER_ARL_master_pub.eddsa_pub)) 679 { 680 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 681 "exchange", 682 "MASTER_PUBLIC_KEY", 683 "invalid key"); 684 GNUNET_free (master_public_key_str); 685 return EXIT_NOTCONFIGURED; 686 } 687 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 688 "Running auditor against exchange master public key `%s'\n", 689 master_public_key_str); 690 GNUNET_free (master_public_key_str); 691 } /* end of -m not given */ 692 693 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 694 "Taler auditor running for exchange master public key %s\n", 695 TALER_B2S (&TALER_ARL_master_pub)); 696 697 if (GNUNET_is_zero (&TALER_ARL_auditor_pub)) 698 { 699 char *auditor_public_key_str; 700 701 if (GNUNET_OK == 702 GNUNET_CONFIGURATION_get_value_string (c, 703 "auditor", 704 "PUBLIC_KEY", 705 &auditor_public_key_str)) 706 { 707 if (GNUNET_OK != 708 GNUNET_CRYPTO_eddsa_public_key_from_string ( 709 auditor_public_key_str, 710 strlen (auditor_public_key_str), 711 &TALER_ARL_auditor_pub.eddsa_pub)) 712 { 713 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 714 "auditor", 715 "PUBLIC_KEY", 716 "invalid key"); 717 GNUNET_free (auditor_public_key_str); 718 return EXIT_NOTCONFIGURED; 719 } 720 GNUNET_free (auditor_public_key_str); 721 } 722 } 723 724 if (GNUNET_is_zero (&TALER_ARL_auditor_pub)) 725 { 726 /* public key not configured */ 727 /* try loading private key and deriving public key */ 728 char *fn; 729 730 if (GNUNET_OK == 731 GNUNET_CONFIGURATION_get_value_filename (c, 732 "auditor", 733 "AUDITOR_PRIV_FILE", 734 &fn)) 735 { 736 struct TALER_AuditorPrivateKeyP auditor_priv; 737 738 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 739 "Loading offline private key from `%s' to get auditor public key\n", 740 fn); 741 if (GNUNET_OK == 742 GNUNET_CRYPTO_eddsa_key_from_file (fn, 743 GNUNET_NO, /* do NOT create it! */ 744 &auditor_priv.eddsa_priv)) 745 { 746 GNUNET_CRYPTO_eddsa_key_get_public (&auditor_priv.eddsa_priv, 747 &TALER_ARL_auditor_pub.eddsa_pub); 748 } 749 GNUNET_free (fn); 750 } 751 } 752 753 if (GNUNET_is_zero (&TALER_ARL_auditor_pub)) 754 { 755 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 756 "auditor", 757 "PUBLIC_KEY/AUDITOR_PRIV_FILE"); 758 return EXIT_NOTCONFIGURED; 759 } 760 761 if (GNUNET_OK != 762 TALER_config_get_currency (TALER_ARL_cfg, 763 "exchange", 764 &TALER_ARL_currency)) 765 { 766 return EXIT_NOTCONFIGURED; 767 } 768 { 769 if ( (GNUNET_OK != 770 TALER_config_get_amount (TALER_ARL_cfg, 771 "exchange", 772 "CURRENCY_ROUND_UNIT", 773 &TALER_ARL_currency_round_unit)) || 774 ( (0 != TALER_ARL_currency_round_unit.fraction) && 775 (0 != TALER_ARL_currency_round_unit.value) ) ) 776 { 777 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 778 "Need non-zero value in section `exchange' under `CURRENCY_ROUND_UNIT'\n"); 779 return EXIT_NOTCONFIGURED; 780 } 781 } 782 if (NULL == 783 (TALER_ARL_edb = TALER_EXCHANGEDB_connect (TALER_ARL_cfg))) 784 { 785 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 786 "Failed to initialize exchange database plugin.\n"); 787 TALER_ARL_done (); 788 return EXIT_FAILURE; 789 } 790 if (NULL == 791 (TALER_ARL_adb = TALER_AUDITORDB_connect (TALER_ARL_cfg))) 792 { 793 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 794 "Failed to initialize auditor database plugin.\n"); 795 TALER_ARL_done (); 796 return EXIT_FAILURE; 797 } 798 if (GNUNET_SYSERR == 799 TALER_AUDITORDB_preflight (TALER_ARL_adb)) 800 { 801 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 802 "Failed to start session with auditor database.\n"); 803 TALER_ARL_done (); 804 return EXIT_FAILURE; 805 } 806 return EXIT_SUCCESS; 807 } 808 809 810 void 811 TALER_ARL_done () 812 { 813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 814 "Audit complete\n"); 815 if (NULL != TALER_ARL_adb) 816 { 817 TALER_AUDITORDB_disconnect (TALER_ARL_adb); 818 TALER_ARL_adb = NULL; 819 } 820 if (NULL != TALER_ARL_edb) 821 { 822 TALER_EXCHANGEDB_disconnect (TALER_ARL_edb); 823 TALER_ARL_edb = NULL; 824 } 825 GNUNET_free (TALER_ARL_exchange_url); 826 GNUNET_free (TALER_ARL_auditor_url); 827 } 828 829 830 /* end of report-lib.c */