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