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