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