report-lib.c (25303B)
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 if (GNUNET_OK != ret) 375 { 376 GNUNET_break (0); 377 return GNUNET_SYSERR; 378 } 379 if (GNUNET_OK != 380 TALER_EXCHANGEDB_preflight (TALER_ARL_edb)) 381 { 382 GNUNET_break (0); 383 return GNUNET_SYSERR; 384 } 385 ret = TALER_EXCHANGEDB_start (TALER_ARL_edb, 386 "auditor"); 387 if (GNUNET_OK != ret) 388 { 389 GNUNET_break (0); 390 TALER_EXCHANGEDB_rollback (TALER_ARL_edb); 391 return GNUNET_SYSERR; 392 } 393 qs = analysis (analysis_cls); 394 if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) 395 { 396 qs = TALER_EXCHANGEDB_commit (TALER_ARL_edb); 397 if (0 > qs) 398 { 399 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); 400 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 401 "Exchange DB commit failed, rolling back transaction\n"); 402 TALER_AUDITORDB_rollback (TALER_ARL_adb); 403 } 404 else 405 { 406 qs = TALER_AUDITORDB_commit (TALER_ARL_adb); 407 if (0 > qs) 408 { 409 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); 410 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 411 "Auditor DB commit failed!\n"); 412 } 413 } 414 } 415 else 416 { 417 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 418 "Processing failed; rolling back transaction\n"); 419 TALER_AUDITORDB_rollback (TALER_ARL_adb); 420 TALER_EXCHANGEDB_rollback (TALER_ARL_edb); 421 } 422 switch (qs) 423 { 424 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 425 return GNUNET_OK; 426 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 427 return GNUNET_OK; 428 case GNUNET_DB_STATUS_SOFT_ERROR: 429 return GNUNET_NO; 430 case GNUNET_DB_STATUS_HARD_ERROR: 431 return GNUNET_SYSERR; 432 } 433 return GNUNET_OK; 434 } 435 436 437 enum GNUNET_GenericReturnValue 438 TALER_ARL_setup_sessions_and_run (TALER_ARL_Analysis ana, 439 void *ana_cls) 440 { 441 enum GNUNET_DB_QueryStatus qs; 442 443 if (GNUNET_SYSERR == 444 TALER_EXCHANGEDB_preflight (TALER_ARL_edb)) 445 { 446 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 447 "Failed to initialize exchange connection.\n"); 448 return GNUNET_SYSERR; 449 } 450 if (GNUNET_SYSERR == 451 TALER_AUDITORDB_preflight (TALER_ARL_adb)) 452 { 453 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 454 "Failed to initialize auditor session.\n"); 455 return GNUNET_SYSERR; 456 } 457 458 for (unsigned int retries=0; retries<3; retries++) 459 { 460 qs = transact (ana, 461 ana_cls); 462 if (GNUNET_DB_STATUS_SOFT_ERROR != qs) 463 break; 464 } 465 if (qs < 0) 466 return GNUNET_SYSERR; 467 return GNUNET_OK; 468 } 469 470 471 void 472 TALER_ARL_amount_add_ (struct TALER_Amount *sum, 473 const struct TALER_Amount *a1, 474 const struct TALER_Amount *a2, 475 const char *filename, 476 const char *functionname, 477 unsigned int line) 478 { 479 enum TALER_AmountArithmeticResult aar; 480 const char *msg; 481 char *a2s; 482 483 aar = TALER_amount_add (sum, 484 a1, 485 a2); 486 if (aar >= 0) 487 return; 488 switch (aar) 489 { 490 case TALER_AAR_INVALID_RESULT_OVERFLOW: 491 msg = 492 "arithmetic overflow in amount addition (likely the database is corrupt, see manual)"; 493 break; 494 case TALER_AAR_INVALID_NORMALIZATION_FAILED: 495 msg = 496 "normalization failed in amount addition (likely the database is corrupt, see manual)"; 497 break; 498 case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE: 499 msg = 500 "incompatible currencies in amount addition (likely bad configuration and auditor code missing a sanity check, see manual)"; 501 break; 502 default: 503 GNUNET_assert (0); /* should be impossible */ 504 } 505 a2s = TALER_amount_to_string (a2); 506 fprintf (stderr, 507 "Aborting audit due to fatal error in function %s at %s:%d trying to add %s to %s: %s\n", 508 functionname, 509 filename, 510 line, 511 TALER_amount2s (a1), 512 a2s, 513 msg); 514 GNUNET_free (a2s); 515 exit (42); 516 } 517 518 519 void 520 TALER_ARL_amount_subtract_ (struct TALER_Amount *diff, 521 const struct TALER_Amount *a1, 522 const struct TALER_Amount *a2, 523 const char *filename, 524 const char *functionname, 525 unsigned int line) 526 { 527 enum TALER_AmountArithmeticResult aar; 528 const char *msg; 529 char *a2s; 530 531 aar = TALER_amount_subtract (diff, 532 a1, 533 a2); 534 if (aar >= 0) 535 return; 536 switch (aar) 537 { 538 case TALER_AAR_INVALID_NEGATIVE_RESULT: 539 msg = 540 "negative result in amount subtraction (likely the database is corrupt, see manual)"; 541 break; 542 case TALER_AAR_INVALID_NORMALIZATION_FAILED: 543 msg = 544 "normalization failed in amount subtraction (likely the database is corrupt, see manual)"; 545 break; 546 case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE: 547 msg = 548 "currencies incompatible in amount subtraction (likely bad configuration and auditor code missing a sanity check, see manual)"; 549 break; 550 default: 551 GNUNET_assert (0); /* should be impossible */ 552 } 553 a2s = TALER_amount_to_string (a2); 554 fprintf (stderr, 555 "Aborting audit due to fatal error in function %s at %s:%d trying to subtract %s from %s: %s\n", 556 functionname, 557 filename, 558 line, 559 a2s, 560 TALER_amount2s (a1), 561 msg); 562 GNUNET_free (a2s); 563 exit (42); 564 } 565 566 567 enum TALER_ARL_SubtractionResult 568 TALER_ARL_amount_subtract_neg_ (struct TALER_Amount *diff, 569 const struct TALER_Amount *a1, 570 const struct TALER_Amount *a2, 571 const char *filename, 572 const char *functionname, 573 unsigned int line) 574 { 575 enum TALER_AmountArithmeticResult aar; 576 const char *msg; 577 char *a2s; 578 579 aar = TALER_amount_subtract (diff, 580 a1, 581 a2); 582 switch (aar) 583 { 584 case TALER_AAR_RESULT_POSITIVE: 585 return TALER_ARL_SR_POSITIVE; 586 case TALER_AAR_RESULT_ZERO: 587 return TALER_ARL_SR_ZERO; 588 case TALER_AAR_INVALID_NEGATIVE_RESULT: 589 return TALER_ARL_SR_INVALID_NEGATIVE; 590 case TALER_AAR_INVALID_NORMALIZATION_FAILED: 591 msg = 592 "normalization failed in amount subtraction (likely the database is corrupt, see manual)"; 593 break; 594 case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE: 595 msg = 596 "currencies incompatible in amount subtraction (likely bad configuration and auditor code missing a sanity check, see manual)"; 597 break; 598 default: 599 GNUNET_assert (0); /* should be impossible */ 600 } 601 a2s = TALER_amount_to_string (a2); 602 fprintf (stderr, 603 "Aborting audit due to fatal error in function %s at %s:%d trying to subtract %s from %s: %s\n", 604 functionname, 605 filename, 606 line, 607 a2s, 608 TALER_amount2s (a1), 609 msg); 610 GNUNET_free (a2s); 611 exit (42); 612 } 613 614 615 enum GNUNET_GenericReturnValue 616 TALER_ARL_init (const struct GNUNET_CONFIGURATION_Handle *c) 617 { 618 TALER_ARL_cfg = c; 619 start_time = GNUNET_TIME_absolute_get (); 620 621 if (GNUNET_OK != 622 GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg, 623 "auditor", 624 "BASE_URL", 625 &TALER_ARL_auditor_url)) 626 { 627 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 628 "auditor", 629 "BASE_URL"); 630 return GNUNET_SYSERR; 631 } 632 if (GNUNET_OK != 633 GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg, 634 "exchange", 635 "BASE_URL", 636 &TALER_ARL_exchange_url)) 637 { 638 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 639 "exchange", 640 "BASE_URL"); 641 return GNUNET_SYSERR; 642 } 643 644 if (GNUNET_is_zero (&TALER_ARL_master_pub)) 645 { 646 /* -m option not given, try configuration */ 647 char *master_public_key_str; 648 649 if (GNUNET_OK != 650 GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg, 651 "exchange", 652 "MASTER_PUBLIC_KEY", 653 &master_public_key_str)) 654 { 655 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 656 "Pass option -m or set MASTER_PUBLIC_KEY in the configuration!\n"); 657 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 658 "exchange", 659 "MASTER_PUBLIC_KEY"); 660 return GNUNET_SYSERR; 661 } 662 if (GNUNET_OK != 663 GNUNET_CRYPTO_eddsa_public_key_from_string ( 664 master_public_key_str, 665 strlen (master_public_key_str), 666 &TALER_ARL_master_pub.eddsa_pub)) 667 { 668 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 669 "exchange", 670 "MASTER_PUBLIC_KEY", 671 "invalid key"); 672 GNUNET_free (master_public_key_str); 673 return GNUNET_SYSERR; 674 } 675 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 676 "Running auditor against exchange master public key `%s'\n", 677 master_public_key_str); 678 GNUNET_free (master_public_key_str); 679 } /* end of -m not given */ 680 681 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 682 "Taler auditor running for exchange master public key %s\n", 683 TALER_B2S (&TALER_ARL_master_pub)); 684 685 if (GNUNET_is_zero (&TALER_ARL_auditor_pub)) 686 { 687 char *auditor_public_key_str; 688 689 if (GNUNET_OK == 690 GNUNET_CONFIGURATION_get_value_string (c, 691 "auditor", 692 "PUBLIC_KEY", 693 &auditor_public_key_str)) 694 { 695 if (GNUNET_OK != 696 GNUNET_CRYPTO_eddsa_public_key_from_string ( 697 auditor_public_key_str, 698 strlen (auditor_public_key_str), 699 &TALER_ARL_auditor_pub.eddsa_pub)) 700 { 701 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 702 "auditor", 703 "PUBLIC_KEY", 704 "invalid key"); 705 GNUNET_free (auditor_public_key_str); 706 return GNUNET_SYSERR; 707 } 708 GNUNET_free (auditor_public_key_str); 709 } 710 } 711 712 if (GNUNET_is_zero (&TALER_ARL_auditor_pub)) 713 { 714 /* public key not configured */ 715 /* try loading private key and deriving public key */ 716 char *fn; 717 718 if (GNUNET_OK == 719 GNUNET_CONFIGURATION_get_value_filename (c, 720 "auditor", 721 "AUDITOR_PRIV_FILE", 722 &fn)) 723 { 724 struct TALER_AuditorPrivateKeyP auditor_priv; 725 726 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 727 "Loading offline private key from `%s' to get auditor public key\n", 728 fn); 729 if (GNUNET_OK == 730 GNUNET_CRYPTO_eddsa_key_from_file (fn, 731 GNUNET_NO, /* do NOT create it! */ 732 &auditor_priv.eddsa_priv)) 733 { 734 GNUNET_CRYPTO_eddsa_key_get_public (&auditor_priv.eddsa_priv, 735 &TALER_ARL_auditor_pub.eddsa_pub); 736 } 737 GNUNET_free (fn); 738 } 739 } 740 741 if (GNUNET_is_zero (&TALER_ARL_auditor_pub)) 742 { 743 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 744 "auditor", 745 "PUBLIC_KEY/AUDITOR_PRIV_FILE"); 746 return GNUNET_SYSERR; 747 } 748 749 if (GNUNET_OK != 750 TALER_config_get_currency (TALER_ARL_cfg, 751 "exchange", 752 &TALER_ARL_currency)) 753 { 754 return GNUNET_SYSERR; 755 } 756 { 757 if ( (GNUNET_OK != 758 TALER_config_get_amount (TALER_ARL_cfg, 759 "exchange", 760 "CURRENCY_ROUND_UNIT", 761 &TALER_ARL_currency_round_unit)) || 762 ( (0 != TALER_ARL_currency_round_unit.fraction) && 763 (0 != TALER_ARL_currency_round_unit.value) ) ) 764 { 765 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 766 "Need non-zero value in section `exchange' under `CURRENCY_ROUND_UNIT'\n"); 767 return GNUNET_SYSERR; 768 } 769 } 770 if (NULL == 771 (TALER_ARL_edb = TALER_EXCHANGEDB_connect (TALER_ARL_cfg, 772 false))) 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 false))) 782 { 783 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 784 "Failed to initialize auditor database plugin.\n"); 785 TALER_ARL_done (); 786 return GNUNET_SYSERR; 787 } 788 if (GNUNET_SYSERR == 789 TALER_AUDITORDB_preflight (TALER_ARL_adb)) 790 { 791 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 792 "Failed to start session with auditor database.\n"); 793 TALER_ARL_done (); 794 return GNUNET_SYSERR; 795 } 796 return GNUNET_OK; 797 } 798 799 800 void 801 TALER_ARL_done () 802 { 803 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 804 "Audit complete\n"); 805 if (NULL != TALER_ARL_adb) 806 { 807 TALER_AUDITORDB_disconnect (TALER_ARL_adb); 808 TALER_ARL_adb = NULL; 809 } 810 if (NULL != TALER_ARL_edb) 811 { 812 TALER_EXCHANGEDB_disconnect (TALER_ARL_edb); 813 TALER_ARL_edb = NULL; 814 } 815 GNUNET_free (TALER_ARL_exchange_url); 816 GNUNET_free (TALER_ARL_auditor_url); 817 } 818 819 820 /* end of report-lib.c */