report-lib.c (25243B)
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 if (NULL == denominations) 182 { 183 denominations = GNUNET_CONTAINER_multihashmap_create (256, 184 GNUNET_NO); 185 if (NULL == denominations_by_serial) 186 denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256, 187 GNUNET_NO) 188 ; 189 190 qs = TALER_EXCHANGEDB_iterate_denomination_info (TALER_ARL_edb, 191 &add_denomination, 192 NULL); 193 if (0 > qs) 194 { 195 GNUNET_break (0); 196 *issuep = NULL; 197 return qs; 198 } 199 } 200 { 201 const struct TALER_EXCHANGEDB_DenominationKeyInformation *i; 202 203 i = GNUNET_CONTAINER_multihashmap_get (denominations, 204 &dh->hash); 205 if (NULL != i) 206 { 207 /* cache hit */ 208 *issuep = i; 209 return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; 210 } 211 } 212 /* maybe database changed since we last iterated, give it one more shot */ 213 { 214 struct TALER_EXCHANGEDB_DenominationKeyInformation issue; 215 uint64_t denom_serial; 216 217 qs = TALER_EXCHANGEDB_get_denomination_info (TALER_ARL_edb, 218 dh, 219 &denom_serial, 220 &issue); 221 if (qs <= 0) 222 { 223 GNUNET_break (qs >= 0); 224 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 225 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 226 "Denomination %s not found\n", 227 TALER_B2S (dh)); 228 return qs; 229 } 230 231 add_denomination (NULL, 232 denom_serial, 233 NULL, 234 &issue); 235 } 236 { 237 const struct TALER_EXCHANGEDB_DenominationKeyInformation *i; 238 239 i = GNUNET_CONTAINER_multihashmap_get (denominations, 240 &dh->hash); 241 if (NULL != i) 242 { 243 /* cache hit */ 244 *issuep = i; 245 return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; 246 } 247 } 248 /* We found more keys, but not the denomination we are looking for :-( */ 249 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 250 "Denomination %s not found\n", 251 TALER_B2S (dh)); 252 return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; 253 } 254 255 256 enum GNUNET_DB_QueryStatus 257 TALER_ARL_get_denomination_info_by_serial ( 258 uint64_t denom_serial, 259 const struct TALER_EXCHANGEDB_DenominationKeyInformation **issuep) 260 { 261 enum GNUNET_DB_QueryStatus qs; 262 struct GNUNET_Uuid uuid; 263 264 serial_to_uuid (denom_serial, 265 &uuid); 266 if (NULL == denominations_by_serial) 267 { 268 denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256, 269 GNUNET_NO); 270 if (NULL == denominations) 271 denominations = GNUNET_CONTAINER_multihashmap_create (256, 272 GNUNET_NO); 273 274 qs = TALER_EXCHANGEDB_iterate_denomination_info (TALER_ARL_edb, 275 &add_denomination, 276 NULL); 277 if (0 > qs) 278 { 279 GNUNET_break (0); 280 *issuep = NULL; 281 return qs; 282 } 283 } 284 { 285 const struct TALER_EXCHANGEDB_DenominationKeyInformation *i; 286 287 i = GNUNET_CONTAINER_multiuuidmap_get (denominations_by_serial, 288 &uuid); 289 if (NULL != i) 290 { 291 /* cache hit */ 292 *issuep = i; 293 return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; 294 } 295 } 296 /* maybe database changed since we last iterated, give it one more shot */ 297 { 298 struct TALER_EXCHANGEDB_DenominationKeyInformation issue; 299 300 qs = TALER_EXCHANGEDB_get_denomination_by_serial (TALER_ARL_edb, 301 denom_serial, 302 &issue); 303 if (qs <= 0) 304 { 305 GNUNET_break (qs >= 0); 306 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 307 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 308 "Denomination with serial %lu not found\n", 309 denom_serial); 310 return qs; 311 } 312 313 add_denomination (NULL, 314 denom_serial, 315 NULL, 316 &issue); 317 } 318 319 { 320 const struct TALER_EXCHANGEDB_DenominationKeyInformation *i; 321 322 i = GNUNET_CONTAINER_multiuuidmap_get (denominations_by_serial, 323 &uuid); 324 if (NULL != i) 325 { 326 /* cache hit */ 327 *issuep = i; 328 return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; 329 } 330 } 331 /* We found more keys, but not the denomination we are looking for :-( */ 332 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 333 "Denomination with serial %lu not found\n", 334 denom_serial); 335 return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; 336 } 337 338 339 enum GNUNET_DB_QueryStatus 340 TALER_ARL_get_denomination_info ( 341 const struct TALER_DenominationPublicKey *denom_pub, 342 const struct TALER_EXCHANGEDB_DenominationKeyInformation **issue, 343 struct TALER_DenominationHashP *dh) 344 { 345 struct TALER_DenominationHashP hc; 346 347 if (NULL == dh) 348 dh = &hc; 349 TALER_denom_pub_hash (denom_pub, 350 dh); 351 return TALER_ARL_get_denomination_info_by_hash (dh, 352 issue); 353 } 354 355 356 /** 357 * Perform the given @a analysis within a transaction scope. 358 * Commit on success. 359 * 360 * @param analysis analysis to run 361 * @param analysis_cls closure for @a analysis 362 * @return #GNUNET_OK if @a analysis successfully committed, 363 * #GNUNET_NO if we had an error on commit (retry may help) 364 * #GNUNET_SYSERR on hard errors 365 */ 366 static enum GNUNET_GenericReturnValue 367 transact (TALER_ARL_Analysis analysis, 368 void *analysis_cls) 369 { 370 int ret; 371 enum GNUNET_DB_QueryStatus qs; 372 373 ret = TALER_AUDITORDB_start (TALER_ARL_adb, 374 "auditor-analysis"); 375 if (GNUNET_OK != ret) 376 { 377 GNUNET_break (0); 378 return GNUNET_SYSERR; 379 } 380 if (GNUNET_OK != 381 TALER_EXCHANGEDB_preflight (TALER_ARL_edb)) 382 { 383 GNUNET_break (0); 384 return GNUNET_SYSERR; 385 } 386 ret = TALER_EXCHANGEDB_start (TALER_ARL_edb, 387 "auditor"); 388 if (GNUNET_OK != ret) 389 { 390 GNUNET_break (0); 391 TALER_EXCHANGEDB_rollback (TALER_ARL_edb); 392 return GNUNET_SYSERR; 393 } 394 qs = analysis (analysis_cls); 395 if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) 396 { 397 qs = TALER_EXCHANGEDB_commit (TALER_ARL_edb); 398 if (0 > qs) 399 { 400 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); 401 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 402 "Exchange DB commit failed, rolling back transaction\n"); 403 TALER_AUDITORDB_rollback (TALER_ARL_adb); 404 } 405 else 406 { 407 qs = TALER_AUDITORDB_commit (TALER_ARL_adb); 408 if (0 > qs) 409 { 410 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); 411 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 412 "Auditor DB commit failed!\n"); 413 } 414 } 415 } 416 else 417 { 418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 419 "Processing failed; rolling back transaction\n"); 420 TALER_AUDITORDB_rollback (TALER_ARL_adb); 421 TALER_EXCHANGEDB_rollback (TALER_ARL_edb); 422 } 423 switch (qs) 424 { 425 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 426 return GNUNET_OK; 427 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 428 return GNUNET_OK; 429 case GNUNET_DB_STATUS_SOFT_ERROR: 430 return GNUNET_NO; 431 case GNUNET_DB_STATUS_HARD_ERROR: 432 return GNUNET_SYSERR; 433 } 434 return GNUNET_OK; 435 } 436 437 438 enum GNUNET_GenericReturnValue 439 TALER_ARL_setup_sessions_and_run (TALER_ARL_Analysis ana, 440 void *ana_cls) 441 { 442 enum GNUNET_DB_QueryStatus qs; 443 444 if (GNUNET_SYSERR == 445 TALER_EXCHANGEDB_preflight (TALER_ARL_edb)) 446 { 447 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 448 "Failed to initialize exchange connection.\n"); 449 return GNUNET_SYSERR; 450 } 451 if (GNUNET_SYSERR == 452 TALER_AUDITORDB_preflight (TALER_ARL_adb)) 453 { 454 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 455 "Failed to initialize auditor session.\n"); 456 return GNUNET_SYSERR; 457 } 458 459 for (unsigned int retries=0; retries<3; retries++) 460 { 461 qs = transact (ana, 462 ana_cls); 463 if (GNUNET_DB_STATUS_SOFT_ERROR != qs) 464 break; 465 } 466 if (qs < 0) 467 return GNUNET_SYSERR; 468 return GNUNET_OK; 469 } 470 471 472 void 473 TALER_ARL_amount_add_ (struct TALER_Amount *sum, 474 const struct TALER_Amount *a1, 475 const struct TALER_Amount *a2, 476 const char *filename, 477 const char *functionname, 478 unsigned int line) 479 { 480 enum TALER_AmountArithmeticResult aar; 481 const char *msg; 482 char *a2s; 483 484 aar = TALER_amount_add (sum, 485 a1, 486 a2); 487 if (aar >= 0) 488 return; 489 switch (aar) 490 { 491 case TALER_AAR_INVALID_RESULT_OVERFLOW: 492 msg = 493 "arithmetic overflow in amount addition (likely the database is corrupt, see manual)"; 494 break; 495 case TALER_AAR_INVALID_NORMALIZATION_FAILED: 496 msg = 497 "normalization failed in amount addition (likely the database is corrupt, see manual)"; 498 break; 499 case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE: 500 msg = 501 "incompatible currencies in amount addition (likely bad configuration and auditor code missing a sanity check, see manual)"; 502 break; 503 default: 504 GNUNET_assert (0); /* should be impossible */ 505 } 506 a2s = TALER_amount_to_string (a2); 507 fprintf (stderr, 508 "Aborting audit due to fatal error in function %s at %s:%d trying to add %s to %s: %s\n", 509 functionname, 510 filename, 511 line, 512 TALER_amount2s (a1), 513 a2s, 514 msg); 515 GNUNET_free (a2s); 516 exit (42); 517 } 518 519 520 void 521 TALER_ARL_amount_subtract_ (struct TALER_Amount *diff, 522 const struct TALER_Amount *a1, 523 const struct TALER_Amount *a2, 524 const char *filename, 525 const char *functionname, 526 unsigned int line) 527 { 528 enum TALER_AmountArithmeticResult aar; 529 const char *msg; 530 char *a2s; 531 532 aar = TALER_amount_subtract (diff, 533 a1, 534 a2); 535 if (aar >= 0) 536 return; 537 switch (aar) 538 { 539 case TALER_AAR_INVALID_NEGATIVE_RESULT: 540 msg = 541 "negative result in amount subtraction (likely the database is corrupt, see manual)"; 542 break; 543 case TALER_AAR_INVALID_NORMALIZATION_FAILED: 544 msg = 545 "normalization failed in amount subtraction (likely the database is corrupt, see manual)"; 546 break; 547 case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE: 548 msg = 549 "currencies incompatible in amount subtraction (likely bad configuration and auditor code missing a sanity check, see manual)"; 550 break; 551 default: 552 GNUNET_assert (0); /* should be impossible */ 553 } 554 a2s = TALER_amount_to_string (a2); 555 fprintf (stderr, 556 "Aborting audit due to fatal error in function %s at %s:%d trying to subtract %s from %s: %s\n", 557 functionname, 558 filename, 559 line, 560 a2s, 561 TALER_amount2s (a1), 562 msg); 563 GNUNET_free (a2s); 564 exit (42); 565 } 566 567 568 enum TALER_ARL_SubtractionResult 569 TALER_ARL_amount_subtract_neg_ (struct TALER_Amount *diff, 570 const struct TALER_Amount *a1, 571 const struct TALER_Amount *a2, 572 const char *filename, 573 const char *functionname, 574 unsigned int line) 575 { 576 enum TALER_AmountArithmeticResult aar; 577 const char *msg; 578 char *a2s; 579 580 aar = TALER_amount_subtract (diff, 581 a1, 582 a2); 583 switch (aar) 584 { 585 case TALER_AAR_RESULT_POSITIVE: 586 return TALER_ARL_SR_POSITIVE; 587 case TALER_AAR_RESULT_ZERO: 588 return TALER_ARL_SR_ZERO; 589 case TALER_AAR_INVALID_NEGATIVE_RESULT: 590 return TALER_ARL_SR_INVALID_NEGATIVE; 591 case TALER_AAR_INVALID_NORMALIZATION_FAILED: 592 msg = 593 "normalization failed in amount subtraction (likely the database is corrupt, see manual)"; 594 break; 595 case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE: 596 msg = 597 "currencies incompatible in amount subtraction (likely bad configuration and auditor code missing a sanity check, see manual)"; 598 break; 599 default: 600 GNUNET_assert (0); /* should be impossible */ 601 } 602 a2s = TALER_amount_to_string (a2); 603 fprintf (stderr, 604 "Aborting audit due to fatal error in function %s at %s:%d trying to subtract %s from %s: %s\n", 605 functionname, 606 filename, 607 line, 608 a2s, 609 TALER_amount2s (a1), 610 msg); 611 GNUNET_free (a2s); 612 exit (42); 613 } 614 615 616 enum GNUNET_GenericReturnValue 617 TALER_ARL_init (const struct GNUNET_CONFIGURATION_Handle *c) 618 { 619 TALER_ARL_cfg = c; 620 start_time = GNUNET_TIME_absolute_get (); 621 622 if (GNUNET_OK != 623 GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg, 624 "auditor", 625 "BASE_URL", 626 &TALER_ARL_auditor_url)) 627 { 628 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 629 "auditor", 630 "BASE_URL"); 631 return GNUNET_SYSERR; 632 } 633 if (GNUNET_OK != 634 GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg, 635 "exchange", 636 "BASE_URL", 637 &TALER_ARL_exchange_url)) 638 { 639 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 640 "exchange", 641 "BASE_URL"); 642 return GNUNET_SYSERR; 643 } 644 645 if (GNUNET_is_zero (&TALER_ARL_master_pub)) 646 { 647 /* -m option not given, try configuration */ 648 char *master_public_key_str; 649 650 if (GNUNET_OK != 651 GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg, 652 "exchange", 653 "MASTER_PUBLIC_KEY", 654 &master_public_key_str)) 655 { 656 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 657 "Pass option -m or set MASTER_PUBLIC_KEY in the configuration!\n"); 658 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 659 "exchange", 660 "MASTER_PUBLIC_KEY"); 661 return GNUNET_SYSERR; 662 } 663 if (GNUNET_OK != 664 GNUNET_CRYPTO_eddsa_public_key_from_string ( 665 master_public_key_str, 666 strlen (master_public_key_str), 667 &TALER_ARL_master_pub.eddsa_pub)) 668 { 669 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 670 "exchange", 671 "MASTER_PUBLIC_KEY", 672 "invalid key"); 673 GNUNET_free (master_public_key_str); 674 return GNUNET_SYSERR; 675 } 676 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 677 "Running auditor against exchange master public key `%s'\n", 678 master_public_key_str); 679 GNUNET_free (master_public_key_str); 680 } /* end of -m not given */ 681 682 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 683 "Taler auditor running for exchange master public key %s\n", 684 TALER_B2S (&TALER_ARL_master_pub)); 685 686 if (GNUNET_is_zero (&TALER_ARL_auditor_pub)) 687 { 688 char *auditor_public_key_str; 689 690 if (GNUNET_OK == 691 GNUNET_CONFIGURATION_get_value_string (c, 692 "auditor", 693 "PUBLIC_KEY", 694 &auditor_public_key_str)) 695 { 696 if (GNUNET_OK != 697 GNUNET_CRYPTO_eddsa_public_key_from_string ( 698 auditor_public_key_str, 699 strlen (auditor_public_key_str), 700 &TALER_ARL_auditor_pub.eddsa_pub)) 701 { 702 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 703 "auditor", 704 "PUBLIC_KEY", 705 "invalid key"); 706 GNUNET_free (auditor_public_key_str); 707 return GNUNET_SYSERR; 708 } 709 GNUNET_free (auditor_public_key_str); 710 } 711 } 712 713 if (GNUNET_is_zero (&TALER_ARL_auditor_pub)) 714 { 715 /* public key not configured */ 716 /* try loading private key and deriving public key */ 717 char *fn; 718 719 if (GNUNET_OK == 720 GNUNET_CONFIGURATION_get_value_filename (c, 721 "auditor", 722 "AUDITOR_PRIV_FILE", 723 &fn)) 724 { 725 struct TALER_AuditorPrivateKeyP auditor_priv; 726 727 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 728 "Loading offline private key from `%s' to get auditor public key\n", 729 fn); 730 if (GNUNET_OK == 731 GNUNET_CRYPTO_eddsa_key_from_file (fn, 732 GNUNET_NO, /* do NOT create it! */ 733 &auditor_priv.eddsa_priv)) 734 { 735 GNUNET_CRYPTO_eddsa_key_get_public (&auditor_priv.eddsa_priv, 736 &TALER_ARL_auditor_pub.eddsa_pub); 737 } 738 GNUNET_free (fn); 739 } 740 } 741 742 if (GNUNET_is_zero (&TALER_ARL_auditor_pub)) 743 { 744 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 745 "auditor", 746 "PUBLIC_KEY/AUDITOR_PRIV_FILE"); 747 return GNUNET_SYSERR; 748 } 749 750 if (GNUNET_OK != 751 TALER_config_get_currency (TALER_ARL_cfg, 752 "exchange", 753 &TALER_ARL_currency)) 754 { 755 return GNUNET_SYSERR; 756 } 757 { 758 if ( (GNUNET_OK != 759 TALER_config_get_amount (TALER_ARL_cfg, 760 "exchange", 761 "CURRENCY_ROUND_UNIT", 762 &TALER_ARL_currency_round_unit)) || 763 ( (0 != TALER_ARL_currency_round_unit.fraction) && 764 (0 != TALER_ARL_currency_round_unit.value) ) ) 765 { 766 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 767 "Need non-zero value in section `exchange' under `CURRENCY_ROUND_UNIT'\n"); 768 return GNUNET_SYSERR; 769 } 770 } 771 if (NULL == 772 (TALER_ARL_edb = TALER_EXCHANGEDB_connect (TALER_ARL_cfg))) 773 { 774 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 775 "Failed to initialize exchange database plugin.\n"); 776 TALER_ARL_done (); 777 return GNUNET_SYSERR; 778 } 779 if (NULL == 780 (TALER_ARL_adb = TALER_AUDITORDB_connect (TALER_ARL_cfg))) 781 { 782 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 783 "Failed to initialize auditor database plugin.\n"); 784 TALER_ARL_done (); 785 return GNUNET_SYSERR; 786 } 787 if (GNUNET_SYSERR == 788 TALER_AUDITORDB_preflight (TALER_ARL_adb)) 789 { 790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 791 "Failed to start session with auditor database.\n"); 792 TALER_ARL_done (); 793 return GNUNET_SYSERR; 794 } 795 return GNUNET_OK; 796 } 797 798 799 void 800 TALER_ARL_done () 801 { 802 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 803 "Audit complete\n"); 804 if (NULL != TALER_ARL_adb) 805 { 806 TALER_AUDITORDB_disconnect (TALER_ARL_adb); 807 TALER_ARL_adb = NULL; 808 } 809 if (NULL != TALER_ARL_edb) 810 { 811 TALER_EXCHANGEDB_disconnect (TALER_ARL_edb); 812 TALER_ARL_edb = NULL; 813 } 814 GNUNET_free (TALER_ARL_exchange_url); 815 GNUNET_free (TALER_ARL_auditor_url); 816 } 817 818 819 /* end of report-lib.c */