exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

test-auditor.sh (78828B)


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