test-auditor.sh (82025B)
1 #!/bin/bash 2 # 3 # This file is part of TALER 4 # Copyright (C) 2014-2025 Taler Systems SA 5 # 6 # TALER is free software; you can redistribute it and/or modify it under the 7 # terms of the GNU General Public License as published by the Free Software 8 # Foundation; either version 3, or (at your option) any later version. 9 # 10 # TALER is distributed in the hope that it will be useful, but WITHOUT ANY 11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License along with 15 # TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/license> 16 # 17 # 18 # shellcheck disable=SC2317 19 # shellcheck disable=SC1091 20 # 21 # 22 # Setup database which was generated from a perfectly normal 23 # exchange-wallet interaction and run the auditor against it. 24 # 25 # Check that the auditor report is as expected. 26 # 27 # Requires 'jq' tool and Postgres superuser rights! 28 set -eu 29 #set -x 30 31 # Set of numbers for all the testcases. 32 # When adding new tests, increase the last number: 33 ALL_TESTS=$(seq 0 31) 34 35 # $TESTS determines which tests we should run. 36 # This construction is used to make it easy to 37 # only run a subset of the tests. To only run a subset, 38 # pass the numbers of the tests to run as the FIRST 39 # argument to test-auditor.sh, i.e.: 40 # 41 # $ test-auditor.sh "1 3" 42 # 43 # to run tests 1 and 3 only. By default, all tests are run. 44 # 45 TESTS=${1:-$ALL_TESTS} 46 47 export TALER_AUDITOR_TOKEN="secret-token:D4CST1Z6AHN3RT03M0T9NSTF2QGHTB5ZD2D3RYZB4HAWG8SX0JEFWBXCKXZHMB7Y3Z7KVFW0B3XPXD5BHCFP8EB0R6CNH2KAWDWVET0" 48 # Make taler-auditor-httpd require the token the requests below send. 49 export TALER_AUDITOR_ACCESS_TOKEN="${TALER_AUDITOR_TOKEN}" 50 export TALER_AUDITOR_SALT="64S36D1N6RVKGC9J6CT3ADHQ70RK4CSM6MV3EE1H68SK8D9P6WW32CHK6GTKCDSR64S36D1N6RVKGC9J6CT3ADHQ70RK4CSM6MV3EE0" 51 52 # Global variable to run the auditor processes under valgrind 53 # VALGRIND=valgrind 54 VALGRIND="" 55 56 . setup.sh 57 58 59 # Cleanup exchange and libeufin between runs. 60 function cleanup() 61 { 62 if [ -n "${EPID:-}" ] 63 then 64 echo -n "Stopping exchange $EPID..." 65 kill -TERM "$EPID" 66 wait "$EPID" || true 67 echo "DONE" 68 unset EPID 69 fi 70 stop_libeufin &> /dev/null 71 } 72 73 # Cleanup to run whenever we exit 74 function exit_cleanup() 75 { 76 jobs 77 if [ -n "${POSTGRES_PATH:-}" ] 78 then 79 echo -n "Stopping Postgres at ${POSTGRES_PATH} ..." 80 "${POSTGRES_PATH}/pg_ctl" \ 81 -D "$TMPDIR" \ 82 --log="${MY_TMP_DIR}/pg_ctl.log" \ 83 stop \ 84 &> ${MY_TMP_DIR}/pg_ctl.out \ 85 || true 86 echo "DONE" 87 fi 88 echo -n "Running exit-cleanup ..." 89 cleanup 90 for n in $(jobs -p) 91 do 92 kill "$n" 2> /dev/null || true 93 done 94 wait || true 95 echo "DONE" 96 } 97 98 # Install cleanup handler (except for kill -9) 99 trap exit_cleanup EXIT 100 101 102 function await_bank () { 103 for n in $(seq 1 80) 104 do 105 echo -n "." 106 sleep 0.1 107 OK=1 108 wget http://localhost:8082/ \ 109 -o /dev/null \ 110 -O /dev/null \ 111 >/dev/null \ 112 && break 113 OK=0 114 done 115 if [ 1 != "$OK" ] 116 then 117 exit_skip "Failed to launch libeufin-bank" 118 fi 119 } 120 121 # Operations to run before the actual audit 122 function pre_audit () { 123 # Launch bank 124 echo -n "Launching libeufin-bank" 125 export CONF 126 export MY_TMP_DIR 127 launch_libeufin 128 await_bank 129 echo " DONE" 130 131 if [ "${1:-no}" = "aggregator" ] 132 then 133 echo -n "Running exchange aggregator ..." 134 taler-exchange-aggregator \ 135 -y \ 136 -L "INFO" \ 137 -t \ 138 -c "$CONF" \ 139 2> "${MY_TMP_DIR}/aggregator.log" \ 140 || exit_fail "FAIL" 141 echo " DONE" 142 echo -n "Running exchange closer ..." 143 taler-exchange-closer \ 144 -L "INFO" \ 145 -t \ 146 -c "$CONF" \ 147 2> "${MY_TMP_DIR}/closer.log" \ 148 || exit_fail "FAIL" 149 echo " DONE" 150 echo -n "Running exchange transfer ..." 151 taler-exchange-transfer \ 152 -L "INFO" \ 153 -t \ 154 -c "$CONF" \ 155 2> "${MY_TMP_DIR}/transfer.log" \ 156 || exit_fail "FAIL" 157 echo " DONE" 158 fi 159 } 160 161 # actual audit run 162 function audit_only () { 163 # Run the auditor! 164 echo -n "Running audit(s) ..." 165 166 # Restart so that first run is always fresh, and second one is incremental 167 taler-auditor-dbinit \ 168 -r \ 169 -c "$CONF" 170 $VALGRIND taler-helper-auditor-aml \ 171 -i \ 172 -L DEBUG \ 173 -c "$CONF" \ 174 -t \ 175 > "${MY_TMP_DIR}/test-audit-aml.out" \ 176 2> "${MY_TMP_DIR}/test-audit-aml.err" \ 177 || exit_fail "aml audit failed (see ${MY_TMP_DIR}/test-audit-aml.*)" 178 echo -n "." 179 $VALGRIND taler-helper-auditor-aml \ 180 -i \ 181 -L DEBUG \ 182 -c "$CONF" \ 183 -t \ 184 > "${MY_TMP_DIR}/test-audit-aml-inc.out" \ 185 2> "${MY_TMP_DIR}/test-audit-aml-inc.err" \ 186 || exit_fail "incremental aml audit failed (see ${MY_TMP_DIR}/test-audit-aml-inc.*)" 187 echo -n "." 188 $VALGRIND taler-helper-auditor-aggregation \ 189 -L DEBUG \ 190 -c "$CONF" \ 191 -t \ 192 > "${MY_TMP_DIR}/test-audit-aggregation.out" \ 193 2> "${MY_TMP_DIR}/test-audit-aggregation.err" \ 194 || exit_fail "aggregation audit failed (see ${MY_TMP_DIR}/test-audit-aggregation.*)" 195 echo -n "." 196 $VALGRIND taler-helper-auditor-aggregation \ 197 -L DEBUG \ 198 -c "$CONF" \ 199 -t \ 200 > "${MY_TMP_DIR}/test-audit-aggregation-inc.out" \ 201 2> "${MY_TMP_DIR}/test-audit-aggregation-inc.err" \ 202 || exit_fail "incremental aggregation audit failed (see ${MY_TMP_DIR}/test-audit-aggregation-inc.*)" 203 echo -n "." 204 $VALGRIND taler-helper-auditor-coins \ 205 -L DEBUG \ 206 -c "$CONF" \ 207 -t \ 208 > "${MY_TMP_DIR}/test-audit-coins.out" \ 209 2> "${MY_TMP_DIR}/test-audit-coins.err" \ 210 || exit_fail "coin audit failed (see ${MY_TMP_DIR}/test-audit-coins.*)" 211 echo -n "." 212 $VALGRIND taler-helper-auditor-coins \ 213 -L DEBUG \ 214 -c "$CONF" \ 215 -t \ 216 > "${MY_TMP_DIR}/test-audit-coins-inc.out" \ 217 2> "${MY_TMP_DIR}/test-audit-coins-inc.err" \ 218 || exit_fail "incremental coin audit failed (see ${MY_TMP_DIR}/test-audit-coins-inc.*)" 219 echo -n "." 220 $VALGRIND taler-helper-auditor-deposits \ 221 -L DEBUG \ 222 -c "$CONF" \ 223 -t \ 224 > "${MY_TMP_DIR}/test-audit-deposits.out" \ 225 2> "${MY_TMP_DIR}/test-audit-deposits.err" \ 226 || exit_fail "deposits audit failed (see ${MY_TMP_DIR}/test-audit-deposits.*)" 227 echo -n "." 228 $VALGRIND taler-helper-auditor-deposits \ 229 -L DEBUG \ 230 -c "$CONF" \ 231 -t \ 232 > "${MY_TMP_DIR}/test-audit-deposits-inc.out" \ 233 2> "${MY_TMP_DIR}/test-audit-deposits-inc.err" \ 234 || exit_fail "incremental deposits audit failed (see ${MY_TMP_DIR}/test-audit-deposits-inc.*)" 235 echo -n "." 236 $VALGRIND taler-helper-auditor-reserves \ 237 -i \ 238 -L DEBUG \ 239 -c "$CONF" \ 240 -t \ 241 > "${MY_TMP_DIR}/test-audit-reserves.out" \ 242 2> "${MY_TMP_DIR}/test-audit-reserves.err" \ 243 || exit_fail "reserves audit failed (see ${MY_TMP_DIR}/test-audit-reserves.*)" 244 echo -n "." 245 $VALGRIND taler-helper-auditor-reserves \ 246 -i \ 247 -L DEBUG \ 248 -c "$CONF" \ 249 -t \ 250 > "${MY_TMP_DIR}/test-audit-reserves-inc.out" \ 251 2> "${MY_TMP_DIR}/test-audit-reserves-inc.err" \ 252 || exit_fail "incremental reserves audit failed (see ${MY_TMP_DIR}/test-audit-reserves-inc.*)" 253 echo -n "." 254 $VALGRIND taler-helper-auditor-wire-credit \ 255 -i \ 256 -L DEBUG \ 257 -c "$CONF" \ 258 -t \ 259 > "${MY_TMP_DIR}/test-audit-wire-credit.out" \ 260 2> "${MY_TMP_DIR}/test-audit-wire-credit.err" \ 261 || exit_fail "wire credit audit failed (see ${MY_TMP_DIR}/test-audit-wire-credit.*)" 262 echo -n "." 263 $VALGRIND taler-helper-auditor-wire-credit \ 264 -i \ 265 -L DEBUG \ 266 -c "$CONF" \ 267 -t \ 268 > "${MY_TMP_DIR}/test-audit-wire-credit-inc.out" \ 269 2> "${MY_TMP_DIR}/test-audit-wire-credit-inc.err" \ 270 || exit_fail "wire credit audit inc failed (see ${MY_TMP_DIR}/test-audit-wire-credit-inc.*)" 271 echo -n "." 272 $VALGRIND taler-helper-auditor-wire-debit \ 273 -i \ 274 -L DEBUG \ 275 -c "$CONF" \ 276 -t \ 277 > "${MY_TMP_DIR}/test-audit-wire-debit.out" \ 278 2> "${MY_TMP_DIR}/test-audit-wire-debit.err" \ 279 || exit_fail "wire debit audit failed (see ${MY_TMP_DIR}/test-audit-wire-debit.*)" 280 echo -n "." 281 $VALGRIND taler-helper-auditor-wire-debit \ 282 -i \ 283 -L DEBUG \ 284 -c "$CONF" \ 285 -t \ 286 > "${MY_TMP_DIR}/test-audit-wire-debit-inc.out" \ 287 2> "${MY_TMP_DIR}/test-audit-wire-debit-inc.err" \ 288 || exit_fail "wire debit audit inc failed (see ${MY_TMP_DIR}/test-audit-wire-debit-inc.*)" 289 echo -n "." 290 $VALGRIND taler-helper-auditor-purses \ 291 -i \ 292 -L DEBUG \ 293 -c "$CONF" \ 294 -t \ 295 > "${MY_TMP_DIR}/test-audit-purses.out" \ 296 2> "${MY_TMP_DIR}/test-audit-purses.err" \ 297 || exit_fail "audit purses failed" 298 echo -n "." 299 $VALGRIND taler-helper-auditor-purses \ 300 -i \ 301 -L DEBUG \ 302 -c "$CONF" \ 303 -t \ 304 > "${MY_TMP_DIR}/test-audit-purses-inc.out" \ 305 2> "${MY_TMP_DIR}/test-audit-purses-inc.err" \ 306 || exit_fail "audit purses inc failed" 307 echo -n "." 308 $VALGRIND taler-helper-auditor-transfer \ 309 -i \ 310 -L DEBUG \ 311 -c "$CONF" \ 312 -t \ 313 > "${MY_TMP_DIR}/test-audit-transfer.out" \ 314 2> "${MY_TMP_DIR}/test-audit-transfer.err" \ 315 || exit_fail "audit transfer failed" 316 echo -n "." 317 $VALGRIND taler-helper-auditor-transfer \ 318 -i \ 319 -L DEBUG \ 320 -c "$CONF" \ 321 -t \ 322 > "${MY_TMP_DIR}/test-audit-transfer-inc.out" \ 323 2> "${MY_TMP_DIR}/test-audit-transfer-inc.err" \ 324 || exit_fail "audit transfer inc failed" 325 echo -n "." 326 327 echo " DONE" 328 } 329 330 331 # Cleanup to run after the auditor 332 function post_audit () { 333 taler-exchange-dbinit \ 334 -c "$CONF" \ 335 -g \ 336 || exit_fail "exchange DB GC failed" 337 cleanup 338 } 339 340 341 # Run audit process on current database, including report 342 # generation. Pass "aggregator" as $1 to run 343 # $ taler-exchange-aggregator 344 # before auditor (to trigger pending wire transfers). 345 # Pass "drain" as $2 to run a drain operation as well. 346 function run_audit () { 347 pre_audit "${1:-no}" 348 if [ "${2:-no}" = "drain" ] 349 then 350 echo -n "Starting exchange..." 351 taler-exchange-httpd \ 352 -c "${CONF}" \ 353 -L INFO \ 354 2> "${MY_TMP_DIR}/exchange-httpd-drain.err" & 355 EPID=$! 356 357 # Wait for exchange service to be available 358 for n in $(seq 1 50) 359 do 360 echo -n "." 361 sleep 0.1 362 OK=0 363 # exchange 364 wget "http://localhost:8081/config" \ 365 -o /dev/null \ 366 -O /dev/null \ 367 >/dev/null \ 368 || continue 369 OK=1 370 break 371 done 372 echo "... DONE." 373 export CONF 374 375 echo -n "Running taler-exchange-offline drain " 376 377 taler-exchange-offline \ 378 -L DEBUG \ 379 -c "${CONF}" \ 380 drain TESTKUDOS:0.1 \ 381 exchange-account-1 payto://iban/DE12500105170648489890?receiver-name=Merchant43 \ 382 upload \ 383 2> "${MY_TMP_DIR}/taler-exchange-offline-drain.log" \ 384 || exit_fail "offline draining failed" 385 kill -TERM "$EPID" 386 wait "$EPID" || true 387 unset EPID 388 echo -n "Running taler-exchange-drain ..." 389 printf "\n" | taler-exchange-drain \ 390 -L DEBUG \ 391 -c "$CONF" \ 392 2> "${MY_TMP_DIR}/taler-exchange-drain.log" \ 393 || exit_fail "FAIL" 394 echo " DONE" 395 396 echo -n "Running taler-exchange-transfer ..." 397 taler-exchange-transfer \ 398 -L INFO \ 399 -t \ 400 -c "$CONF" \ 401 2> "${MY_TMP_DIR}/drain-transfer.log" \ 402 || exit_fail "FAIL" 403 echo " DONE" 404 fi 405 audit_only 406 post_audit 407 } 408 409 410 function stop_auditor_httpd() { 411 if [ -n "${APID:-}" ] 412 then 413 echo -n "Stopping auditor $APID..." 414 kill -TERM "$APID" 415 wait "$APID" || true 416 echo "DONE" 417 unset APID 418 fi 419 } 420 421 422 # Do a full reload of the (original) database 423 function full_reload() 424 { 425 echo -n "Doing full reload of the database (loading ${BASEDB}.sql into $DB at ${PGHOST:-})... " 426 dropdb -f "$DB" &>> ${MY_TMP_DIR}/drop.log || true 427 createdb -T template0 "$DB" \ 428 || exit_skip "could not create database $DB (at ${PGHOST:-})" 429 # Import pre-generated database, -q(ietly) using single (-1) transaction 430 psql -Aqt "$DB" \ 431 -q \ 432 -1 \ 433 -f "${BASEDB}.sql" \ 434 &>> ${MY_TMP_DIR}/postgresql-reload.log \ 435 || exit_skip "Failed to load database $DB from ${BASEDB}.sql" 436 echo "DONE" 437 # Technically, this call shouldn't be needed as libeufin should already be stopped here... 438 stop_libeufin 439 stop_auditor_httpd 440 } 441 442 function run_auditor_httpd() { 443 echo -n "Starting auditor..." 444 $VALGRIND taler-auditor-httpd \ 445 -c "${CONF}" \ 446 -L INFO \ 447 2> "${MY_TMP_DIR}/auditor-httpd.err" & 448 APID=$! 449 450 # Wait for auditor service to be available 451 for n in $(seq 1 50) 452 do 453 echo -n "." 454 sleep 0.2 455 OK=0 456 # auditor 457 wget "http://localhost:8083/config" \ 458 -o /dev/null \ 459 -O /dev/null \ 460 >/dev/null \ 461 || continue 462 OK=1 463 break 464 done 465 echo "... DONE." 466 wget "http://localhost:8083/webui/" \ 467 -o /dev/null \ 468 -O /dev/null \ 469 >/dev/null \ 470 || exit_fail "Auditor WebUI is not available under /webui/" 471 curl -sS -f \ 472 -H "Accept: application/json" \ 473 -H "Authorization: Bearer ${TALER_AUDITOR_TOKEN}" \ 474 -o /dev/null \ 475 "http://localhost:8083/monitoring/coin-inconsistencies" \ 476 || exit_fail "Auditor monitoring endpoint rejects default pagination" 477 } 478 479 480 function check_auditor_running() { 481 ARUNSTATUS=$(curl -Is http://localhost:8083/config | head -1) 482 if [ -n "${ARUNSTATUS:-}" ] 483 then 484 echo "Auditor running" 485 else 486 echo "Auditor not running, starting it" 487 run_auditor_httpd 488 fi 489 unset ARUNSTATUS 490 } 491 492 function call_endpoint() { 493 if [ -n "${2+x}" ] 494 then 495 curl -s -H "Accept: application/json" -H "Authorization: Bearer ${TALER_AUDITOR_TOKEN}" -o "${MY_TMP_DIR}/${2}.json" "localhost:8083/monitoring/${1}?limit=50&balance_key=${2}" 496 echo "endpoint ${1} called (with balance_key)... " 497 else 498 curl -s -H "Accept: application/json" -H "Authorization: Bearer ${TALER_AUDITOR_TOKEN}" -o "${MY_TMP_DIR}/${1}.json" "localhost:8083/monitoring/${1}?limit=50" 499 echo "endpoint ${1} called... " 500 fi 501 } 502 503 504 function check_balance() { 505 call_endpoint "balances" "$1" 506 BAL=$(jq -r .records[0].balance_value < "${MY_TMP_DIR}/${1}.json") 507 if [ "$BAL" != "$2" ] 508 then 509 exit_fail "$3 (got $BAL, wanted $2)" 510 fi 511 echo "PASS" 512 } 513 514 515 function check_not_balance() { 516 call_endpoint "balances" "$1" 517 BAL=$(jq -r .records[0].balance_value < "${MY_TMP_DIR}/${1}.json") 518 if [ "$BAL" = "$2" ] 519 then 520 exit_fail "$3 (got $BAL, wanted NOT $2)" 521 fi 522 echo "PASS" 523 } 524 525 526 function check_report() { 527 call_endpoint "$1" 528 VAL=$(jq -r .records[0].\"$2\" < "${MY_TMP_DIR}/${1}.json") 529 if [ "$VAL" != "$3" ] 530 then 531 exit_fail "$1::$2 (got $VAL, wanted $3)" 532 fi 533 echo "PASS" 534 } 535 536 # Check that at least one entry of report $1 has field $2 set to $3. 537 # Unlike check_report, this does not depend on the order in which the 538 # auditor inserted its findings: one fault can legitimately be reported 539 # against several operations (a coin with a bad denomination signature is 540 # flagged once per operation that used it). 541 function check_report_any() { 542 call_endpoint "$1" 543 jq -e --arg want "$3" "any(.records[]; .\"$2\" == \$want)" \ 544 < "${MY_TMP_DIR}/${1}.json" \ 545 > /dev/null \ 546 || exit_fail "$1::$2 (no entry with value $3)" 547 echo "PASS" 548 } 549 550 function check_no_report() { 551 call_endpoint "$1" 552 jq -e .records[0] \ 553 < "${MY_TMP_DIR}/${1}.json" \ 554 > /dev/null \ 555 && exit_fail "Wanted empty report for $1, but got incidents" 556 echo "PASS" 557 } 558 559 function check_report_neg() { 560 call_endpoint "$1" 561 VAL=$(jq -r .records[0].\"$2\" < "${MY_TMP_DIR}/${1}.json") 562 if [ "$VAL" == "$3" ] 563 then 564 exit_fail "$1::$2 (got $VAL, wanted $3)" 565 fi 566 echo "PASS" 567 } 568 569 function check_row() { 570 call_endpoint "$1" 571 if [ -n "${3+x}" ] 572 then 573 RID="$2" 574 WANT="$3" 575 else 576 RID="row_id" 577 WANT="$2" 578 fi 579 ROW=$(jq -r .records[0].\"${RID}\" < "${MY_TMP_DIR}/${1}.json") 580 if [ "$ROW" != "$WANT" ] 581 then 582 exit_fail "Row ${1} wrong (got ${ROW}, wanted ${WANT})" 583 fi 584 echo "PASS" 585 } 586 587 588 function test_0() { 589 590 echo "===========0: normal run with aggregator===========" 591 run_audit aggregator 592 check_auditor_running 593 594 echo "Checking output" 595 596 # if an emergency was detected, that is a bug and we should fail 597 echo -n "Test for emergencies... " 598 check_no_report "emergencies" 599 echo -n "Test for emergencies by count... " 600 check_no_report "emergencies-by-count" 601 echo -n "Test for wire inconsistencies... " 602 check_no_report "denomination-key-validity-withdraw-inconsistencies" 603 echo -n "Test for deposit confirmation problems... " 604 check_no_report "deposit-confirmations" 605 606 # Just to test the endpoint and for logging ... 607 call_endpoint "balances" 608 609 echo -n "Testing bad sig loss balance... " 610 check_balance \ 611 "aggregation_total_bad_sig_loss" \ 612 "TESTKUDOS:0" \ 613 "Wrong total bad sig loss from aggregation, got unexpected loss" 614 615 echo -n "Testing coin irregular loss balances... " 616 check_balance \ 617 "coin_irregular_loss" \ 618 "TESTKUDOS:0" \ 619 "Wrong total bad sig loss from coins" 620 621 echo -n "Testing reserves bad sig loss balances... " 622 check_balance \ 623 "reserves_total_bad_sig_loss" \ 624 "TESTKUDOS:0" \ 625 "Wrong total bad sig loss from reserves" 626 627 # The aggregator ran and every transfer it decided on was executed, so 628 # nothing may be left aggregated-but-unpaid, under any of the three 629 # headings. This database has no KYC at all (see 630 # generate-auditor-basedb.sh), so a non-zero total_aml_hold would mean the 631 # exchange claimed a legal reason it cannot have had; test-kyc.sh covers 632 # the case where there genuinely is one. 633 echo -n "Test for withheld payouts... " 634 check_balance \ 635 "total_aml_hold" \ 636 "TESTKUDOS:0" \ 637 "Auditor found a KYC hold in a database without KYC" 638 echo -n "Test for aggregates parked below the wire fee... " 639 check_balance \ 640 "total_small_aggregate" \ 641 "TESTKUDOS:0" \ 642 "Exchange parked an aggregate as too small to pay out" 643 echo -n "Test for unexplained payout delays... " 644 check_balance \ 645 "total_transfer_lag" \ 646 "TESTKUDOS:0" \ 647 "Exchange aggregated a payout and did not execute it" 648 649 echo -n "Test for aggregation wire out delta plus... " 650 check_balance \ 651 "aggregation_total_wire_out_delta_plus" \ 652 "TESTKUDOS:0" \ 653 "Expected total wire out delta plus wrong" 654 655 echo -n "Test for aggregation wire out delta minus... " 656 check_balance \ 657 "aggregation_total_wire_out_delta_minus" \ 658 "TESTKUDOS:0" \ 659 "Expected total wire out delta minus wrong" 660 661 echo -n "Test for bad incoming delta plus... " 662 check_balance \ 663 "total_bad_amount_in_plus" \ 664 "TESTKUDOS:0" \ 665 "Expected total wire in delta plus wrong" 666 667 echo -n "Test for bad incoming delta minus... " 668 check_balance \ 669 "total_bad_amount_in_minus" \ 670 "TESTKUDOS:0" \ 671 "Expected total wire in delta minus wrong" 672 673 echo -n "Test for misattribution amounts... " 674 check_balance \ 675 "total_misattribution_in" \ 676 "TESTKUDOS:0" \ 677 "Expected total misattribution in wrong" 678 679 echo -n "Checking for unexpected aggregation delta plus differences... " 680 check_balance \ 681 "aggregation_total_arithmetic_delta_plus" \ 682 "TESTKUDOS:0" \ 683 "Wrong arithmetic delta plus from aggregations" 684 685 echo -n "Checking for unexpected aggregation delta minus differences... " 686 check_balance \ 687 "aggregation_total_arithmetic_delta_minus" \ 688 "TESTKUDOS:0" \ 689 "Wrong arithmetic delta minus from aggregations" 690 691 echo -n "Checking for unexpected coin delta plus differences... " 692 check_balance \ 693 "coins_total_arithmetic_delta_plus" \ 694 "TESTKUDOS:0" \ 695 "Wrong arithmetic delta plus from coins" 696 697 echo -n "Checking for unexpected coin delta minus differences... " 698 check_balance \ 699 "coins_total_arithmetic_delta_minus" \ 700 "TESTKUDOS:0" \ 701 "Wrong arithmetic delta minus from coins" 702 703 echo -n "Checking for unexpected reserves delta plus... " 704 check_balance \ 705 "reserves_total_arithmetic_delta_plus" \ 706 "TESTKUDOS:0" \ 707 "Wrong arithmetic delta plus from reserves" 708 709 echo -n "Checking for unexpected reserves delta minus... " 710 check_balance \ 711 "reserves_total_arithmetic_delta_minus" \ 712 "TESTKUDOS:0" \ 713 "Wrong arithmetic delta minus from reserves" 714 715 echo -n "Checking for unexpected wire out differences " 716 check_no_report "wire-out-inconsistencies" 717 718 # cannot easily undo aggregator, hence full reload 719 full_reload 720 cleanup 721 } 722 723 724 # Run without aggregator, hence auditor should detect wire 725 # transfer lag! 726 function test_1() { 727 728 echo "===========1: normal run===========" 729 run_audit 730 check_auditor_running 731 732 echo "Checking output" 733 # if an emergency was detected, that is a bug and we should fail 734 735 call_endpoint "balances" 736 737 echo -n "Test for emergencies... " 738 check_no_report "emergencies" 739 echo -n "Test for emergencies by count... " 740 check_no_report "emergencies-by-count" 741 echo -n "Test for wire inconsistencies... " 742 check_no_report "denomination-key-validity-withdraw-inconsistencies" 743 744 # TODO: check operation balances are correct (once we have all transaction types and wallet is deterministic) 745 # TODO: check revenue summaries are correct (once we have all transaction types and wallet is deterministic) 746 747 echo -n "Check for lag detection... " 748 # Check wire transfer lag reported (no aggregator!) 749 check_not_balance \ 750 "total_amount_lag" \ 751 "TESTKUDOS:0" \ 752 "Failed to detect lag" 753 754 echo -n "Test for bad incoming delta plus... " 755 check_balance \ 756 "total_bad_amount_in_plus" \ 757 "TESTKUDOS:0" \ 758 "Expected total wire in delta plus wrong" 759 760 echo -n "Test for bad incoming delta minus... " 761 check_balance \ 762 "total_bad_amount_in_minus" \ 763 "TESTKUDOS:0" \ 764 "Expected total wire in delta minus wrong" 765 766 echo -n "Test for misattribution amounts... " 767 check_balance \ 768 "total_misattribution_in" \ 769 "TESTKUDOS:0" \ 770 "Expected total misattribution in wrong" 771 # Database was unmodified, no need to undo 772 } 773 774 775 # Change amount of wire transfer reported by exchange 776 function test_2() { 777 778 echo "===========2: reserves_in inconsistency ===========" 779 echo -n "Modifying database: " 780 echo "UPDATE exchange.reserves_in SET credit.val=5 WHERE reserve_in_serial_id=1" \ 781 | psql -At "$DB" 782 783 run_audit 784 check_auditor_running 785 786 echo -n "Testing inconsistency detection ... " 787 check_report \ 788 "reserve-in-inconsistencies" \ 789 "row_id" 1 790 echo -n "Testing inconsistency detection amount wired ... " 791 check_report \ 792 "reserve-in-inconsistencies" \ 793 "amount_wired" "TESTKUDOS:10" 794 echo -n "Testing inconsistency detection amount expected ... " 795 check_report \ 796 "reserve-in-inconsistencies" \ 797 "amount_exchange_expected" "TESTKUDOS:5" 798 799 call_endpoint "balances" 800 echo -n "Checking wire credit balance minus ... " 801 check_balance \ 802 "total_bad_amount_in_minus" \ 803 "TESTKUDOS:0" \ 804 "Wrong total_bad_amount_in_minus" 805 echo -n "Checking wire credit balance plus ... " 806 check_balance \ 807 "total_bad_amount_in_plus" \ 808 "TESTKUDOS:5" \ 809 "Expected total_bad_amount_in_plus wrong" 810 811 echo -n "Undoing database modification " 812 echo "UPDATE exchange.reserves_in SET credit.val=10 WHERE reserve_in_serial_id=1" \ 813 | psql -Aqt "$DB" 814 full_reload 815 cleanup 816 } 817 818 819 # Check for incoming wire transfer amount given being 820 # lower than what exchange claims to have received. 821 function test_3() { 822 823 echo "===========3: reserves_in inconsistency===========" 824 echo "UPDATE exchange.reserves_in SET credit.val=15 WHERE reserve_in_serial_id=1" \ 825 | psql -Aqt "$DB" 826 827 run_audit 828 check_auditor_running 829 830 echo "Checking reserve balance summary inconsistency detection ..." 831 check_report \ 832 "reserve-balance-summary-wrong-inconsistencies" \ 833 "auditor_amount" "TESTKUDOS:5.01" 834 check_report \ 835 "reserve-balance-summary-wrong-inconsistencies" \ 836 "exchange_amount" "TESTKUDOS:0.01" 837 838 call_endpoint "balances" 839 check_balance \ 840 "reserves_reserve_loss" \ 841 "TESTKUDOS:0" \ 842 "Wrong total loss from insufficient balance" 843 844 echo -n "Testing inconsistency detection ... " 845 check_report \ 846 "reserve-in-inconsistencies" \ 847 "row_id" 1 848 echo -n "Testing inconsistency detection amount wired ... " 849 check_report \ 850 "reserve-in-inconsistencies" \ 851 "amount_wired" "TESTKUDOS:10" 852 echo -n "Testing inconsistency detection amount expected ... " 853 check_report \ 854 "reserve-in-inconsistencies" \ 855 "amount_exchange_expected" "TESTKUDOS:15" 856 857 echo -n "Checking wire credit balance minus ... " 858 check_balance \ 859 "total_bad_amount_in_minus" \ 860 "TESTKUDOS:5" \ 861 "Wrong total_bad_amount_in_minus" 862 echo -n "Checking wire credit balance plus ... " 863 check_balance \ 864 "total_bad_amount_in_plus" \ 865 "TESTKUDOS:0" \ 866 "Wrong total_bad_amount_in_plus" 867 868 # Undo database modification 869 echo "UPDATE exchange.reserves_in SET credit.val=10 WHERE reserve_in_serial_id=1" | psql -Aqt "$DB" 870 full_reload 871 cleanup 872 } 873 874 875 # Check for incoming wire transfer amount given being 876 # lower than what exchange claims to have received. 877 function test_4() { 878 echo "===========4: deposit wire target wrong=================" 879 880 SERIALE=$(echo "SELECT coin_deposit_serial_id FROM exchange.coin_deposits WHERE (amount_with_fee).val=3 ORDER BY coin_deposit_serial_id LIMIT 1;" | psql "$DB" -Aqt) 881 OLD_COIN_SIG=$(echo "SELECT coin_sig FROM exchange.coin_deposits WHERE coin_deposit_serial_id=${SERIALE};" | psql "$DB" -Aqt) 882 echo -n "Manipulating row ${SERIALE} ..." 883 # shellcheck disable=SC2028 884 echo "INSERT INTO exchange.wire_targets (payto_uri, wire_target_h_payto) VALUES ('payto://x-taler-bank/localhost/testuser-xxlargtp', '\x1e8f31936b3cee8f8afd3aac9e38b5db42d45b721ffc4eb1e5b9ddaf1565660b');" \ 885 | psql -Aqt "$DB" 886 # shellcheck disable=SC2028 887 echo "UPDATE exchange.coin_deposits SET coin_sig='\x0f29b2ebf3cd1ecbb3e1f2a7888872058fc870c28c0065d4a7d457f2fee9eb5ec376958fc52460c8c540e583be10cf67491a6651a62c1bda68051c62dbe9130c' WHERE coin_deposit_serial_id=${SERIALE}" \ 888 | psql -Aqt "$DB" 889 echo " DONE" 890 891 run_audit 892 check_auditor_running 893 894 echo -n "Testing inconsistency detection... " 895 check_report \ 896 "bad-sig-losses" \ 897 "problem_row_id" "${SERIALE}" 898 echo -n "Testing loss report... " 899 check_report \ 900 "bad-sig-losses" \ 901 "loss" "TESTKUDOS:3.02" 902 echo -n "Testing loss operation attribution... " 903 check_report \ 904 "bad-sig-losses" \ 905 "operation" "deposit" 906 echo -n "Testing total coin_irregular_loss balance update... " 907 check_balance \ 908 "coin_irregular_loss" \ 909 "TESTKUDOS:3.02" \ 910 "wrong total coin_irregular_loss" 911 # Undo: 912 echo "UPDATE exchange.coin_deposits SET coin_sig='$OLD_COIN_SIG' WHERE coin_deposit_serial_id=${SERIALE}" | psql -Aqt "$DB" 913 914 full_reload 915 cleanup 916 } 917 918 919 # Test where h_contract_terms in the deposit table is wrong 920 # (=> bad signature) 921 function test_5() { 922 echo "===========5: deposit contract hash wrong=================" 923 # Modify h_wire hash, so it is inconsistent with 'wire' 924 CSERIAL=$(echo "SELECT coin_deposit_serial_id FROM exchange.coin_deposits WHERE (amount_with_fee).val=3 ORDER BY coin_deposit_serial_id LIMIT 1;" | psql "$DB" -Aqt) 925 SERIAL=$(echo "SELECT batch_deposit_serial_id FROM exchange.coin_deposits WHERE (amount_with_fee).val=3 ORDER BY coin_deposit_serial_id LIMIT 1;" | psql "$DB" -Aqt) 926 OLD_H=$(echo "SELECT h_contract_terms FROM exchange.batch_deposits WHERE batch_deposit_serial_id=$SERIAL;" | psql "$DB" -Aqt) 927 echo -n "Manipulating row ${SERIAL} ..." 928 # shellcheck disable=SC2028 929 echo "UPDATE exchange.batch_deposits SET h_contract_terms='\x12bb676444955c98789f219148aa31899d8c354a63330624d3d143222cf3bb8b8e16f69accd5a8773127059b804c1955696bf551dd7be62719870613332aa8d5' WHERE batch_deposit_serial_id=${SERIAL}" \ 930 | psql -At "$DB" 931 # 932 run_audit 933 check_auditor_running 934 935 echo -n "Checking bad signature detection... " 936 check_report \ 937 "bad-sig-losses" \ 938 "problem_row_id" "$CSERIAL" 939 echo -n "Testing loss report... " 940 check_report \ 941 "bad-sig-losses" \ 942 "loss" "TESTKUDOS:3.02" 943 echo -n "Testing loss operation attribution... " 944 check_report \ 945 "bad-sig-losses" \ 946 "operation" "deposit" 947 echo -n "Testing total coin_irregular_loss balance update... " 948 check_balance \ 949 "coin_irregular_loss" \ 950 "TESTKUDOS:3.02" \ 951 "wrong total coin_irregular_loss" 952 953 # Undo: 954 echo "UPDATE exchange.batch_deposits SET h_contract_terms='${OLD_H}' WHERE batch_deposit_serial_id=$SERIAL" \ 955 | psql -Aqt "$DB" 956 957 } 958 959 960 # Test where denom_sig in known_coins table is wrong 961 # (=> bad signature) 962 function test_6() { 963 echo "===========6: known_coins signature wrong=================" 964 # Modify denom_sig, so it is wrong 965 OLD_ROW=$(echo "SELECT known_coin_id FROM exchange.known_coins LIMIT 1;" | psql "$DB" -Aqt) 966 OLD_SIG=$(echo "SELECT denom_sig FROM exchange.known_coins WHERE known_coin_id=$OLD_ROW;" | psql "$DB" -Aqt) 967 COIN_PUB=$(echo "SELECT coin_pub FROM exchange.known_coins WHERE denom_sig='$OLD_SIG';" | psql "$DB" -Aqt) 968 # shellcheck disable=SC2028 969 echo "UPDATE exchange.known_coins SET denom_sig='\x0000000100000000287369672d76616c200a2028727361200a2020287320233542383731423743393036444643303442424430453039353246413642464132463537303139374131313437353746324632323332394644443146324643333445393939413336363430334233413133324444464239413833353833464536354442374335434445304441453035374438363336434541423834463843323843344446304144363030343430413038353435363039373833434431333239393736423642433437313041324632414132414435413833303432434346314139464635394244434346374436323238344143354544364131373739463430353032323241373838423837363535453434423145443831364244353638303232413123290a2020290a20290b' WHERE coin_pub='$COIN_PUB'" \ 970 | psql -Aqt "$DB" 971 972 run_audit 973 check_auditor_running 974 975 echo -n "Checking bad-signature-loss detected ..." 976 check_row \ 977 "bad-sig-losses" \ 978 "problem_row_id" "1" # Row reported is that of deposits or melt table, not known_coins 979 echo -n "Checking bad-signature-loss amount detected ..." 980 check_report_neg \ 981 "bad-sig-losses" \ 982 "loss" "TESTKUDOS:0" 983 echo -n "Checking bad-signature-loss operation detected ..." 984 # The coin was both melted and deposited, so the bad denomination 985 # signature is reported against either operation; only require that 986 # the deposit was flagged. 987 check_report_any \ 988 "bad-sig-losses" \ 989 "operation" "deposit" 990 echo -n "Checking bad-signature-loss balance update ..." 991 check_not_balance \ 992 "coin_irregular_loss" \ 993 "TESTKUDOS:0" \ 994 "Wrong total bad sig loss" 995 996 echo -n "Undo database change ... " 997 echo "UPDATE exchange.known_coins SET denom_sig='$OLD_SIG' WHERE coin_pub='$COIN_PUB'" | psql -Aqt "$DB" 998 full_reload 999 cleanup 1000 } 1001 1002 1003 # Test where signature in the withdraw table is wrong 1004 function test_7() { 1005 echo "===========7: withdraw signature wrong=================" 1006 # Modify reserve_sig, so it is bogus 1007 HBE=$(echo 'SELECT withdraw_id FROM exchange.withdraw LIMIT 1;' | psql "$DB" -Aqt) 1008 OLD_SIG=$(echo "SELECT reserve_sig FROM exchange.withdraw WHERE withdraw_id='$HBE';" | psql "$DB" -Aqt) 1009 A_VAL=$(echo "SELECT (amount_with_fee).val FROM exchange.withdraw WHERE withdraw_id='$HBE';" | psql "$DB" -Aqt) 1010 A_FRAC=$(echo "SELECT (amount_with_fee).frac FROM exchange.withdraw WHERE withdraw_id='$HBE';" | psql "$DB" -Aqt) 1011 # Normalize, we only deal with cents in this test-case 1012 A_FRAC=$(( A_FRAC / 1000000)) 1013 # shellcheck disable=SC2028 1014 echo "UPDATE exchange.withdraw SET reserve_sig='\x9ef381a84aff252646a157d88eded50f708b2c52b7120d5a232a5b628f9ced6d497e6652d986b581188fb014ca857fd5e765a8ccc4eb7e2ce9edcde39accaa4b' WHERE withdraw_id='$HBE'" \ 1015 | psql -Aqt "$DB" 1016 run_audit 1017 check_auditor_running 1018 1019 echo -n "Checking bad signature was detected ..." 1020 check_report \ 1021 "bad-sig-losses" \ 1022 "operation" "withdraw" 1023 echo -n "Checking loss was reported ..." 1024 if [ "$A_FRAC" != 0 ] 1025 then 1026 if [ "$A_FRAC" -lt 10 ] 1027 then 1028 A_PREV="0" 1029 else 1030 A_PREV="" 1031 fi 1032 EXPECTED_LOSS="TESTKUDOS:$A_VAL.$A_PREV$A_FRAC" 1033 else 1034 EXPECTED_LOSS="TESTKUDOS:$A_VAL" 1035 fi 1036 check_report \ 1037 "bad-sig-losses" \ 1038 "loss" "$EXPECTED_LOSS" 1039 echo "Checking loss was totaled up ..." 1040 check_balance \ 1041 "reserves_total_bad_sig_loss" \ 1042 "$EXPECTED_LOSS" \ 1043 "wrong total bad sig loss" 1044 1045 # Undo: 1046 echo "UPDATE exchange.withdraw SET reserve_sig='$OLD_SIG' WHERE withdraw_id='$HBE'" | psql -Aqt "$DB" 1047 full_reload 1048 cleanup 1049 } 1050 1051 1052 # Test wire transfer subject disagreement! 1053 function test_8() { 1054 1055 echo "===========8: wire-transfer-subject disagreement===========" 1056 # Technically, this call shouldn't be needed, as libeufin should already be stopped here. 1057 stop_libeufin 1058 OLD_ID=$(echo "SELECT exchange_incoming_id FROM libeufin_bank.taler_exchange_incoming JOIN libeufin_bank.bank_account_transactions ON (bank_transaction=bank_transaction_id) WHERE (amount).val=10 ORDER BY exchange_incoming_id LIMIT 1;" | psql "${DB}" -Aqt) \ 1059 || exit_fail "Failed to SELECT FROM libeufin_bank.bank_account_transactions!" 1060 OLD_WTID=$(echo "SELECT metadata FROM libeufin_bank.taler_exchange_incoming WHERE exchange_incoming_id='$OLD_ID';" \ 1061 | psql "${DB}" -Aqt) 1062 NEW_WTID="\x77b4e23a41a0158299cdbe4d3247b42f907836d76dbc45c585c6a9beb196e6ca" 1063 echo -n "Modifying $OLD_ID ..." 1064 echo "UPDATE libeufin_bank.taler_exchange_incoming SET metadata='$NEW_WTID' WHERE exchange_incoming_id='$OLD_ID';" \ 1065 | psql "${DB}" -At \ 1066 || exit_fail "Failed to update taler_exchange_incoming" 1067 echo "DONE" 1068 1069 run_audit 1070 check_auditor_running 1071 1072 echo -n "Checking inconsistency diagnostic ..." 1073 check_report \ 1074 "reserve-in-inconsistencies" \ 1075 "diagnostic" "wire subject does not match" 1076 echo -n "Checking expected balance report ..." 1077 check_report \ 1078 "reserve-in-inconsistencies" \ 1079 "amount_exchange_expected" "TESTKUDOS:10" 1080 echo -n "Checking actual incoming balance report ..." 1081 check_report \ 1082 "reserve-in-inconsistencies" \ 1083 "amount_wired" "TESTKUDOS:0" 1084 echo -n "Checking balance update (bad plus)..." 1085 check_balance \ 1086 "total_bad_amount_in_plus" \ 1087 "TESTKUDOS:10" \ 1088 "Wrong total_bad_amount_in_plus" 1089 echo -n "Checking balance update (bad minus)..." 1090 check_balance \ 1091 "total_bad_amount_in_minus" \ 1092 "TESTKUDOS:10" \ 1093 "Wrong total_bad_amount_in_plus" 1094 1095 # Undo database modification 1096 echo "UPDATE libeufin_bank.taler_exchange_incoming SET metadata='$OLD_WTID' WHERE exchange_incoming_id='$OLD_ID';" \ 1097 | psql "${DB}" -q 1098 full_reload 1099 cleanup 1100 } 1101 1102 1103 # Test wire origin disagreement! 1104 function test_9() { 1105 1106 echo "===========9: wire-origin disagreement===========" 1107 # Technically, this call shouldn't be needed, as libeufin should already be stopped here. 1108 stop_libeufin 1109 OLD_ID=$(echo "SELECT bank_transaction FROM libeufin_bank.taler_exchange_incoming JOIN libeufin_bank.bank_account_transactions ON (bank_transaction=bank_transaction_id) WHERE (amount).val=10 ORDER BY bank_transaction LIMIT 1;" | psql "${DB}" -Aqt) \ 1110 || exit_fail "Failed to SELECT FROM libeufin_bank.bank_account_transactions!" 1111 OLD_ACC=$(echo "SELECT debtor_payto FROM libeufin_bank.bank_account_transactions WHERE bank_transaction_id='$OLD_ID';" | psql "${DB}" -Aqt) 1112 1113 echo -n "Modifying $OLD_ID ..." 1114 echo "UPDATE libeufin_bank.bank_account_transactions SET debtor_payto='payto://iban/DE68210501700012345678' WHERE bank_transaction_id='$OLD_ID';" \ 1115 | psql "${DB}" -At 1116 1117 run_audit 1118 check_auditor_running 1119 1120 echo -n "Testing inconsistency detection... " 1121 check_report \ 1122 misattribution-in-inconsistencies \ 1123 "amount" "TESTKUDOS:10" 1124 echo -n "Testing balance update... " 1125 check_balance \ 1126 "total_misattribution_in" \ 1127 "TESTKUDOS:10" \ 1128 "Reported total_misattribution_in wrong" 1129 # Undo database modification 1130 echo "UPDATE libeufin_bank.bank_account_transactions SET debtor_payto='$OLD_ACC' WHERE bank_transaction_id='$OLD_ID';" \ 1131 | psql "${DB}" -Atq 1132 full_reload 1133 cleanup 1134 } 1135 1136 1137 # Test wire_in timestamp disagreement! 1138 function test_10() { 1139 NOW_MS=$(date +%s)000 1140 echo "===========10: wire-timestamp disagreement===========" 1141 # Technically, this call shouldn't be needed, as libeufin should already be stopped here. 1142 stop_libeufin 1143 OLD_ID=$(echo "SELECT bank_transaction FROM libeufin_bank.taler_exchange_incoming JOIN libeufin_bank.bank_account_transactions ON (bank_transaction=bank_transaction_id) WHERE (amount).val=10 ORDER BY exchange_incoming_id LIMIT 1;" | psql "${DB}" -Aqt) \ 1144 || exit_fail "Failed to SELECT FROM libeufin_bank.bank_account_transactions!" 1145 OLD_DATE=$(echo "SELECT transaction_date FROM libeufin_bank.bank_account_transactions WHERE bank_transaction_id='$OLD_ID';" | psql "${DB}" -Aqt) 1146 echo -n "Modifying $OLD_ID ..." 1147 echo "UPDATE libeufin_bank.bank_account_transactions SET transaction_date=$NOW_MS WHERE bank_transaction_id=$OLD_ID;" \ 1148 | psql "${DB}" -At 1149 1150 run_audit 1151 check_auditor_running 1152 1153 echo -n "Testing inconsistency detection diagnostic... " 1154 check_report \ 1155 row-minor-inconsistencies \ 1156 "diagnostic" "execution date mismatch" 1157 echo -n "Testing inconsistency detection table... " 1158 check_report \ 1159 row-minor-inconsistencies \ 1160 "row_table" "reserves_in" 1161 # Undo database modification 1162 echo "UPDATE libeufin_bank.bank_account_transactions SET transaction_date=$OLD_DATE WHERE bank_transaction_id=$OLD_ID;" \ 1163 | psql "${DB}" -Aqt 1164 full_reload 1165 cleanup 1166 } 1167 1168 1169 # Test for extra outgoing wire transfer. 1170 function test_11() { 1171 echo "===========11: spurious outgoing transfer ===========" 1172 # Technically, this call shouldn't be needed, as libeufin should already be stopped here. 1173 stop_libeufin 1174 launch_libeufin 1175 OTHER_IBAN=$(echo "SELECT internal_payto FROM libeufin_bank.bank_accounts ba JOIN libeufin_bank.customers bc ON (ba.owning_customer_id = bc.customer_id) WHERE username='fortytwo'" | psql "${DB}" -Aqt) 1176 1177 await_bank 1178 echo -n "Creating bogus transfer... " 1179 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 1180 -u 'exchange:password' \ 1181 http://localhost:8082/accounts/exchange/taler-wire-gateway/transfer \ 1182 -d '{"credit_account":"'"$OTHER_IBAN"'","exchange_base_url":"http://exchange.example.com/","amount":"TESTKUDOS:10","wtid":"7X93HVKPHE0KAQ6KHSB3921KJGSVDMQFHMQV17885YJDMZ20XS9G","request_uid":"7X93HKPHE0KAQ6KHSB3921KJGSVDMQFHMQV17885YJDMZ20XS9G7X93HVKPHE0KAQ6KHSB3921KJGSVDMQFHMQV17885YJDMZ20XS9G"}' \ 1183 -w "%{http_code}" -s -o /dev/null) 1184 1185 if [ "$STATUS" != "200" ] 1186 then 1187 exit_fail "Expected 200 OK. Got: $STATUS" 1188 fi 1189 echo "DONE" 1190 stop_libeufin 1191 1192 run_audit 1193 check_auditor_running 1194 1195 echo -n "Testing inconsistency detection... " 1196 check_report \ 1197 "wire-out-inconsistencies" \ 1198 "claimed" \ 1199 "TESTKUDOS:10" 1200 echo -n "Testing bad_amount_plus balance reporting... " 1201 check_balance \ 1202 "total_bad_amount_out_plus" \ 1203 "TESTKUDOS:10" \ 1204 "reported total_bad_amount_plus wrong" 1205 echo -n "Testing bad_amount_minus balance reporting... " 1206 check_balance \ 1207 "total_bad_amount_out_minus" \ 1208 "TESTKUDOS:0" \ 1209 "reported total_bad_amount_minus wrong" 1210 echo -n "Testing expected amount is correct... " 1211 check_report \ 1212 "wire-out-inconsistencies" \ 1213 "expected" \ 1214 "TESTKUDOS:0" 1215 echo -n "Testing diagnostic message is correct... " 1216 check_report \ 1217 "wire-out-inconsistencies" \ 1218 "diagnostic" \ 1219 "missing justification for outgoing wire transfer" 1220 full_reload 1221 } 1222 1223 1224 function test_12() { 1225 1226 echo "===========12: normal run with aggregator and profit drain===========" 1227 run_audit aggregator drain 1228 check_auditor_running 1229 1230 echo "Checking output" 1231 # if an emergency was detected, that is a bug and we should fail 1232 echo -n "Test for emergencies... " 1233 check_no_report "emergencies" 1234 echo -n "Test for deposit confirmation detection... " 1235 check_no_report "deposit-confirmations" 1236 echo -n "Test for emergencies by count... " 1237 check_no_report "emergencies-by-count" 1238 1239 echo -n "Testing bad sig loss balance... " 1240 check_balance \ 1241 "aggregation_total_bad_sig_loss" \ 1242 "TESTKUDOS:0" \ 1243 "Wrong total bad sig loss from aggregation, got unexpected loss" 1244 1245 echo -n "Testing coin irregular loss balances... " 1246 check_balance \ 1247 "coin_irregular_loss" \ 1248 "TESTKUDOS:0" \ 1249 "Wrong total bad sig loss from coins" 1250 1251 echo -n "Testing reserves bad sig loss balances... " 1252 check_balance \ 1253 "reserves_total_bad_sig_loss" \ 1254 "TESTKUDOS:0" \ 1255 "Wrong total bad sig loss from reserves" 1256 1257 echo -n "Test for aggregation wire out delta plus... " 1258 check_balance \ 1259 "aggregation_total_wire_out_delta_plus" \ 1260 "TESTKUDOS:0" \ 1261 "Expected total wire out delta plus wrong" 1262 1263 echo -n "Test for aggregation wire out delta minus... " 1264 check_balance \ 1265 "aggregation_total_wire_out_delta_minus" \ 1266 "TESTKUDOS:0" \ 1267 "Expected total wire out delta minus wrong" 1268 1269 echo -n "Test for bad incoming delta plus... " 1270 check_balance \ 1271 "total_bad_amount_in_plus" \ 1272 "TESTKUDOS:0" \ 1273 "Expected total wire in delta plus wrong" 1274 1275 echo -n "Test for total misattribution in ... " 1276 check_balance \ 1277 "total_misattribution_in" \ 1278 "TESTKUDOS:0" \ 1279 "Expected total wire in delta plus wrong" 1280 1281 echo -n "Test for bad incoming delta minus... " 1282 check_balance \ 1283 "total_bad_amount_in_minus" \ 1284 "TESTKUDOS:0" \ 1285 "Expected total wire in delta minus wrong" 1286 1287 echo -n "Test for bad outgoing delta plus... " 1288 check_balance \ 1289 "total_bad_amount_out_plus" \ 1290 "TESTKUDOS:0" \ 1291 "Expected total wire out delta plus wrong" 1292 1293 echo -n "Test for bad outgoing delta minus... " 1294 check_balance \ 1295 "total_bad_amount_out_minus" \ 1296 "TESTKUDOS:0" \ 1297 "Expected total wire in delta minus wrong" 1298 1299 echo -n "Test for misattribution amounts... " 1300 check_balance \ 1301 "total_misattribution_in" \ 1302 "TESTKUDOS:0" \ 1303 "Expected total misattribution in wrong" 1304 1305 echo -n "Checking for unexpected aggregation delta plus differences... " 1306 check_balance \ 1307 "aggregation_total_arithmetic_delta_plus" \ 1308 "TESTKUDOS:0" \ 1309 "Wrong arithmetic delta plus from aggregations" 1310 1311 echo -n "Checking for unexpected aggregation delta minus differences... " 1312 check_balance \ 1313 "aggregation_total_arithmetic_delta_minus" \ 1314 "TESTKUDOS:0" \ 1315 "Wrong arithmetic delta minus from aggregations" 1316 1317 echo -n "Checking for unexpected coin delta plus differences... " 1318 check_balance \ 1319 "coins_total_arithmetic_delta_plus" \ 1320 "TESTKUDOS:0" \ 1321 "Wrong arithmetic delta plus from coins" 1322 1323 echo -n "Checking for unexpected coin delta minus differences... " 1324 check_balance \ 1325 "coins_total_arithmetic_delta_minus" \ 1326 "TESTKUDOS:0" \ 1327 "Wrong arithmetic delta minus from coins" 1328 1329 echo -n "Checking for unexpected reserves delta plus... " 1330 check_balance \ 1331 "reserves_total_arithmetic_delta_plus" \ 1332 "TESTKUDOS:0" \ 1333 "Wrong arithmetic delta plus from reserves" 1334 1335 echo -n "Checking for unexpected reserves delta minus... " 1336 check_balance \ 1337 "reserves_total_arithmetic_delta_minus" \ 1338 "TESTKUDOS:0" \ 1339 "Wrong arithmetic delta minus from reserves" 1340 1341 echo -n "Checking for unexpected wire out differences... " 1342 check_no_report "wire-out-inconsistencies" 1343 1344 # Just to test the endpoint and for logging ... 1345 call_endpoint "balances" 1346 1347 echo -n "Testing for aggregation bad sig loss... " 1348 check_balance \ 1349 "aggregation_total_bad_sig_loss" \ 1350 "TESTKUDOS:0" \ 1351 "Wrong total bad sig loss from aggregation, got unexpected loss" 1352 1353 echo -n "Testing for coin bad sig loss... " 1354 check_balance \ 1355 "coin_irregular_loss" \ 1356 "TESTKUDOS:0" \ 1357 "Wrong total bad sig loss from coins, got unexpected loss" 1358 1359 echo -n "Testing for reserves bad sig loss... " 1360 check_balance \ 1361 "reserves_total_bad_sig_loss" \ 1362 "TESTKUDOS:0" \ 1363 "Wrong total bad sig loss from reserves, got unexpected loss" 1364 1365 echo -n "Checking for unexpected aggregation delta plus differences... " 1366 check_balance \ 1367 "aggregation_total_arithmetic_delta_plus" \ 1368 "TESTKUDOS:0" \ 1369 "Wrong arithmetic delta plus from aggregations" 1370 1371 echo -n "Checking for unexpected aggregation delta minus differences... " 1372 check_balance \ 1373 "aggregation_total_arithmetic_delta_minus" \ 1374 "TESTKUDOS:0" \ 1375 "Wrong arithmetic delta minus from aggregations" 1376 1377 echo -n "Checking for unexpected coin delta plus differences... " 1378 check_balance \ 1379 "coins_total_arithmetic_delta_plus" \ 1380 "TESTKUDOS:0" \ 1381 "Wrong arithmetic delta plus from coins" 1382 1383 echo -n "Checking for unexpected coin delta minus differences... " 1384 check_balance \ 1385 "coins_total_arithmetic_delta_minus" \ 1386 "TESTKUDOS:0" \ 1387 "Wrong arithmetic delta minus from coins" 1388 1389 echo -n "Checking for unexpected reserves delta plus... " 1390 check_balance \ 1391 "reserves_total_arithmetic_delta_plus" \ 1392 "TESTKUDOS:0" \ 1393 "Wrong arithmetic delta plus from reserves" 1394 1395 echo -n "Checking for unexpected reserves delta minus... " 1396 check_balance \ 1397 "reserves_total_arithmetic_delta_minus" \ 1398 "TESTKUDOS:0" \ 1399 "Wrong arithmetic delta minus from reserves" 1400 1401 echo -n "Checking amount arithmetic inconsistency" 1402 check_no_report "amount-arithmetic-inconsistencies" 1403 1404 echo -n "Checking for unexpected wire out differences " 1405 check_no_report "wire-out-inconsistencies" 1406 1407 echo -n "Checking total drained... " 1408 check_balance \ 1409 "total_drained" \ 1410 "TESTKUDOS:0.1" \ 1411 "Wrong total drained amount reported" 1412 # cannot easily undo aggregator, hence full reload 1413 full_reload 1414 } 1415 1416 1417 # Test for wrong signature on refresh. 1418 function test_13() { 1419 1420 echo "===========13: wrong melt signature ===========" 1421 # Modify denom_sig, so it is wrong 1422 COIN_PUB=$(echo "SELECT old_coin_pub FROM exchange.refresh LIMIT 1;" | psql "$DB" -Aqt) 1423 OLD_SIG=$(echo "SELECT old_coin_sig FROM exchange.refresh WHERE old_coin_pub='$COIN_PUB';" | psql "$DB" -Aqt) 1424 NEW_SIG="\xba588af7c13c477dca1ac458f65cc484db8fba53b969b873f4353ecbd815e6b4c03f42c0cb63a2b609c2d726e612fd8e0c084906a41f409b6a23a08a83c89a02" 1425 echo "UPDATE exchange.refresh SET old_coin_sig='$NEW_SIG' WHERE old_coin_pub='$COIN_PUB'" \ 1426 | psql -Aqt "$DB" 1427 1428 run_audit 1429 check_auditor_running 1430 1431 echo -n "Testing inconsistency detection... " 1432 1433 check_report \ 1434 "bad-sig-losses" \ 1435 "operation" "melt" 1436 echo -n "Checking loss amount reported ..." 1437 check_report \ 1438 "bad-sig-losses" \ 1439 "loss" "TESTKUDOS:3.96" 1440 echo -n "Checking loss amount totaled ..." 1441 check_balance \ 1442 "coin_irregular_loss" \ 1443 "TESTKUDOS:3.96" \ 1444 "Loss inconsistent" 1445 1446 # cannot easily undo DELETE, hence full reload 1447 full_reload 1448 } 1449 1450 1451 # Test for wire fee disagreement 1452 function test_14() { 1453 1454 echo "===========14: wire-fee disagreement===========" 1455 1456 # Wire fees are only checked/generated once there are 1457 # actual outgoing wire transfers, so we need to run the 1458 # aggregator here. 1459 pre_audit aggregator 1460 echo "UPDATE exchange.wire_fee SET wire_fee.frac=100 WHERE wire_fee_serial=1;" \ 1461 | psql -Aqt "$DB" 1462 audit_only 1463 post_audit 1464 check_auditor_running 1465 1466 echo -n "Checking wire-fee inconsistency was detected ..." 1467 check_report \ 1468 "row-inconsistencies" \ 1469 "row_table" "wire-fee" 1470 echo -n "Checking diagnostic was set correctly ..." 1471 check_report \ 1472 "row-inconsistencies" \ 1473 "diagnostic" "wire fee signature invalid at given time" 1474 1475 # cannot easily undo aggregator, hence full reload 1476 full_reload 1477 } 1478 1479 1480 # Test where salt in the deposit table is wrong 1481 function test_15() { 1482 echo "===========15: deposit wire salt wrong=================" 1483 1484 # Modify wire_salt hash, so it is inconsistent 1485 ##SALT=$(echo "SELECT wire_salt FROM exchange.deposits WHERE deposit_serial_id=1;" | psql -Aqt "$DB") 1486 SALT=$(echo "SELECT wire_salt FROM exchange.batch_deposits WHERE batch_deposit_serial_id=1;" | psql -Aqt "$DB") 1487 # shellcheck disable=SC2028 1488 echo "UPDATE exchange.batch_deposits SET wire_salt='\x1197cd7f7b0e13ab1905fedb36c536a2' WHERE batch_deposit_serial_id=1;" \ 1489 | psql -Aqt "$DB" 1490 1491 run_audit 1492 check_auditor_running 1493 1494 echo -n "Checking broken deposit signature detected ..." 1495 check_report \ 1496 "bad-sig-losses" \ 1497 "operation" "deposit" 1498 1499 # Restore DB 1500 echo "UPDATE exchange.batch_deposits SET wire_salt='$SALT' WHERE batch_deposit_serial_id=1;" \ 1501 | psql -Aqt "$DB" 1502 stop_auditor_httpd 1503 1504 } 1505 1506 1507 # Test where wired amount (wire out) is wrong 1508 function test_16() { 1509 echo "===========16: incorrect wire_out amount=================" 1510 1511 # First, we need to run the aggregator so we even 1512 # have a wire_out to modify. 1513 pre_audit aggregator 1514 check_auditor_running 1515 stop_libeufin 1516 OLD_AMOUNT_VAL=$(echo "SELECT (amount).val FROM libeufin_bank.bank_account_transactions WHERE debtor_name='Exchange Company' AND direction='debit';" | psql "${DB}" -Aqt) 1517 OLD_AMOUNT_FRAC=$(echo "SELECT (amount).frac FROM libeufin_bank.bank_account_transactions WHERE debtor_name='Exchange Company' AND direction='debit';" | psql "${DB}" -Aqt) 1518 if [[ 0 = "$OLD_AMOUNT_FRAC" ]] 1519 then 1520 OLD_AMOUNT="TESTKUDOS:${OLD_AMOUNT_VAL}" 1521 else 1522 OLD_AMOUNT_CENTS=$(($OLD_AMOUNT_FRAC / 1000000)) 1523 if [[ 10 -gt "$OLD_AMOUNT_CENTS" ]] 1524 then 1525 OLD_AMOUNT="TESTKUDOS:${OLD_AMOUNT_VAL}.0${OLD_AMOUNT_CENTS}" 1526 else 1527 OLD_AMOUNT="TESTKUDOS:${OLD_AMOUNT_VAL}.${OLD_AMOUNT_CENTS}" 1528 fi 1529 fi 1530 NEW_AMOUNT="TESTKUDOS:50" 1531 echo "UPDATE libeufin_bank.bank_account_transactions SET amount=(50,0) WHERE debtor_name='Exchange Company';" \ 1532 | psql "${DB}" -q 1533 launch_libeufin 1534 await_bank 1535 1536 audit_only 1537 check_auditor_running 1538 1539 echo -n "Testing wire-out-inconsistency-expected... " 1540 check_report \ 1541 "wire-out-inconsistencies" \ 1542 "expected" \ 1543 "$OLD_AMOUNT" 1544 echo -n "Testing wire-out-inconsistency-claimed... " 1545 check_report \ 1546 "wire-out-inconsistencies" \ 1547 "claimed" \ 1548 "$NEW_AMOUNT" 1549 echo -n "Testing bad_amount_minus balance reporting... " 1550 check_balance \ 1551 "total_bad_amount_out_minus" \ 1552 "TESTKUDOS:0" \ 1553 "reported total_bad_amount_minus wrong" 1554 echo -n "Testing bad_amount_plus balance reporting... " 1555 check_not_balance \ 1556 "total_bad_amount_out_plus" \ 1557 "TESTKUDOS:0" \ 1558 "reported total_bad_amount_plus wrong" 1559 1560 stop_libeufin 1561 echo "Second modification: wire nothing" 1562 NEW_AMOUNT="TESTKUDOS:0" 1563 echo "UPDATE libeufin_bank.bank_account_transactions SET amount=(0,0) WHERE debtor_name='Exchange Company';" \ 1564 | psql "${DB}" -q 1565 launch_libeufin 1566 audit_only 1567 stop_libeufin 1568 1569 echo -n "Testing wire-out-inconsistency-expected... " 1570 check_report \ 1571 "wire-out-inconsistencies" \ 1572 "expected" \ 1573 "$OLD_AMOUNT" 1574 echo -n "Testing wire-out-inconsistency-claimed... " 1575 check_report \ 1576 "wire-out-inconsistencies" \ 1577 "claimed" \ 1578 "$NEW_AMOUNT" 1579 echo -n "Testing bad_amount_minus balance reporting... " 1580 check_balance \ 1581 "total_bad_amount_out_minus" \ 1582 "$OLD_AMOUNT" \ 1583 "reported total_bad_amount_minus wrong" 1584 echo -n "Testing bad_amount_plus balance reporting... " 1585 check_balance \ 1586 "total_bad_amount_out_plus" \ 1587 "TESTKUDOS:0" \ 1588 "reported total_bad_amount_plus wrong" 1589 1590 post_audit 1591 1592 # cannot easily undo aggregator, hence full reload 1593 full_reload 1594 } 1595 1596 1597 # Test where wire-out timestamp is wrong 1598 function test_17() { 1599 echo "===========17: incorrect wire_out timestamp=================" 1600 1601 # First, we need to run the aggregator so we even 1602 # have a wire_out to modify. 1603 pre_audit aggregator 1604 stop_libeufin 1605 1606 echo -n "Modifying timestamp of existing wire_out transaction... " 1607 OLD_DATE=$(echo "SELECT transaction_date FROM libeufin_bank.bank_account_transactions WHERE debtor_name='Exchange Company' AND direction='debit';" | psql "${DB}" -Aqt) 1608 # Note: need - interval '1h' as "NOW()" may otherwise be exactly what is already in the DB 1609 # (due to rounding, if this machine is fast...) 1610 NOW_1HR=$(( $(date +%s) - 3600)) 1611 1612 echo "UPDATE libeufin_bank.bank_account_transactions SET transaction_date='${NOW_1HR}000000' WHERE debtor_name='Exchange Company';" \ 1613 | psql "${DB}" -q 1614 echo "DONE" 1615 1616 launch_libeufin 1617 await_bank 1618 audit_only 1619 post_audit 1620 check_auditor_running 1621 1622 echo -n "Testing inconsistency detection... " 1623 check_report \ 1624 row-minor-inconsistencies \ 1625 "row_table" "wire_out" 1626 1627 echo -n "Testing inconsistency diagnostic... " 1628 call_endpoint "row-minor-inconsistencies" 1629 DIAG=$(jq -r .records[0].diagnostic < "${MY_TMP_DIR}/row-minor-inconsistencies.json" | awk '{print $1 " " $2 " " $3}') 1630 if [ "$DIAG" != "execution date mismatch" ] 1631 then 1632 exit_fail "Reported diagnostic wrong: $DIAG" 1633 fi 1634 echo "PASS" 1635 1636 # cannot easily undo aggregator, hence full reload 1637 full_reload 1638 } 1639 1640 1641 # Test where we trigger an emergency. 1642 function test_18() { 1643 echo "===========18: emergency=================" 1644 1645 echo "DELETE FROM exchange.withdraw;" \ 1646 | psql -Aqt "$DB" -q 1647 1648 run_audit 1649 check_auditor_running 1650 1651 echo -n "Testing bad reserve balance summary reporting ... " 1652 # note: we check "suppressed" to only check the *existence* here. 1653 check_report \ 1654 "reserve-balance-summary-wrong-inconsistencies" \ 1655 "suppressed" "false" 1656 echo -n "Testing emergency detection... " 1657 check_report \ 1658 "emergencies" \ 1659 "suppressed" "false" 1660 echo -n "Testing emergency detection by count... " 1661 check_report \ 1662 "emergencies-by-count" \ 1663 "suppressed" "false" 1664 echo -n "Testing escrow balance calculation impossibility... " 1665 check_report \ 1666 "amount-arithmetic-inconsistencies" \ 1667 "suppressed" "false" 1668 echo -n "Testing loss calculation by count... " 1669 check_not_balance \ 1670 "coins_emergencies_loss_by_count" \ 1671 "TESTKUDOS:0" \ 1672 "Emergency by count loss not reported" 1673 echo -n "Testing loss calculation... " 1674 check_not_balance \ 1675 "coins_emergencies_loss" \ 1676 "TESTKUDOS:0" \ 1677 "Emergency loss not reported" 1678 # cannot easily undo broad DELETE operation, hence full reload 1679 full_reload 1680 } 1681 1682 1683 # Test where reserve closure was done properly 1684 function test_19() { 1685 echo "===========19: reserve closure done properly =================" 1686 1687 OLD_TIME=$(echo "SELECT execution_date FROM exchange.reserves_in WHERE reserve_in_serial_id=1;" | psql "$DB" -Aqt) 1688 OLD_VAL=$(echo "SELECT (credit).val FROM exchange.reserves_in WHERE reserve_in_serial_id=1;" | psql "$DB" -Aqt) 1689 RES_PUB=$(echo "SELECT reserve_pub FROM exchange.reserves_in WHERE reserve_in_serial_id=1;" | psql "$DB" -Aqt) 1690 OLD_EXP=$(echo "SELECT expiration_date FROM exchange.reserves WHERE reserve_pub='${RES_PUB}';" | psql "$DB" -Aqt) 1691 VAL_DELTA=1 1692 NEW_TIME=$(( OLD_TIME - 3024000000000)) # 5 weeks 1693 NEW_EXP=$(( OLD_EXP - 3024000000000)) # 5 weeks 1694 NEW_CREDIT=$(( OLD_VAL + VAL_DELTA)) 1695 echo "UPDATE exchange.reserves_in SET execution_date='${NEW_TIME}',credit.val=${NEW_CREDIT} WHERE reserve_in_serial_id=1;" \ 1696 | psql -Aqt "$DB" 1697 echo "UPDATE exchange.reserves SET current_balance.val=${VAL_DELTA}+(current_balance).val,expiration_date='${NEW_EXP}' WHERE reserve_pub='${RES_PUB}';" \ 1698 | psql -Aqt "$DB" 1699 # Need to run with the aggregator so the reserve closure happens 1700 run_audit aggregator 1701 check_auditor_running 1702 1703 echo -n "Testing reserve closure was done correctly... " 1704 check_no_report "reserve-not-closed-inconsistencies" 1705 echo -n "Testing no bogus transfers detected... " 1706 check_no_report "wire-out-inconsistencies" 1707 1708 # cannot easily undo aggregator, hence full reload 1709 full_reload 1710 } 1711 1712 1713 # Test where reserve closure was not done properly 1714 function test_20() { 1715 echo "===========20: reserve closure missing =================" 1716 1717 OLD_TIME=$(echo "SELECT execution_date FROM exchange.reserves_in WHERE reserve_in_serial_id=1;" | psql "$DB" -Aqt) 1718 OLD_VAL=$(echo "SELECT (credit).val FROM exchange.reserves_in WHERE reserve_in_serial_id=1;" | psql "$DB" -Aqt) 1719 RES_PUB=$(echo "SELECT reserve_pub FROM exchange.reserves_in WHERE reserve_in_serial_id=1;" | psql "$DB" -Aqt) 1720 NEW_TIME=$(( OLD_TIME - 3024000000000 )) # 5 weeks 1721 NEW_CREDIT=$(( OLD_VAL + 100 )) 1722 echo "UPDATE exchange.reserves_in SET execution_date='${NEW_TIME}',credit.val=${NEW_CREDIT} WHERE reserve_in_serial_id=1;" \ 1723 | psql -Aqt "$DB" 1724 echo "UPDATE exchange.reserves SET current_balance.val=100+(current_balance).val WHERE reserve_pub='${RES_PUB}';" \ 1725 | psql -Aqt "$DB" 1726 1727 # This time, run without the aggregator so the reserve closure is skipped! 1728 run_audit 1729 check_auditor_running 1730 1731 echo -n "Testing reserve closure missing detected... " 1732 check_report \ 1733 "reserve-not-closed-inconsistencies" \ 1734 "suppressed" "false" 1735 echo -n "Testing balance updated correctly... " 1736 check_not_balance \ 1737 "total_balance_reserve_not_closed" \ 1738 "TESTKUDOS:0" \ 1739 "Reported total amount wrong" 1740 1741 # Undo 1742 echo "UPDATE exchange.reserves_in SET execution_date='${OLD_TIME}',credit.val=${OLD_VAL} WHERE reserve_in_serial_id=1;" \ 1743 | psql -Aqt "$DB" 1744 echo "UPDATE exchange.reserves SET current_balance.val=(current_balance).val-100 WHERE reserve_pub='${RES_PUB}';" \ 1745 | psql -Aqt "$DB" 1746 1747 full_reload 1748 } 1749 1750 1751 # Test reserve closure reported but wire transfer missing detection 1752 function test_21() { 1753 echo "===========21: reserve closure missreported =================" 1754 1755 OLD_TIME=$(echo "SELECT execution_date FROM exchange.reserves_in WHERE reserve_in_serial_id=1;" | psql "$DB" -Aqt) 1756 OLD_VAL=$(echo "SELECT (credit).val FROM exchange.reserves_in WHERE reserve_in_serial_id=1;" | psql "$DB" -Aqt) 1757 RES_PUB=$(echo "SELECT reserve_pub FROM exchange.reserves_in WHERE reserve_in_serial_id=1;" | psql "$DB" -Aqt) 1758 OLD_EXP=$(echo "SELECT expiration_date FROM exchange.reserves WHERE reserve_pub='${RES_PUB}';" | psql "$DB" -Aqt) 1759 VAL_DELTA=1 1760 NEW_TIME=$(( OLD_TIME - 3024000000000 )) # 5 weeks 1761 NEW_EXP=$(( OLD_EXP - 3024000000000 )) # 5 weeks 1762 NEW_CREDIT=$(( OLD_VAL + VAL_DELTA )) 1763 echo "UPDATE exchange.reserves_in SET execution_date='${NEW_TIME}',credit.val=${NEW_CREDIT} WHERE reserve_in_serial_id=1;" \ 1764 | psql -Aqt "$DB" 1765 echo "UPDATE exchange.reserves SET current_balance.val=${VAL_DELTA}+(current_balance).val,expiration_date='${NEW_EXP}' WHERE reserve_pub='${RES_PUB}';" \ 1766 | psql -Aqt "$DB" 1767 1768 # Need to first run the aggregator so the transfer is marked as done 1769 pre_audit aggregator 1770 stop_libeufin 1771 1772 # remove wire transfer from bank DB 1773 echo "DELETE FROM libeufin_bank.bank_account_transactions WHERE debtor_name='Exchange Company';" \ 1774 | psql "${DB}" -q 1775 1776 launch_libeufin 1777 audit_only 1778 post_audit 1779 check_auditor_running 1780 1781 echo -n "Testing reserve_in inconsistency detection... " 1782 check_report \ 1783 row-minor-inconsistencies \ 1784 "row_table" "reserves_in" 1785 1786 echo -n "Testing lack of reserve closure transaction detected... " 1787 check_report \ 1788 "closure-lags" \ 1789 "suppressed" "false" 1790 echo -n "Checking closure lag amount ..." 1791 check_report \ 1792 "closure-lags" \ 1793 "amount" "TESTKUDOS:${VAL_DELTA}" 1794 echo -n "Checking closure lag total balance ..." 1795 check_balance \ 1796 "total_closure_amount_lag" \ 1797 "TESTKUDOS:${VAL_DELTA}" \ 1798 "Reported total_closure_amount_lag wrong" 1799 # cannot easily undo aggregator, hence full reload 1800 full_reload 1801 } 1802 1803 1804 # Test use of withdraw-expired denomination key 1805 function test_22() { 1806 echo "===========22: denomination key expired =================" 1807 1808 S_DENOM=$(echo 'SELECT denom_serials[1] FROM exchange.withdraw LIMIT 1;' | psql "$DB" -Aqt) 1809 1810 OLD_START=$(echo "SELECT valid_from FROM exchange.denominations WHERE denominations_serial='${S_DENOM}';" | psql "$DB" -Aqt) 1811 OLD_WEXP=$(echo "SELECT expire_withdraw FROM exchange.denominations WHERE denominations_serial='${S_DENOM}';" | psql "$DB" -Aqt) 1812 # Basically expires 'immediately', so that the withdraw must have been 'invalid' 1813 NEW_WEXP=$OLD_START 1814 1815 echo "UPDATE exchange.denominations SET expire_withdraw=${NEW_WEXP} WHERE denominations_serial='${S_DENOM}';" | psql -Aqt "$DB" 1816 1817 1818 run_audit 1819 check_auditor_running 1820 1821 echo -n "Testing inconsistency detection... " 1822 check_report \ 1823 "denomination-key-validity-withdraw-inconsistencies" \ 1824 "suppressed" "false" 1825 call_endpoint "denomination-key-validity-withdraw-inconsistencies" 1826 1827 # Undo modification 1828 echo "UPDATE exchange.denominations SET expire_withdraw=${OLD_WEXP} WHERE denominations_serial='${S_DENOM}';" | psql -Aqt "$DB" 1829 1830 full_reload 1831 } 1832 1833 1834 # Test calculation of wire-out amounts 1835 function test_23() { 1836 echo "===========23: wire out calculations =================" 1837 1838 # Need to first run the aggregator so the transfer is marked as done exists 1839 pre_audit aggregator 1840 1841 OLD_AMOUNT=$(echo "SELECT (amount).frac FROM exchange.wire_out WHERE wireout_uuid=1;" | psql "$DB" -Aqt) 1842 NEW_AMOUNT=$(( OLD_AMOUNT - 1000000 )) 1843 echo "UPDATE exchange.wire_out SET amount.frac=${NEW_AMOUNT} WHERE wireout_uuid=1;" \ 1844 | psql -Aqt "$DB" 1845 1846 audit_only 1847 post_audit 1848 check_auditor_running 1849 1850 echo -n "Testing inconsistency detection... " 1851 check_report \ 1852 "wire-out-inconsistencies" \ 1853 "suppressed" "false" 1854 echo -n "Testing inconsistency row report... " 1855 check_report \ 1856 "wire-out-inconsistencies" \ 1857 "wire_out_row_id" "1" 1858 echo -n "Testing inconsistency balance... " 1859 check_balance \ 1860 "aggregation_total_wire_out_delta_plus" \ 1861 "TESTKUDOS:0" \ 1862 "Reported aggregation_total_wire_out_delta_plus wrong" 1863 echo -n "Testing inconsistency balance change ... " 1864 check_balance \ 1865 "aggregation_total_wire_out_delta_minus" \ 1866 "TESTKUDOS:0.01" \ 1867 "Reported aggregation_total_wire_out_delta_minus wrong" 1868 1869 echo "Second pass: changing how amount is wrong to other direction" 1870 NEW_AMOUNT=$(( OLD_AMOUNT + 1000000 )) 1871 echo "UPDATE exchange.wire_out SET amount.frac=${NEW_AMOUNT} WHERE wireout_uuid=1;" | psql -Aqt "$DB" 1872 1873 pre_audit 1874 audit_only 1875 post_audit 1876 1877 echo -n "Testing inconsistency detection... " 1878 1879 echo -n "Testing inconsistency detection... " 1880 check_report \ 1881 "wire-out-inconsistencies" \ 1882 "suppressed" "false" 1883 echo -n "Testing inconsistency row report... " 1884 check_report \ 1885 "wire-out-inconsistencies" \ 1886 "wire_out_row_id" "1" 1887 echo -n "Testing inconsistency balance... " 1888 check_balance \ 1889 "aggregation_total_wire_out_delta_plus" \ 1890 "TESTKUDOS:0.01" \ 1891 "Reported aggregation_total_wire_out_delta_plus wrong" 1892 echo -n "Testing inconsistency balance change ... " 1893 check_balance \ 1894 "aggregation_total_wire_out_delta_minus" \ 1895 "TESTKUDOS:0" \ 1896 "Reported aggregation_total_wire_out_delta_minus wrong" 1897 1898 # cannot easily undo aggregator, hence full reload 1899 full_reload 1900 } 1901 1902 1903 # Test for missing deposits in exchange database. 1904 function test_24() { 1905 echo "===========24: deposits missing ===========" 1906 # Modify denom_sig, so it is wrong 1907 CNT=$(echo "SELECT COUNT(*) FROM auditor.auditor_deposit_confirmations;" | psql -Aqt "$DB") 1908 if [ "$CNT" = "0" ] 1909 then 1910 echo "Skipping deposits missing test: no deposit confirmations in database!" 1911 else 1912 echo "DELETE FROM exchange.batch_deposits;" | psql -Aqt "$DB" 1913 echo "DELETE FROM exchange.batch_deposits WHERE batch_deposit_serial_id=1;" \ 1914 | psql -Aqt "$DB" 1915 1916 run_audit 1917 check_auditor_running 1918 1919 echo -n "Testing inconsistency detection... " 1920 call_endpoint "balances" 1921 check_report \ 1922 "deposit-confirmations" \ 1923 "suppressed" "false" 1924 echo -n "Testing inconsistency detection balance change ... " 1925 check_not_balance \ 1926 "total_missed_deposit_confirmations" \ 1927 "TESTKUDOS:0" \ 1928 "Expected non-zero total missing deposit confirmation amount" 1929 # cannot easily undo DELETE, hence full reload 1930 full_reload 1931 fi 1932 } 1933 1934 1935 # Test for inconsistent coin history. 1936 function test_25() { 1937 1938 echo "=========25: inconsistent coin history=========" 1939 1940 # Drop refund, so coin history is bogus. 1941 echo -n "Dropping refund from DB... " 1942 echo "DELETE FROM exchange.refunds WHERE refund_serial_id=1;" \ 1943 | psql -At "$DB" 1944 1945 run_audit aggregator 1946 check_auditor_running 1947 1948 echo -n "Testing inconsistency detection... " 1949 check_report \ 1950 "coin-inconsistencies" \ 1951 "profitable" "true" 1952 echo -n "Testing emergency risk reporting... " 1953 check_report \ 1954 "emergencies" \ 1955 "denom_risk" "TESTKUDOS:10" 1956 echo -n "Testing emergency loss reporting... " 1957 # The dropped refund covered coin deposit #2, so the deposit's full 1958 # amount is what the denomination is now short of. 1959 check_report \ 1960 "emergencies" \ 1961 "denom_loss" "TESTKUDOS:7.02" 1962 echo -n "Testing double-spending reporting... " 1963 check_balance \ 1964 "coins_reported_emergency_risk_by_amount" \ 1965 "TESTKUDOS:10" \ 1966 "double-spending not detected" 1967 echo -n "Testing balance loss update... " 1968 check_balance \ 1969 "aggregation_total_coin_delta_minus" \ 1970 "TESTKUDOS:5.98" \ 1971 "aggregation total coin delta minus not reported" 1972 # cannot easily undo DELETE, hence full reload 1973 full_reload 1974 } 1975 1976 1977 # Test for deposit wire target malformed 1978 function test_26() { 1979 echo "===========26: deposit wire target malformed =================" 1980 1981 # Expects 'payto_uri', not 'url' (also breaks signature, but we cannot even check that). 1982 SERIAL=$(echo "SELECT batch_deposit_serial_id FROM exchange.coin_deposits WHERE (amount_with_fee).val=3 ORDER BY batch_deposit_serial_id LIMIT 1" | psql "$DB" -Aqt) 1983 OLD_WIRE_ID=$(echo "SELECT wire_target_h_payto FROM exchange.batch_deposits WHERE batch_deposit_serial_id=${SERIAL};" | psql "$DB" -Aqt) 1984 # shellcheck disable=SC2028 1985 echo "INSERT INTO exchange.wire_targets (payto_uri, wire_target_h_payto) VALUES ('payto://x-taler-bank/localhost/testuser-xxlargtp', '\x1e8f31936b3cee8f8afd3aac9e38b5db42d45b721ffc4eb1e5b9ddaf1565660b');" \ 1986 | psql "$DB" -Aqt 1987 # shellcheck disable=SC2028 1988 echo "UPDATE exchange.batch_deposits SET wire_target_h_payto='\x1e8f31936b3cee8f8afd3aac9e38b5db42d45b721ffc4eb1e5b9ddaf1565660b' WHERE batch_deposit_serial_id=${SERIAL};" \ 1989 | psql -Aqt "$DB" 1990 1991 run_audit 1992 check_auditor_running 1993 1994 check_balance \ 1995 "coin_irregular_loss" \ 1996 "TESTKUDOS:3.02" \ 1997 "wrong total irregular coin loss" 1998 call_endpoint "bad-sig-losses" 1999 echo -n "Checking correct operation of loss reported... " 2000 check_report \ 2001 "bad-sig-losses" \ 2002 "operation" "deposit" 2003 echo -n "Checking correct loss reported... " 2004 check_report \ 2005 "bad-sig-losses" \ 2006 "loss" "TESTKUDOS:3.02" 2007 echo -n "Checking correct problem row ID reported... " 2008 check_report \ 2009 "bad-sig-losses" \ 2010 "problem_row_id" "$SERIAL" 2011 2012 # Undo: 2013 echo "UPDATE exchange.batch_deposits SET wire_target_h_payto='$OLD_WIRE_ID' WHERE batch_deposit_serial_id=${SERIAL}" \ 2014 | psql -Aqt "$DB" 2015 } 2016 2017 2018 # Test where denom_sig in known_coins table is wrong 2019 # (=> bad signature) AND the coin is used in aggregation 2020 function test_27() { 2021 2022 echo "===========27: known_coins signature wrong=================" 2023 # Modify denom_sig, so it is wrong 2024 OLD_SIG=$(echo 'SELECT denom_sig FROM exchange.known_coins LIMIT 1;' | psql "$DB" -Aqt) 2025 COIN_PUB=$(echo "SELECT coin_pub FROM exchange.known_coins WHERE denom_sig='$OLD_SIG';" | psql "$DB" -Aqt) 2026 # shellcheck disable=SC2028 2027 echo "UPDATE exchange.known_coins SET denom_sig='\x0000000100000000287369672d76616c200a2028727361200a2020287320233542383731423743393036444643303442424430453039353246413642464132463537303139374131313437353746324632323332394644443146324643333445393939413336363430334233413133324444464239413833353833464536354442374335434445304441453035374438363336434541423834463843323843344446304144363030343430413038353435363039373833434431333239393736423642433437313041324632414132414435413833303432434346314139464635394244434346374436323238344143354544364131373739463430353032323241373838423837363535453434423145443831364244353638303232413123290a2020290a20290b' WHERE coin_pub='$COIN_PUB'" \ 2028 | psql -Aqt "$DB" 2029 2030 run_audit aggregator 2031 check_auditor_running 2032 2033 echo -n "Testing inconsistency detection... " 2034 check_report_neg \ 2035 "bad-sig-losses" \ 2036 "loss" "TESTKUDOS:0" 2037 echo -n "Testing inconsistency detection operation attribution... " 2038 check_report \ 2039 "bad-sig-losses" \ 2040 "operation" "wire" 2041 echo -n "Testing table attribution for inconsistency... " 2042 check_report \ 2043 "row-inconsistencies" \ 2044 "row_table" "deposit" 2045 echo -n "Check signature loss was accumulated ..." 2046 check_not_balance \ 2047 "aggregation_total_bad_sig_loss" \ 2048 "TESTKUDOS:0" \ 2049 "Wrong aggregation_total_bad_sig_loss" 2050 2051 # cannot easily undo aggregator, hence full reload 2052 full_reload 2053 } 2054 2055 2056 2057 # Test where fees known to the auditor differ from those 2058 # accounted for by the exchange 2059 function test_28() { 2060 echo "===========28: withdraw fee inconsistency =================" 2061 2062 echo "UPDATE exchange.withdraw SET amount_with_fee.val=(amount_with_fee).val+1 WHERE withdraw_id=1;" | psql -Aqt "$DB" 2063 2064 run_audit 2065 check_auditor_running 2066 2067 echo -n "Testing inconsistency detection... " 2068 check_report \ 2069 "row-inconsistencies" \ 2070 "row_table" "withdraw" 2071 # Undo 2072 full_reload 2073 } 2074 2075 2076 # Test where fees known to the auditor differ from those 2077 # accounted for by the exchange 2078 function test_29() { 2079 echo "===========29: melt fee inconsistency =================" 2080 2081 echo "UPDATE exchange.denominations SET fee_refresh.frac=5000000 WHERE (coin).val=10;" | psql -Aqt "$DB" 2082 2083 run_audit 2084 check_auditor_running 2085 2086 echo -n "Testing inconsistency detection... " 2087 check_report_neg \ 2088 "bad-sig-losses" \ 2089 "loss" "TESTKUDOS:0" 2090 echo -n "Testing inconsistency was reported as profitable... " 2091 check_report \ 2092 "amount-arithmetic-inconsistencies" \ 2093 "profitable" "true" 2094 echo -n "Testing no emergency was raised... " 2095 check_no_report "emergencies" 2096 2097 # Undo 2098 echo "UPDATE exchange.denominations SET fee_refresh.frac=3000000 WHERE (coin).val=10;" | psql -Aqt "$DB" 2099 2100 full_reload 2101 } 2102 2103 2104 # Test where fees known to the auditor differ from those 2105 # accounted for by the exchange 2106 function test_30() { 2107 echo "===========30: deposit fee inconsistency =================" 2108 2109 echo "UPDATE exchange.denominations SET fee_deposit.frac=5000000 WHERE (coin).val=8;" | psql -Aqt "$DB" 2110 2111 run_audit aggregator 2112 check_auditor_running 2113 2114 echo -n "Testing inconsistency detection... " 2115 2116 check_not_balance \ 2117 "coin_irregular_loss" \ 2118 "TESTKUDOS:0" \ 2119 "Reported total coin_irregular_loss wrong" 2120 check_report \ 2121 "bad-sig-losses" \ 2122 "operation" "deposit" 2123 # Undo 2124 echo "UPDATE exchange.denominations SET fee_deposit.frac=2000000 WHERE (coin).val=8;" | psql -Aqt "$DB" 2125 full_reload 2126 } 2127 2128 2129 2130 2131 # Test where denom_sig in known_coins table is wrong 2132 # (=> bad signature) 2133 function test_31() { 2134 echo "===========31: known_coins signature wrong w. aggregation=================" 2135 # Modify denom_sig, so it is wrong 2136 OLD_SIG=$(echo 'SELECT denom_sig FROM exchange.known_coins LIMIT 1;' | psql "$DB" -Aqt) 2137 COIN_PUB=$(echo "SELECT coin_pub FROM exchange.known_coins WHERE denom_sig='$OLD_SIG';" | psql "$DB" -Aqt) 2138 # shellcheck disable=SC2028 2139 echo "UPDATE exchange.known_coins SET denom_sig='\x0000000100000000287369672d76616c200a2028727361200a2020287320233542383731423743393036444643303442424430453039353246413642464132463537303139374131313437353746324632323332394644443146324643333445393939413336363430334233413133324444464239413833353833464536354442374335434445304441453035374438363336434541423834463843323843344446304144363030343430413038353435363039373833434431333239393736423642433437313041324632414132414435413833303432434346314139464635394244434346374436323238344143354544364131373739463430353032323241373838423837363535453434423145443831364244353638303232413123290a2020290a20290b' WHERE coin_pub='$COIN_PUB'" \ 2140 | psql -Aqt "$DB" 2141 2142 run_audit aggregator 2143 check_auditor_running 2144 2145 echo -n "Testing inconsistency detection... " 2146 check_report \ 2147 "bad-sig-losses" \ 2148 "operation" "wire" 2149 echo -n "Testing inconsistency balance update... " 2150 check_not_balance \ 2151 "aggregation_total_bad_sig_loss" \ 2152 "TESTKUDOS:0" \ 2153 "Missed updating aggregation_total_bad_sig_loss" 2154 2155 # Cannot undo aggregation, do full reload 2156 full_reload 2157 cleanup 2158 } 2159 2160 2161 # *************** Main test loop starts here ************** 2162 2163 2164 # Run all the tests against the database given in $1. 2165 # Sets $fail to 0 on success, non-zero on failure. 2166 function check_with_database() 2167 { 2168 BASEDB="$1" 2169 CONF="$1.conf" 2170 export CONF 2171 echo "Running test suite with database $BASEDB using configuration $CONF" 2172 MASTER_PRIV_FILE="${BASEDB}.mpriv" 2173 taler-exchange-config \ 2174 -f \ 2175 -c "${CONF}" \ 2176 -s exchange-offline \ 2177 -o MASTER_PRIV_FILE \ 2178 -V "${MASTER_PRIV_FILE}" 2179 2180 # Load database 2181 full_reload 2182 2183 # Run test suite 2184 fail=0 2185 for i in $TESTS 2186 do 2187 "test_$i" 2188 if test 0 != $fail 2189 then 2190 break 2191 fi 2192 done 2193 echo "Cleanup (disabled, leaving database $DB behind)" 2194 # dropdb $DB 2195 } 2196 2197 # When the script is not run as root, setup a temporary directory for the 2198 # postgres database. 2199 # Sets PGHOST accordingly to the freshly created socket. 2200 function perform_initdb() { 2201 # Available directly in path? 2202 INITDB_BIN=$(command -v initdb) || true 2203 if [[ -n "$INITDB_BIN" ]]; then 2204 echo " FOUND (in path) at $INITDB_BIN" 2205 else 2206 HAVE_INITDB=$(find /usr -name "initdb" 2> /dev/null \ 2207 | head -1 2> /dev/null \ 2208 | grep postgres) \ 2209 || exit_skip " MISSING" 2210 echo " FOUND at $(dirname "$HAVE_INITDB")" 2211 INITDB_BIN=$(echo "$HAVE_INITDB" | grep bin/initdb | grep postgres | sort -n | tail -n1) 2212 fi 2213 POSTGRES_PATH=$(dirname "$INITDB_BIN") 2214 2215 TMPDIR="$MY_TMP_DIR/postgres" 2216 mkdir -p "$TMPDIR" 2217 echo -n "Setting up Postgres DB at $TMPDIR ..." 2218 $INITDB_BIN \ 2219 --no-sync \ 2220 --auth=trust \ 2221 -D "${TMPDIR}" \ 2222 > "${MY_TMP_DIR}/postgres-dbinit.log" \ 2223 2> "${MY_TMP_DIR}/postgres-dbinit.err" \ 2224 || { 2225 echo "FAILED!" 2226 echo "Last entries in ${MY_TMP_DIR}/postgres-dbinit.err:" 2227 tail "${MY_TMP_DIR}/postgres-dbinit.err" 2228 exit 1 2229 } 2230 echo "DONE" 2231 2232 # Once we move to PG16, we can use: 2233 # --set listen_addresses='' \ 2234 # --set fsync=off \ 2235 # --set max_wal_senders=0 \ 2236 # --set synchronous_commit=off \ 2237 # --set wal_level=minimal \ 2238 # --set unix_socket_directories="${TMPDIR}/sockets" \ 2239 2240 2241 SOCKETDIR="${TMPDIR}/sockets" 2242 mkdir "${SOCKETDIR}" 2243 2244 echo -n "Launching Postgres service" 2245 2246 cat - >> "$TMPDIR/postgresql.conf" <<EOF 2247 unix_socket_directories='${TMPDIR}/sockets' 2248 fsync=off 2249 max_wal_senders=0 2250 synchronous_commit=off 2251 wal_level=minimal 2252 listen_addresses='' 2253 EOF 2254 2255 grep -v host \ 2256 < "$TMPDIR/pg_hba.conf" \ 2257 > "$TMPDIR/pg_hba.conf.new" 2258 mv "$TMPDIR/pg_hba.conf.new" "$TMPDIR/pg_hba.conf" 2259 "${POSTGRES_PATH}/pg_ctl" \ 2260 -D "$TMPDIR" \ 2261 -l "${MY_TMP_DIR}/postgres.log" \ 2262 start \ 2263 > "${MY_TMP_DIR}/postgres-start.log" \ 2264 2> "${MY_TMP_DIR}/postgres-start.err" 2265 echo " DONE" 2266 PGHOST="$TMPDIR/sockets" 2267 export PGHOST 2268 } 2269 2270 2271 # *************** Main logic starts here ************** 2272 2273 # ####### Setup globals ###### 2274 # Postgres database to use (must match configuration file) 2275 export DB="auditor-basedb" 2276 2277 # test required commands exist 2278 echo "Testing for jq" 2279 jq -h > /dev/null || exit_skip "jq required" 2280 echo "Testing for taler-merchant-config" 2281 taler-merchant-config -h > /dev/null || exit_skip "taler-merchant-config required" 2282 echo "Testing for taler-merchant-httpd" 2283 taler-merchant-httpd -h > /dev/null || exit_skip "taler-merchant-httpd required" 2284 echo "Testing for faketime" 2285 faketime -h > /dev/null || exit_skip "faketime required" 2286 # NOTE: really check for all three libeufin commands? 2287 echo "Testing for libeufin" 2288 libeufin-bank --help >/dev/null 2> /dev/null </dev/null || exit_skip "libeufin required" 2289 echo "Testing for taler-wallet-cli" 2290 taler-wallet-cli -h >/dev/null </dev/null 2>/dev/null || exit_skip "taler-wallet-cli required" 2291 2292 2293 echo -n "Testing for Postgres" 2294 2295 MY_TMP_DIR=$(mktemp -d /tmp/taler-auditor-basedbXXXXXX) 2296 echo "Using $MY_TMP_DIR for logging and temporary data" 2297 2298 # If run as root, simply use the running postgres instance. 2299 # Otherwise create a temporary storage space for postgres. 2300 [ $(id -u) == 0 ] || perform_initdb 2301 2302 MYDIR="${MY_TMP_DIR}/basedb" 2303 mkdir -p "${MYDIR}" 2304 2305 if [ -z ${REUSE_BASEDB_DIR+x} ] 2306 then 2307 echo "Generating fresh database at $MYDIR" 2308 2309 if faketime -f '-1 d' ./generate-auditor-basedb.sh -d "$MYDIR/$DB" 2310 then 2311 echo -n "Reset 'auditor-basedb' database at ${PGHOST:-} ..." 2312 dropdb --if-exists "auditor-basedb" > /dev/null 2> /dev/null || true 2313 createdb "auditor-basedb" || exit_skip "Could not create database '$BASEDB' at ${PGHOST:-}" 2314 echo " DONE" 2315 else 2316 echo "Generation failed" 2317 exit 1 2318 fi 2319 echo "To reuse this database in the future, use:" 2320 echo "export REUSE_BASEDB_DIR=$MY_TMP_DIR" 2321 else 2322 echo "Reusing existing database from ${REUSE_BASEDB_DIR}" 2323 cp -r "${REUSE_BASEDB_DIR}/basedb"/* "${MYDIR}/" 2324 fi 2325 2326 check_with_database "$MYDIR/$DB" 2327 if [ "$fail" != "0" ] 2328 then 2329 exit "$fail" 2330 fi 2331 2332 if [ -z "${REUSE_BASEDB_DIR+x}" ] 2333 then 2334 echo "Run 'export REUSE_BASEDB_DIR=${MY_TMP_DIR}' to re-run tests against the same database" 2335 fi 2336 2337 exit 0