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