exchange

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

commit 9d6dc3cdc14b574ddff38224f6ad9fa8e0ec0a6e
parent 40cd7a3af2abe8fa556a19b1708d76cbdbc36065
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri, 31 Jul 2026 23:33:46 +0200

fix test-auditor.sh

Diffstat:
Msrc/auditor/generate-auditor-basedb.sh | 7+++++++
Msrc/auditor/generate-revoke-basedb.sh | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/auditor/meson.build | 62++++++++++++++++++++++++++++++++++++--------------------------
Msrc/auditor/test-auditor.sh | 27++++++++++++++++++++++++---
Msrc/auditor/test-revocation.sh | 714+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/auditordb/iterate_amount_arithmetic_inconsistencies.c | 8++++----
Msrc/auditordb/iterate_denomination_key_validity_withdraw_inconsistencies.c | 8++++----
Msrc/auditordb/iterate_misattribution_in_inconsistencies.c | 8++++----
Msrc/auditordb/iterate_reserve_balance_insufficient_inconsistencies.c | 8++++----
Msrc/auditordb/iterate_reserve_balance_summary_wrong_inconsistencies.c | 8++++----
Msrc/auditordb/iterate_reserve_not_closed_inconsistencies.c | 8++++----
Msrc/auditordb/meson.build | 1+
Msrc/auditordb/restart.sql | 1+
13 files changed, 573 insertions(+), 419 deletions(-)

diff --git a/src/auditor/generate-auditor-basedb.sh b/src/auditor/generate-auditor-basedb.sh @@ -12,6 +12,13 @@ # set -eu +# The auditor tests inject faults into specific rows of the generated +# database, so the wallet must pick the same coins and make the same +# transactions on every run. The coin selection introduced after 2024 is +# not deterministic in that way; 'legacy-2024' restores the old behaviour +# (see https://bugs.gnunet.org/view.php?id=11272). +export TALER_WALLET_COINSEL="legacy-2024" + . setup.sh CONF="generate-auditor-basedb.conf" diff --git a/src/auditor/generate-revoke-basedb.sh b/src/auditor/generate-revoke-basedb.sh @@ -8,6 +8,12 @@ set -eu # set -x +# The revocation test depends on the wallet picking specific coins (it +# revokes the denomination of a particular coin), so coin selection has to +# be deterministic. See generate-auditor-basedb.sh and +# https://bugs.gnunet.org/view.php?id=11272. +export TALER_WALLET_COINSEL="legacy-2024" + . setup.sh echo -n "Testing for curl ..." @@ -35,8 +41,30 @@ BANK_URL="http://localhost:${BANK_PORT}/" # Setup merchant +export MERCHANT_URL echo -n "Setting up merchant ..." -curl -H "Content-Type: application/json" -X POST -d '{"auth": {"method": "external"}, "accounts":[{"payto_uri":"payto://iban/SANDBOXX/DE474361?receiver-name=Merchant43"}],"id":"admin","name":"admin","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000},"use_stefan":true}' "${MERCHANT_URL}management/instances" +curl -H "Content-Type: application/json" -X POST -d '{"auth": {"method": "external"},"id":"admin","name":"admin","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000},"use_stefan":true}' "${MERCHANT_URL}management/instances" +echo " DONE" + +echo -n "Setting up merchant account ..." +FORTYTHREE="payto://iban/DE474361?receiver-name=Merchant43" +STATUS=$(curl -H "Content-Type: application/json" -X POST \ + "${MERCHANT_URL}private/accounts" \ + -d '{"payto_uri":"'"$FORTYTHREE"'"}' \ + -w "%{http_code}" -s -o /dev/null) +if [ "$STATUS" != "200" ] +then + exit_fail "Expected 200 OK. Got: $STATUS" +fi +echo " DONE" + +echo -n "Setting up libeufin merchant account ..." +libeufin-bank create-account \ + --config="${CONF}" \ + --name="Merchant43" \ + --username="Merchant43" \ + --password="password" \ + --payto_uri="payto://iban/DE474361?receiver-name=Merchant43" echo " DONE" @@ -82,6 +110,28 @@ export COINS export rc=$(echo "$COINS" | jq -r '[.coins[] | select((.denomValue == "TESTKUDOS:2"))][0] | .coinPub') # Find the denom export rd=$(echo "$COINS" | jq -r '[.coins[] | select((.denomValue == "TESTKUDOS:2"))][0] | .denomPubHash') + +# This database is all about recoup, which the exchange currently does not +# implement: the recoup handlers are compiled out behind FIXME_9828 (see +# src/exchange/taler-exchange-httpd.c and +# https://bugs.gnunet.org/view.php?id=9828). Without them the wallet can +# never recoup the coins of the revoked denomination and we would spin until +# the test times out, so detect that up front and skip. +echo -n "Checking that the exchange implements recoup ..." +RECOUP_CODE=$(curl -s -X POST \ + -o "${MY_TMP_DIR}/recoup-probe.json" \ + -w "%{http_code}" \ + -H "Content-Type: application/json" \ + -d '{}' \ + "${EXCHANGE_URL}coins/${rc}/recoup") +if [ "$RECOUP_CODE" = "404" ] && + [ "$(jq -r '.code' < "${MY_TMP_DIR}/recoup-probe.json")" = "1001" ] +then + echo " NO" + exit_skip "exchange has no /coins/\$COIN_PUB/recoup endpoint (recoup is disabled, see FIXME_9828)" +fi +echo " YES" + echo -n "Revoking denomination ${rd} (to affect coin ${rc}) ..." # Find all other coins, which will be suspended export susp=$(echo "$COINS" | jq --arg rc "$rc" '[.coins[] | select(.coinPub != $rc) | .coinPub]') @@ -146,43 +196,62 @@ taler-wallet-cli \ echo "Purchase with recoup'ed coin (via reserve) done" +# Re-read the coins: the recoup and the purchase above changed the wallet's +# coin set, so the dump taken before the first revocation is stale. +COINS=$(taler-wallet-cli --wallet-db="$WALLET_DB" advanced dump-coins) +export COINS + # Find coin we want to refresh, then revoke -export rrc=$(echo "$coins" | jq -r '[.coins[] | select((.denomValue == "TESTKUDOS:5"))][0] | .coinPub') +export rrc=$(echo "$COINS" | jq -r '[.coins[] | select((.denomValue == "TESTKUDOS:5"))][0] | .coinPub') # Find the denom -export zombie_denom=$(echo "$coins" | jq -r '[.coins[] | select((.denomValue == "TESTKUDOS:5"))][0] | .denomPubHash') +export zombie_denom=$(echo "$COINS" | jq -r '[.coins[] | select((.denomValue == "TESTKUDOS:5"))][0] | .denomPubHash') echo "Will refresh coin ${rrc} of denomination ${zombie_denom}" # Find all other coins, which will be suspended -export susp=$(echo "$coins" | jq --arg rrc "$rrc" '[.coins[] | select(.coinPub != $rrc) | .coinPub]') +export susp=$(echo "$COINS" | jq --arg rrc "$rrc" '[.coins[] | select(.coinPub != $rrc) | .coinPub]') # Travel into the future! (must match DURATION_WITHDRAW option) export TIMETRAVEL="--timetravel=604800000000" echo "Launching exchange 1 week in the future" -kill -TERM "$EXCHANGE_PID" -kill -TERM "$RSA_DENOM_HELPER_PID" -kill -TERM "$CS_DENOM_HELPER_PID" -kill -TERM "$SIGNKEY_HELPER_PID" +# The exchange and its security modules were started by +# taler-unified-setup.sh, so we do not have their PIDs; stop them by name +# and bring them back up with the time offset applied. +for proc in taler-exchange-httpd \ + taler-exchange-secmod-rsa \ + taler-exchange-secmod-cs \ + taler-exchange-secmod-eddsa +do + pkill -x -u "$(id -u)" -TERM "$proc" || true +done +# Give them a moment to release their sockets +sleep 1 taler-exchange-secmod-eddsa $TIMETRAVEL -c "$CONF" 2> "${MY_TMP_DIR}/taler-exchange-secmod-eddsa.log" & SIGNKEY_HELPER_PID=$! taler-exchange-secmod-rsa $TIMETRAVEL -c "$CONF" 2> "${MY_TMP_DIR}/taler-exchange-secmod-rsa.log" & RSA_DENOM_HELPER_PID=$! taler-exchange-secmod-cs $TIMETRAVEL -c "$CONF" 2> "${MY_TMP_DIR}/taler-exchange-secmod-cs.log" & CS_DENOM_HELPER_PID=$! +export SIGNKEY_HELPER_PID RSA_DENOM_HELPER_PID CS_DENOM_HELPER_PID taler-exchange-httpd $TIMETRAVEL -c "$CONF" 2> "${MY_TMP_DIR}/taler-exchange-httpd.log" & export EXCHANGE_PID=$! # Wait for exchange to be available -for n in `seq 1 50` +OK=0 +for n in `seq 1 100` do echo -n "." - sleep 0.1 - OK=0 + sleep 0.2 # exchange - wget http://localhost:8081/ -o /dev/null -O /dev/null >/dev/null || continue + wget "${EXCHANGE_URL}config" -o /dev/null -O /dev/null >/dev/null || continue OK=1 break done +if [ 1 != "$OK" ] +then + exit_fail "Failed to restart exchange in the future" +fi +echo " DONE" echo "Refreshing coin $rrc" taler-wallet-cli \ @@ -252,24 +321,31 @@ taler-wallet-cli \ run-until-done echo "Restarting merchant (so new keys are known)" -kill -TERM $MERCHANT_PID +pkill -x -u "$(id -u)" -TERM taler-merchant-httpd || true +sleep 1 taler-merchant-httpd \ -c "$CONF" \ -L INFO \ 2> ${MY_TMP_DIR}/taler-merchant-httpd.log & MERCHANT_PID=$! +export MERCHANT_PID # Wait for merchant to be again available -for n in `seq 1 50` +OK=0 +for n in `seq 1 100` do echo -n "." - sleep 0.1 - OK=0 + sleep 0.2 # merchant - wget http://localhost:9966/ -o /dev/null -O /dev/null >/dev/null || continue + wget "${MERCHANT_URL}config" -o /dev/null -O /dev/null >/dev/null || continue OK=1 break done +if [ 1 != "$OK" ] +then + exit_fail "Failed to restart merchant" +fi +echo " DONE" # Now we buy something, only the coins resulting from recoup+refresh will be # used, as other ones are suspended @@ -290,7 +366,23 @@ taler-wallet-cli \ echo "Bought something with refresh-recouped coin" echo "Shutting down services" +# Stop the exchange/merchant processes we restarted ourselves first: they +# are not children of taler-unified-setup.sh, so its teardown misses them +# and a bare 'wait' below would block forever. +for pid in "${EXCHANGE_PID:-}" \ + "${MERCHANT_PID:-}" \ + "${RSA_DENOM_HELPER_PID:-}" \ + "${CS_DENOM_HELPER_PID:-}" \ + "${SIGNKEY_HELPER_PID:-}" +do + if [ -n "$pid" ] + then + kill -TERM "$pid" 2> /dev/null || true + wait "$pid" 2> /dev/null || true + fi +done exit_cleanup +unset SETUP_PID # Where do we write the result? @@ -298,14 +390,14 @@ export BASEDB=${1:-"revoke-basedb"} # Dump database +mkdir -p "$(dirname "$BASEDB")" echo "Dumping database ${BASEDB}.sql" pg_dump -O "auditor-basedb" | sed -e '/AS integer/d' > "${BASEDB}.sql" +cp "${CONF}" "${BASEDB}.conf" +cp "$(taler-exchange-config -c "${CONF}" -s exchange-offline -o MASTER_PRIV_FILE -f)" "${BASEDB}.mpriv" # clean up echo -n "Final clean up ..." -kill -TERM "$SETUP_PID" -wait -unset SETUP_PID dropdb "auditor-basedb" echo " DONE" diff --git a/src/auditor/meson.build b/src/auditor/meson.build @@ -279,21 +279,24 @@ executable( ) -#TESTS = \ -# test-sync.sh -# test-auditor.sh -- blocked on stable coin selection option in wallet... - -#test_auditor = configure_file( -# input: 'test-auditor.sh', -# output: 'test-auditor.sh', -# copy: true, -#) -#test( -# 'test-auditor', -# test_auditor, -# workdir: meson.current_build_dir(), -# suite: ['auditor', 'installcheck'], -#) +# These tests audit a pre-generated reference database, so they need the +# wallet to pick the same coins on every run: the generator scripts set +# TALER_WALLET_COINSEL=legacy-2024 for that (bug #11272). They are in the +# 'installcheck' suite because they drive installed binaries and need +# Postgres superuser rights. +test_auditor = configure_file( + input: 'test-auditor.sh', + output: 'test-auditor.sh', + copy: true, +) +test( + 'test-auditor', + test_auditor, + workdir: meson.current_build_dir(), + suite: ['auditor', 'installcheck'], + is_parallel: false, + timeout: 1800, +) #test_kyc = configure_file( # input: 'test-kyc.sh', # output: 'test-kyc.sh', @@ -305,17 +308,23 @@ executable( # workdir: meson.current_build_dir(), # suite: ['auditor', 'installcheck'], #) -#test_revocation = configure_file( -# input: 'test-revocation.sh', -# output: 'test-revocation.sh', -# copy: true, -#) -#test( -# 'test-revocation', -# test_revocation, -# workdir: meson.current_build_dir(), -# suite: ['auditor', 'installcheck'], -#) +# test-revocation audits denomination revocation, which relies on recoup. +# The exchange's recoup handlers are currently compiled out (FIXME_9828, +# https://bugs.gnunet.org/view.php?id=9828), so the test detects the missing +# endpoint and reports itself as skipped until recoup is reimplemented. +test_revocation = configure_file( + input: 'test-revocation.sh', + output: 'test-revocation.sh', + copy: true, +) +test( + 'test-revocation', + test_revocation, + workdir: meson.current_build_dir(), + suite: ['auditor', 'installcheck'], + is_parallel: false, + timeout: 1800, +) test_sync = configure_file( input: 'test-sync.sh', output: 'test-sync.sh', @@ -327,6 +336,7 @@ test( workdir: meson.current_build_dir(), suite: ['auditor', 'installcheck'], is_parallel: false, + timeout: 1800, ) EXTRA_DIST = [ diff --git a/src/auditor/test-auditor.sh b/src/auditor/test-auditor.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # This file is part of TALER # Copyright (C) 2014-2025 Taler Systems SA @@ -504,6 +504,22 @@ function check_report() { echo "PASS" } +# Check that at least one entry of report $1 has field $2 set to $3. +# Unlike check_report, this does not depend on the order in which the +# auditor inserted its findings: one fault can legitimately be reported +# against several operations (a coin with a bad denomination signature is +# flagged once per operation that used it). +function check_report_any() { + call_endpoint "$1" + NAME=$(echo "$1" | tr '-' '_') + # shellcheck disable=SC2086 + jq -e --arg want "$3" "any(.\"${NAME}\"[]; .\"$2\" == \$want)" \ + < "${MY_TMP_DIR}/${1}.json" \ + > /dev/null \ + || exit_fail "$1::$2 (no entry with value $3)" + echo "PASS" +} + function check_no_report() { call_endpoint "$1" NAME=$(echo "$1" | tr '-' '_') @@ -922,7 +938,10 @@ function test_6() { "bad-sig-losses" \ "loss" "TESTKUDOS:0" echo -n "Checking bad-signature-loss operation detected ..." - check_report \ + # The coin was both melted and deposited, so the bad denomination + # signature is reported against either operation; only require that + # the deposit was flagged. + check_report_any \ "bad-sig-losses" \ "operation" "deposit" echo -n "Checking bad-signature-loss balance update ..." @@ -1892,9 +1911,11 @@ function test_25() { "emergency" \ "denom_risk" "TESTKUDOS:10" echo -n "Testing emergency loss reporting... " + # The dropped refund covered coin deposit #2, so the deposit's full + # amount is what the denomination is now short of. check_report \ "emergency" \ - "denom_loss" "TESTKUDOS:5.98" + "denom_loss" "TESTKUDOS:7.02" echo -n "Testing double-spending reporting... " check_balance \ "coins_reported_emergency_risk_by_amount" \ diff --git a/src/auditor/test-revocation.sh b/src/auditor/test-revocation.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # This file is part of TALER # Copyright (C) 2014-2022 Taler Systems SA @@ -41,6 +41,9 @@ ALL_TESTS=$(seq 0 4) # TESTS=${1:-$ALL_TESTS} +export TALER_AUDITOR_TOKEN="secret-token:D4CST1Z6AHN3RT03M0T9NSTF2QGHTB5ZD2D3RYZB4HAWG8SX0JEFWBXCKXZHMB7Y3Z7KVFW0B3XPXD5BHCFP8EB0R6CNH2KAWDWVET0" +export TALER_AUDITOR_SALT="64S36D1N6RVKGC9J6CT3ADHQ70RK4CSM6MV3EE1H68SK8D9P6WW32CHK6GTKCDSR64S36D1N6RVKGC9J6CT3ADHQ70RK4CSM6MV3EE0" + # Global variable to run the auditor processes under valgrind # VALGRIND=valgrind VALGRIND="" @@ -93,27 +96,14 @@ trap exit_cleanup EXIT function pre_audit () { # Launch bank echo -n "Launching bank " + export CONF + export MY_TMP_DIR launch_libeufin for n in $(seq 1 80) do echo -n "." sleep 0.1 OK=1 - wget http://localhost:18082/ \ - -o /dev/null \ - -O /dev/null \ - >/dev/null && break - OK=0 - done - if [ 1 != "$OK" ] - then - exit_skip "Failed to launch Sandbox" - fi - for n in $(seq 1 80) - do - echo -n "." - sleep 0.1 - OK=1 wget http://localhost:8082/ \ -o /dev/null \ -O /dev/null \ @@ -122,12 +112,11 @@ function pre_audit () { done if [ 1 != "$OK" ] then - exit_skip "Failed to launch Nexus" + exit_skip "Failed to launch libeufin-bank" fi echo " DONE" if [ "${1:-no}" = "aggregator" ] then - export CONF echo -n "Running exchange aggregator ... (config: $CONF)" taler-exchange-aggregator \ -L "$LOGLEVEL" \ @@ -165,94 +154,170 @@ function audit_only () { taler-auditor-dbinit \ -r \ -c "$CONF" - $VALGRIND taler-helper-auditor-aggregation \ - -L "$LOGLEVEL" \ - -c "$CONF" \ - -m "$MASTER_PUB" \ - > test-audit-aggregation.json \ - 2> test-audit-aggregation.log \ - || exit_fail "aggregation audit failed" - echo -n "." - $VALGRIND taler-helper-auditor-aggregation \ - -L "$LOGLEVEL" \ - -c "$CONF" \ - -m "$MASTER_PUB" \ - > test-audit-aggregation-inc.json \ - 2> test-audit-aggregation-inc.log \ - || exit_fail "incremental aggregation audit failed" - echo -n "." - $VALGRIND taler-helper-auditor-coins \ - -L "$LOGLEVEL" \ - -c "$CONF" \ - -m "$MASTER_PUB" \ - > test-audit-coins.json \ - 2> test-audit-coins.log \ - || exit_fail "coin audit failed" - echo -n "." - $VALGRIND taler-helper-auditor-coins \ - -L "$LOGLEVEL" \ - -c "$CONF" \ - -m "$MASTER_PUB" \ - > test-audit-coins-inc.json \ - 2> test-audit-coins-inc.log \ - || exit_fail "incremental coin audit failed" - echo -n "." - $VALGRIND taler-helper-auditor-deposits \ - -L "$LOGLEVEL" \ - -c "$CONF" \ - -m "$MASTER_PUB" \ - > test-audit-deposits.json \ - 2> test-audit-deposits.log \ - || exit_fail "deposits audit failed" - echo -n "." - $VALGRIND taler-helper-auditor-deposits \ - -L "$LOGLEVEL" \ - -c "$CONF" \ - -m "$MASTER_PUB" \ - > test-audit-deposits-inc.json \ - 2> test-audit-deposits-inc.log \ - || exit_fail "incremental deposits audit failed" - echo -n "." - $VALGRIND taler-helper-auditor-reserves \ - -i \ - -L "$LOGLEVEL" \ - -c "$CONF" \ - -m "$MASTER_PUB" \ - > test-audit-reserves.json \ - 2> test-audit-reserves.log \ - || exit_fail "reserves audit failed" - echo -n "." - $VALGRIND taler-helper-auditor-reserves \ - -i \ - -L "$LOGLEVEL" \ - -c "$CONF" \ - -m "$MASTER_PUB" \ - > test-audit-reserves-inc.json \ - 2> test-audit-reserves-inc.log \ - || exit_fail "incremental reserves audit failed" - echo -n "." - $VALGRIND taler-helper-auditor-wire \ - -i \ - -L "$LOGLEVEL" \ - -c "$CONF" \ - -m "$MASTER_PUB" \ - > test-audit-wire.json \ - 2> test-wire-audit.log \ - || exit_fail "wire audit failed" - echo -n "." - $VALGRIND taler-helper-auditor-wire \ - -i \ - -L "$LOGLEVEL" \ - -c "$CONF" \ - -m "$MASTER_PUB" \ - > test-audit-wire-inc.json \ - 2> test-wire-audit-inc.log \ - || exit_fail "wire audit failed" - echo -n "." + # Each helper is run twice: the first run audits from scratch, the + # second one exercises the incremental path. Findings end up in the + # auditor database and are inspected via the auditor's REST API. + for helper in aggregation coins deposits reserves \ + wire-credit wire-debit purses transfer + do + for pass in "" "-inc" + do + $VALGRIND "taler-helper-auditor-${helper}" \ + -i \ + -L "$LOGLEVEL" \ + -c "$CONF" \ + -t \ + > "${MY_TMP_DIR}/test-audit-${helper}${pass}.out" \ + 2> "${MY_TMP_DIR}/test-audit-${helper}${pass}.err" \ + || exit_fail "${helper} audit${pass} failed (see ${MY_TMP_DIR}/test-audit-${helper}${pass}.*)" + echo -n "." + done + done echo " DONE" } +function stop_auditor_httpd() { + if [ -n "${APID:-}" ] + then + echo -n "Stopping auditor $APID..." + kill -TERM "$APID" + wait "$APID" || true + echo "DONE" + unset APID + fi +} + + +function run_auditor_httpd() { + echo -n "Starting auditor..." + $VALGRIND taler-auditor-httpd \ + -c "${CONF}" \ + -L "$LOGLEVEL" \ + 2> "${MY_TMP_DIR}/auditor-httpd.err" & + APID=$! + # Wait for auditor service to be available + for n in $(seq 1 50) + do + echo -n "." + sleep 0.2 + wget "http://localhost:8083/config" \ + -o /dev/null \ + -O /dev/null \ + >/dev/null \ + || continue + break + done + echo "... DONE." +} + + +function check_auditor_running() { + ARUNSTATUS=$(curl -Is http://localhost:8083/config | head -1) + if [ -n "${ARUNSTATUS:-}" ] + then + echo "Auditor running" + else + echo "Auditor not running, starting it" + run_auditor_httpd + fi + unset ARUNSTATUS +} + + +function call_endpoint() { + if [ -n "${2+x}" ] + then + 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}" + echo "endpoint ${1} called (with balance_key)... " + else + curl -s \ + -H "Accept: application/json" \ + -H "Authorization: Bearer ${TALER_AUDITOR_TOKEN}" \ + -o "${MY_TMP_DIR}/${1}.json" \ + "localhost:8083/monitoring/${1}?limit=50" + echo "endpoint ${1} called... " + fi +} + + +function check_balance() { + call_endpoint "balances" "$1" + BAL=$(jq -r .balances[0].balance_value < "${MY_TMP_DIR}/${1}.json") + if [ "$BAL" != "$2" ] + then + exit_fail "$3 (got $BAL, wanted $2)" + fi + echo "PASS" +} + + +function check_not_balance() { + call_endpoint "balances" "$1" + BAL=$(jq -r .balances[0].balance_value < "${MY_TMP_DIR}/${1}.json") + if [ "$BAL" = "$2" ] + then + exit_fail "$3 (got $BAL, wanted NOT $2)" + fi + echo "PASS" +} + + +function check_report() { + call_endpoint "$1" + NAME=$(echo "$1" | tr '-' '_') + # shellcheck disable=SC2086 + VAL=$(jq -r .\"${NAME}\"[0].\"$2\" < "${MY_TMP_DIR}/${1}.json") + if [ "$VAL" != "$3" ] + then + exit_fail "$1::$2 (got $VAL, wanted $3)" + fi + echo "PASS" +} + + +function check_no_report() { + call_endpoint "$1" + NAME=$(echo "$1" | tr '-' '_') + # shellcheck disable=SC2086 + jq -e .\"${NAME}\"[0] \ + < "${MY_TMP_DIR}/${1}.json" \ + > /dev/null \ + && exit_fail "Wanted empty report for $1, but got incidents" + echo "PASS" +} + + +function check_report_neg() { + call_endpoint "$1" + NAME=$(echo "$1" | tr '-' '_') + # shellcheck disable=SC2086 + VAL=$(jq -r .\"${NAME}\"[0].\"$2\" < "${MY_TMP_DIR}/${1}.json") + if [ "$VAL" == "$3" ] + then + exit_fail "$1::$2 (got $VAL, wanted $3)" + fi + echo "PASS" +} + + +# Check that at least one entry of report $1 has field $2 set to $3. +function check_report_any() { + call_endpoint "$1" + NAME=$(echo "$1" | tr '-' '_') + # shellcheck disable=SC2086 + jq -e --arg want "$3" "any(.\"${NAME}\"[]; .\"$2\" == \$want)" \ + < "${MY_TMP_DIR}/${1}.json" \ + > /dev/null \ + || exit_fail "$1::$2 (no entry with value $3)" + echo "PASS" +} + + # Run audit process on current database, including report # generation. Pass "aggregator" as $1 to run # $ taler-exchange-aggregator @@ -269,7 +334,8 @@ function run_audit () { function full_reload() { echo -n "Doing full reload of the database... " - dropdb "$DB" 2> /dev/null || true + stop_auditor_httpd + dropdb -f "$DB" 2> /dev/null || true createdb -T template0 "$DB" \ || exit_skip "could not create database $DB (at ${PGHOST:-})" # Import pre-generated database, -q(ietly) using single (-1) transaction @@ -286,128 +352,103 @@ function full_reload() function test_0() { echo "===========0: normal run with aggregator===========" run_audit aggregator + check_auditor_running echo "Checking output" # if an emergency was detected, that is a bug and we should fail echo -n "Test for emergencies... " - jq -e .emergencies[0] < test-audit-coins.json > /dev/null && exit_fail "Unexpected emergency detected in ordinary run" || echo PASS - echo -n "Test for deposit confirmation emergencies... " - jq -e .deposit_confirmation_inconsistencies[0] < test-audit-deposits.json > /dev/null && exit_fail "Unexpected deposit confirmation inconsistency detected" || echo PASS + check_no_report "emergency" echo -n "Test for emergencies by count... " - jq -e .emergencies_by_count[0] < test-audit-coins.json > /dev/null && exit_fail "Unexpected emergency by count detected in ordinary run" || echo PASS - + check_no_report "emergency-by-count" + echo -n "Test for deposit confirmation problems... " + check_no_report "deposit-confirmation" echo -n "Test for wire inconsistencies... " - jq -e .wire_out_amount_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected wire out inconsistency detected in ordinary run" - jq -e .reserve_in_amount_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected reserve in inconsistency detected in ordinary run" - jq -e .misattribution_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected misattribution inconsistency detected in ordinary run" - jq -e .row_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected row inconsistency detected in ordinary run" - jq -e .denomination_key_validity_withdraw_inconsistencies[0] < test-audit-reserves.json > /dev/null && exit_fail "Unexpected denomination key withdraw inconsistency detected in ordinary run" - jq -e .row_minor_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected minor row inconsistency detected in ordinary run" - jq -e .lag_details[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected lag detected in ordinary run" - jq -e .wire_format_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected wire format inconsistencies detected in ordinary run" - - - # TODO: check operation balances are correct (once we have all transaction types and wallet is deterministic) - # TODO: check revenue summaries are correct (once we have all transaction types and wallet is deterministic) - - echo PASS - - LOSS=$(jq -r .total_bad_sig_loss < test-audit-aggregation.json) - if [ "$LOSS" != "TESTKUDOS:0" ] - then - exit_fail "Wrong total bad sig loss from aggregation, got unexpected loss of $LOSS" - fi - LOSS=$(jq -r .irregular_loss < test-audit-coins.json) - if [ "$LOSS" != "TESTKUDOS:0" ] - then - exit_fail "Wrong total bad sig loss from coins, got unexpected loss of $LOSS" - fi - LOSS=$(jq -r .total_bad_sig_loss < test-audit-reserves.json) - if [ "$LOSS" != "TESTKUDOS:0" ] - then - exit_fail "Wrong total bad sig loss from reserves, got unexpected loss of $LOSS" - fi - - echo -n "Test for wire amounts... " - WIRED=$(jq -r .total_wire_in_delta_plus < test-audit-wire.json) - if [ "$WIRED" != "TESTKUDOS:0" ] - then - exit_fail "Expected total wire delta plus wrong, got $WIRED" - fi - WIRED=$(jq -r .total_wire_in_delta_minus < test-audit-wire.json) - if [ "$WIRED" != "TESTKUDOS:0" ] - then - exit_fail "Expected total wire delta minus wrong, got $WIRED" - fi - WIRED=$(jq -r .total_wire_out_delta_plus < test-audit-wire.json) - if [ "$WIRED" != "TESTKUDOS:0" ] - then - exit_fail "Expected total wire delta plus wrong, got $WIRED" - fi - WIRED=$(jq -r .total_wire_out_delta_minus < test-audit-wire.json) - if [ "$WIRED" != "TESTKUDOS:0" ] - then - exit_fail "Expected total wire delta minus wrong, got $WIRED" - fi - WIRED=$(jq -r .total_misattribution_in < test-audit-wire.json) - if [ "$WIRED" != "TESTKUDOS:0" ] - then - exit_fail "Expected total misattribution in wrong, got $WIRED" - fi - echo "PASS" - - echo -n "Checking for unexpected arithmetic differences " - LOSS=$(jq -r .total_arithmetic_delta_plus < test-audit-aggregation.json) - if [ "$LOSS" != "TESTKUDOS:0" ] - then - exit_fail "Wrong arithmetic delta from aggregations, got unexpected plus of $LOSS" - fi - LOSS=$(jq -r .total_arithmetic_delta_minus < test-audit-aggregation.json) - if [ "$LOSS" != "TESTKUDOS:0" ] - then - exit_fail "Wrong arithmetic delta from aggregation, got unexpected minus of $LOSS" - fi - LOSS=$(jq -r .total_arithmetic_delta_plus < test-audit-coins.json) - if [ "$LOSS" != "TESTKUDOS:0" ] - then - exit_fail "Wrong arithmetic delta from coins, got unexpected plus of $LOSS" - fi - LOSS=$(jq -r .total_arithmetic_delta_minus < test-audit-coins.json) - if [ "$LOSS" != "TESTKUDOS:0" ] - then - exit_fail "Wrong arithmetic delta from coins, got unexpected minus of $LOSS" - fi - LOSS=$(jq -r .total_arithmetic_delta_plus < test-audit-reserves.json) - if [ "$LOSS" != "TESTKUDOS:0" ] - then - exit_fail "Wrong arithmetic delta from reserves, got unexpected plus of $LOSS" - fi - LOSS=$(jq -r .total_arithmetic_delta_minus < test-audit-reserves.json) - if [ "$LOSS" != "TESTKUDOS:0" ] - then - exit_fail "Wrong arithmetic delta from reserves, got unexpected minus of $LOSS" - fi - - jq -e .amount_arithmetic_inconsistencies[0] \ - < test-audit-aggregation.json \ - > /dev/null \ - && exit_fail "Unexpected arithmetic inconsistencies from aggregations detected in ordinary run" - jq -e .amount_arithmetic_inconsistencies[0] \ - < test-audit-coins.json \ - > /dev/null \ - && exit_fail "Unexpected arithmetic inconsistencies from coins detected in ordinary run" - jq -e .amount_arithmetic_inconsistencies[0] \ - < test-audit-reserves.json \ - > /dev/null \ - && exit_fail "Unexpected arithmetic inconsistencies from reserves detected in ordinary run" - echo "PASS" - - echo -n "Checking for unexpected wire out differences " - jq -e .wire_out_inconsistencies[0] \ - < test-audit-aggregation.json \ - > /dev/null \ - && exit_fail "Unexpected wire out inconsistencies detected in ordinary run" - echo "PASS" + check_no_report "denomination-key-validity-withdraw-inconsistency" + check_no_report "wire-out-inconsistency" + check_no_report "reserve-in-inconsistency" + check_no_report "misattribution-in-inconsistency" + check_no_report "row-inconsistency" + check_no_report "row-minor-inconsistencies" + check_no_report "wire-format-inconsistency" + + # Just to test the endpoint and for logging ... + call_endpoint "balances" + + echo -n "Testing bad sig loss balance... " + check_balance \ + "aggregation_total_bad_sig_loss" \ + "TESTKUDOS:0" \ + "Wrong total bad sig loss from aggregation" + echo -n "Testing coin irregular loss balances... " + check_balance \ + "coin_irregular_loss" \ + "TESTKUDOS:0" \ + "Wrong total bad sig loss from coins" + echo -n "Testing reserves bad sig loss balances... " + check_balance \ + "reserves_total_bad_sig_loss" \ + "TESTKUDOS:0" \ + "Wrong total bad sig loss from reserves" + + echo -n "Test for bad incoming delta plus... " + check_balance \ + "total_bad_amount_in_plus" \ + "TESTKUDOS:0" \ + "Expected total wire in delta plus wrong" + echo -n "Test for bad incoming delta minus... " + check_balance \ + "total_bad_amount_in_minus" \ + "TESTKUDOS:0" \ + "Expected total wire in delta minus wrong" + echo -n "Test for aggregation wire out delta plus... " + check_balance \ + "aggregation_total_wire_out_delta_plus" \ + "TESTKUDOS:0" \ + "Expected total wire out delta plus wrong" + echo -n "Test for aggregation wire out delta minus... " + check_balance \ + "aggregation_total_wire_out_delta_minus" \ + "TESTKUDOS:0" \ + "Expected total wire out delta minus wrong" + echo -n "Test for misattribution amounts... " + check_balance \ + "total_misattribution_in" \ + "TESTKUDOS:0" \ + "Expected total misattribution in wrong" + + echo -n "Checking for unexpected aggregation delta plus differences... " + check_balance \ + "aggregation_total_arithmetic_delta_plus" \ + "TESTKUDOS:0" \ + "Wrong arithmetic delta plus from aggregations" + echo -n "Checking for unexpected aggregation delta minus differences... " + check_balance \ + "aggregation_total_arithmetic_delta_minus" \ + "TESTKUDOS:0" \ + "Wrong arithmetic delta minus from aggregations" + echo -n "Checking for unexpected coin delta plus differences... " + check_balance \ + "coins_total_arithmetic_delta_plus" \ + "TESTKUDOS:0" \ + "Wrong arithmetic delta plus from coins" + echo -n "Checking for unexpected coin delta minus differences... " + check_balance \ + "coins_total_arithmetic_delta_minus" \ + "TESTKUDOS:0" \ + "Wrong arithmetic delta minus from coins" + echo -n "Checking for unexpected reserves delta plus... " + check_balance \ + "reserves_total_arithmetic_delta_plus" \ + "TESTKUDOS:0" \ + "Wrong arithmetic delta plus from reserves" + echo -n "Checking for unexpected reserves delta minus... " + check_balance \ + "reserves_total_arithmetic_delta_minus" \ + "TESTKUDOS:0" \ + "Wrong arithmetic delta minus from reserves" + + echo -n "Checking for unexpected arithmetic inconsistencies... " + check_no_report "amount-arithmetic-inconsistency" # cannot easily undo aggregator, hence full reload full_reload @@ -420,79 +461,38 @@ function test_1() { echo "===========1: normal run===========" run_audit + check_auditor_running echo "Checking output" # if an emergency was detected, that is a bug and we should fail echo -n "Test for emergencies... " - jq -e .emergencies[0] \ - < test-audit-coins.json \ - > /dev/null \ - && exit_fail "Unexpected emergency detected in ordinary run" \ - || echo "PASS" + check_no_report "emergency" echo -n "Test for emergencies by count... " - jq -e .emergencies_by_count[0] \ - < test-audit-coins.json \ - > /dev/null \ - && exit_fail "Unexpected emergency by count detected in ordinary run" \ - || echo "PASS" + check_no_report "emergency-by-count" echo -n "Test for wire inconsistencies... " - jq -e .wire_out_amount_inconsistencies[0] \ - < test-audit-wire.json \ - > /dev/null \ - && exit_fail "Unexpected wire out inconsistency detected in ordinary run" - jq -e .reserve_in_amount_inconsistencies[0] \ - < test-audit-wire.json \ - > /dev/null \ - && exit_fail "Unexpected reserve in inconsistency detected in ordinary run" - jq -e .misattribution_inconsistencies[0] \ - < test-audit-wire.json \ - > /dev/null \ - && exit_fail "Unexpected misattribution inconsistency detected in ordinary run" - jq -e .row_inconsistencies[0] \ - < test-audit-wire.json \ - > /dev/null \ - && exit_fail "Unexpected row inconsistency detected in ordinary run" - jq -e .row_minor_inconsistencies[0] \ - < test-audit-wire.json \ - > /dev/null \ - && exit_fail "Unexpected minor row inconsistency detected in ordinary run" - jq -e .wire_format_inconsistencies[0] \ - < test-audit-wire.json \ - > /dev/null \ - && exit_fail "Unexpected wire format inconsistencies detected in ordinary run" - - # TODO: check operation balances are correct (once we have all transaction types and wallet is deterministic) - # TODO: check revenue summaries are correct (once we have all transaction types and wallet is deterministic) - - echo "PASS" - - echo -n "Test for wire amounts... " - WIRED=$(jq -r .total_wire_in_delta_plus < test-audit-wire.json) - if [ "$WIRED" != "TESTKUDOS:0" ] - then - exit_fail "Expected total wire delta plus wrong, got $WIRED" - fi - WIRED=$(jq -r .total_wire_in_delta_minus < test-audit-wire.json) - if [ "$WIRED" != "TESTKUDOS:0" ] - then - exit_fail "Expected total wire delta minus wrong, got $WIRED" - fi - WIRED=$(jq -r .total_wire_out_delta_plus < test-audit-wire.json) - if [ "$WIRED" != "TESTKUDOS:0" ] - then - exit_fail "Expected total wire delta plus wrong, got $WIRED" - fi - WIRED=$(jq -r .total_wire_out_delta_minus < test-audit-wire.json) - if [ "$WIRED" != "TESTKUDOS:0" ] - then - exit_fail "Expected total wire delta minus wrong, got $WIRED" - fi - WIRED=$(jq -r .total_misattribution_in < test-audit-wire.json) - if [ "$WIRED" != "TESTKUDOS:0" ] - then - exit_fail "Expected total misattribution in wrong, got $WIRED" - fi + check_no_report "wire-out-inconsistency" + check_no_report "reserve-in-inconsistency" + check_no_report "misattribution-in-inconsistency" + check_no_report "row-inconsistency" + check_no_report "row-minor-inconsistencies" + check_no_report "wire-format-inconsistency" + + echo -n "Test for bad incoming delta plus... " + check_balance \ + "total_bad_amount_in_plus" \ + "TESTKUDOS:0" \ + "Expected total wire in delta plus wrong" + echo -n "Test for bad incoming delta minus... " + check_balance \ + "total_bad_amount_in_minus" \ + "TESTKUDOS:0" \ + "Expected total wire in delta minus wrong" + echo -n "Test for misattribution amounts... " + check_balance \ + "total_misattribution_in" \ + "TESTKUDOS:0" \ + "Expected total misattribution in wrong" # Database was unmodified, no need to undo echo "OK" @@ -504,38 +504,32 @@ function test_1() { function test_2() { echo "===========2: recoup amount inconsistency===========" - echo "UPDATE exchange.recoup SET amount_val=5 WHERE recoup_uuid=1" | psql -Aqt "$DB" + echo "UPDATE exchange.recoup SET amount.val=5 WHERE recoup_uuid=1" | psql -Aqt "$DB" run_audit + check_auditor_running # Reserve balance is now wrong - echo -n "Testing inconsistency detection... " - AMOUNT=$(jq -r .reserve_balance_summary_wrong_inconsistencies[0].auditor < test-audit-reserves.json) - if [ "$AMOUNT" != "TESTKUDOS:3" ] - then - exit_fail "Reserve auditor amount $AMOUNT is wrong" - fi - AMOUNT=$(jq -r .reserve_balance_summary_wrong_inconsistencies[0].exchange < test-audit-reserves.json) - if [ "$AMOUNT" != "TESTKUDOS:0" ] - then - exit_fail "Reserve exchange amount $AMOUNT is wrong" - fi + echo -n "Testing reserve balance inconsistency detection... " + check_report \ + "reserve-balance-summary-wrong-inconsistency" \ + "auditor_amount" "TESTKUDOS:3" + check_report \ + "reserve-balance-summary-wrong-inconsistency" \ + "exchange_amount" "TESTKUDOS:0" # Coin spent exceeded coin's value - AMOUNT=$(jq -r .amount_arithmetic_inconsistencies[0].auditor < test-audit-coins.json) - if [ "$AMOUNT" != "TESTKUDOS:2" ] - then - exit_fail "Coin auditor amount $AMOUNT is wrong" - fi - AMOUNT=$(jq -r .amount_arithmetic_inconsistencies[0].exchange < test-audit-coins.json) - if [ "$AMOUNT" != "TESTKUDOS:5" ] - then - exit_fail "Coin exchange amount $AMOUNT is wrong" - fi + echo -n "Testing coin arithmetic inconsistency detection... " + check_report \ + "amount-arithmetic-inconsistency" \ + "auditor_amount" "TESTKUDOS:2" + check_report \ + "amount-arithmetic-inconsistency" \ + "exchange_amount" "TESTKUDOS:5" echo "OK" # Undo database modification - echo "UPDATE exchange.recoup SET amount_val=2 WHERE recoup_uuid=1" | psql -Aqt "$DB" - + echo "UPDATE exchange.recoup SET amount.val=2 WHERE recoup_uuid=1" | psql -Aqt "$DB" + full_reload } @@ -543,27 +537,26 @@ function test_2() { function test_3() { echo "===========3: recoup-refresh amount inconsistency===========" - echo "UPDATE exchange.recoup_refresh SET amount_val=5 WHERE recoup_refresh_uuid=1" | psql -Aqt "$DB" + echo "UPDATE exchange.recoup_refresh SET amount.val=5 WHERE recoup_refresh_uuid=1" | psql -Aqt "$DB" run_audit + check_auditor_running echo -n "Testing inconsistency detection... " # Coin spent exceeded coin's value - AMOUNT=$(jq -r .total_arithmetic_delta_minus < test-audit-coins.json) - if [ "$AMOUNT" != "TESTKUDOS:5" ] - then - exit_fail "Arithmetic delta minus amount $AMOUNT is wrong" - fi - AMOUNT=$(jq -r .total_arithmetic_delta_plus < test-audit-coins.json) - if [ "$AMOUNT" != "TESTKUDOS:0" ] - then - exit_fail "Arithmetic delta plus amount $AMOUNT is wrong" - fi + check_balance \ + "coins_total_arithmetic_delta_minus" \ + "TESTKUDOS:5" \ + "Arithmetic delta minus amount is wrong" + check_balance \ + "coins_total_arithmetic_delta_plus" \ + "TESTKUDOS:0" \ + "Arithmetic delta plus amount is wrong" echo "OK" # Undo database modification - echo "UPDATE exchange.recoup_refresh SET amount_val=0 WHERE recoup_refresh_uuid=1" | psql -Aqt "$DB" - + echo "UPDATE exchange.recoup_refresh SET amount.val=0 WHERE recoup_refresh_uuid=1" | psql -Aqt "$DB" + full_reload } @@ -574,23 +567,22 @@ function test_4() { echo "DELETE FROM exchange.denomination_revocations;" | psql -Aqt "$DB" run_audit + check_auditor_running echo -n "Testing inconsistency detection... " - # Coin spent exceeded coin's value - jq -e .bad_sig_losses[0] \ - < test-audit-coins.json \ - > /dev/null \ - || exit_fail "Bad recoup not detected" - AMOUNT=$(jq -r .irregular_loss < test-audit-coins.json) - if [ "$AMOUNT" == "TESTKUDOS:0" ] - then - exit_fail "Total bad sig losses are wrong" - fi - TAB=$(jq -r .row_inconsistencies[0].table < test-audit-reserves.json) - if [ "$TAB" != "recoup" ] - then - exit_fail "Wrong table for row inconsistency, got $TAB" - fi + # Recoup of a denomination that was never revoked is not legitimate + check_report_neg \ + "bad-sig-losses" \ + "loss" "TESTKUDOS:0" + echo -n "Testing irregular loss balance... " + check_not_balance \ + "coin_irregular_loss" \ + "TESTKUDOS:0" \ + "Total bad sig losses are wrong" + echo -n "Testing row inconsistency table attribution... " + check_report_any \ + "row-inconsistency" \ + "row_table" "recoup" echo "OK" # Undo database modification (can't easily undo DELETE, so full reload) @@ -716,24 +708,54 @@ taler-wallet-cli -h \ || exit_skip "taler-wallet-cli required" MY_TMP_DIR=$(mktemp -d /tmp/taler-auditor-basedbXXXXXX) +export MY_TMP_DIR +echo "Using $MY_TMP_DIR for logging and temporary data" echo -n "Testing for Postgres " [ $(id -u) == 0 ] || perform_dbinit -echo "Generating fresh database at $MY_TMP_DIR" -if faketime -f '-1 d' ./generate-revoke-basedb.sh "$MY_TMP_DIR/$DB" +MYDIR="${MY_TMP_DIR}/basedb" +mkdir -p "${MYDIR}" + +# Generating the reference database is by far the slowest part of this +# test. Set REUSE_BASEDB_DIR to the directory printed at the end of a +# previous run to audit that database again instead of regenerating it. +if [ -z "${REUSE_BASEDB_DIR+x}" ] then - check_with_database "$MY_TMP_DIR/$DB" - if [ "x$fail" != "x0" ] + echo "Generating fresh database at $MYDIR" + set +e + faketime -f '-1 d' ./generate-revoke-basedb.sh "$MYDIR/$DB" + GENSTATUS=$? + set -e + if [ 77 = "$GENSTATUS" ] then - exit "$fail" - else - echo "Cleaning up $MY_TMP_DIR..." - rm -rf "$MY_TMP_DIR" || echo "Removing $MY_TMP_DIR failed" + # Prerequisite missing (currently: recoup is not implemented by the + # exchange, see FIXME_9828); report as skipped, not as a failure. + echo "SKIPPING: could not generate the revocation database" + exit 77 fi + if [ 0 != "$GENSTATUS" ] + then + echo "Generation failed" + exit 1 + fi + echo "To reuse this database in the future, use:" + echo "export REUSE_BASEDB_DIR=$MY_TMP_DIR" else - echo "Generation failed" + echo "Reusing existing database from ${REUSE_BASEDB_DIR}" + cp -r "${REUSE_BASEDB_DIR}/basedb"/* "${MYDIR}/" +fi + +check_with_database "$MYDIR/$DB" +if [ "x$fail" != "x0" ] +then + exit "$fail" +fi + +if [ -z "${REUSE_BASEDB_DIR+x}" ] +then + echo "Run 'export REUSE_BASEDB_DIR=${MY_TMP_DIR}' to re-run tests against the same database" fi exit 0 diff --git a/src/auditordb/iterate_amount_arithmetic_inconsistencies.c b/src/auditordb/iterate_amount_arithmetic_inconsistencies.c @@ -128,7 +128,7 @@ TALER_AUDITORDB_iterate_amount_arithmetic_inconsistencies ( enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "iterate_amount_arithmetic_inconsistencies_inconsistency_select_desc", + "iterate_amount_arithmetic_inconsistencies_desc", "SELECT" " row_id" ",problem_row_id" @@ -144,7 +144,7 @@ TALER_AUDITORDB_iterate_amount_arithmetic_inconsistencies ( " LIMIT $3" ); PREPARE (pg, - "iterate_amount_arithmetic_inconsistencies_inconsistency_select_asc", + "iterate_amount_arithmetic_inconsistencies_asc", "SELECT" " row_id" ",problem_row_id" @@ -162,8 +162,8 @@ TALER_AUDITORDB_iterate_amount_arithmetic_inconsistencies ( qs = GNUNET_PQ_eval_prepared_multi_select ( pg->conn, (limit > 0) - ? "iterate_amount_arithmetic_inconsistencies_inconsistency_select_asc" - : "iterate_amount_arithmetic_inconsistencies_inconsistency_select_desc", + ? "iterate_amount_arithmetic_inconsistencies_asc" + : "iterate_amount_arithmetic_inconsistencies_desc", params, &amount_arithmetic_inconsistency_cb, &dcc); diff --git a/src/auditordb/iterate_denomination_key_validity_withdraw_inconsistencies.c b/src/auditordb/iterate_denomination_key_validity_withdraw_inconsistencies.c @@ -127,7 +127,7 @@ TALER_AUDITORDB_iterate_denomination_key_validity_withdraw_inconsistencies ( enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "iterate_denomination_key_validity_withdraw_inconsistencies_inconsistency_get_desc", + "iterate_denomination_key_validity_withdraw_inconsistencies_desc", "SELECT" " row_id" ",problem_row_id" @@ -142,7 +142,7 @@ TALER_AUDITORDB_iterate_denomination_key_validity_withdraw_inconsistencies ( " LIMIT $3" ); PREPARE (pg, - "iterate_denomination_key_validity_withdraw_inconsistencies_inconsistency_get_asc", + "iterate_denomination_key_validity_withdraw_inconsistencies_asc", "SELECT" " row_id" ",problem_row_id" @@ -160,9 +160,9 @@ TALER_AUDITORDB_iterate_denomination_key_validity_withdraw_inconsistencies ( pg->conn, (limit > 0) ? - "iterate_denomination_key_validity_withdraw_inconsistencies_inconsistency_get_asc" + "iterate_denomination_key_validity_withdraw_inconsistencies_asc" : - "iterate_denomination_key_validity_withdraw_inconsistencies_inconsistency_get_desc", + "iterate_denomination_key_validity_withdraw_inconsistencies_desc", params, &denomination_key_validity_withdraw_inconsistency_cb, &dcc); diff --git a/src/auditordb/iterate_misattribution_in_inconsistencies.c b/src/auditordb/iterate_misattribution_in_inconsistencies.c @@ -127,7 +127,7 @@ TALER_AUDITORDB_iterate_misattribution_in_inconsistencies (struct enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "iterate_misattribution_in_inconsistencies_inconsistency_get_desc", + "iterate_misattribution_in_inconsistencies_desc", "SELECT" " row_id" ",amount" @@ -141,7 +141,7 @@ TALER_AUDITORDB_iterate_misattribution_in_inconsistencies (struct " LIMIT $3" ); PREPARE (pg, - "iterate_misattribution_in_inconsistencies_inconsistency_get_asc", + "iterate_misattribution_in_inconsistencies_asc", "SELECT" " row_id" ",amount" @@ -157,8 +157,8 @@ TALER_AUDITORDB_iterate_misattribution_in_inconsistencies (struct qs = GNUNET_PQ_eval_prepared_multi_select ( pg->conn, (limit > 0) - ? "iterate_misattribution_in_inconsistencies_inconsistency_get_asc" - : "iterate_misattribution_in_inconsistencies_inconsistency_get_desc", + ? "iterate_misattribution_in_inconsistencies_asc" + : "iterate_misattribution_in_inconsistencies_desc", params, &misattribution_in_inconsistency_cb, &dcc); diff --git a/src/auditordb/iterate_reserve_balance_insufficient_inconsistencies.c b/src/auditordb/iterate_reserve_balance_insufficient_inconsistencies.c @@ -132,7 +132,7 @@ TALER_AUDITORDB_iterate_reserve_balance_insufficient_inconsistencies (struct enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "iterate_reserve_balance_insufficient_inconsistencies_inconsistency_get_desc", + "iterate_reserve_balance_insufficient_inconsistencies_desc", "SELECT" " row_id" ",reserve_pub" @@ -146,7 +146,7 @@ TALER_AUDITORDB_iterate_reserve_balance_insufficient_inconsistencies (struct " LIMIT $3" ); PREPARE (pg, - "iterate_reserve_balance_insufficient_inconsistencies_inconsistency_get_asc", + "iterate_reserve_balance_insufficient_inconsistencies_asc", "SELECT" " row_id" ",reserve_pub" @@ -163,9 +163,9 @@ TALER_AUDITORDB_iterate_reserve_balance_insufficient_inconsistencies (struct pg->conn, (limit > 0) ? - "iterate_reserve_balance_insufficient_inconsistencies_inconsistency_get_asc" + "iterate_reserve_balance_insufficient_inconsistencies_asc" : - "iterate_reserve_balance_insufficient_inconsistencies_inconsistency_get_desc", + "iterate_reserve_balance_insufficient_inconsistencies_desc", params, &reserve_balance_insufficient_inconsistency_cb, &dcc); diff --git a/src/auditordb/iterate_reserve_balance_summary_wrong_inconsistencies.c b/src/auditordb/iterate_reserve_balance_summary_wrong_inconsistencies.c @@ -129,7 +129,7 @@ TALER_AUDITORDB_iterate_reserve_balance_summary_wrong_inconsistencies (struct enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "iterate_reserve_balance_summary_wrong_inconsistencies_inconsistency_get_desc", + "iterate_reserve_balance_summary_wrong_inconsistencies_desc", "SELECT" " row_id" ",reserve_pub" @@ -143,7 +143,7 @@ TALER_AUDITORDB_iterate_reserve_balance_summary_wrong_inconsistencies (struct " LIMIT $3" ); PREPARE (pg, - "iterate_reserve_balance_summary_wrong_inconsistencies_inconsistency_get_asc", + "iterate_reserve_balance_summary_wrong_inconsistencies_asc", "SELECT" " row_id" ",reserve_pub" @@ -160,9 +160,9 @@ TALER_AUDITORDB_iterate_reserve_balance_summary_wrong_inconsistencies (struct pg->conn, (limit > 0) ? - "iterate_reserve_balance_summary_wrong_inconsistencies_inconsistency_get_asc" + "iterate_reserve_balance_summary_wrong_inconsistencies_asc" : - "iterate_reserve_balance_summary_wrong_inconsistencies_inconsistency_get_desc", + "iterate_reserve_balance_summary_wrong_inconsistencies_desc", params, &reserve_balance_summary_wrong_inconsistency_cb, &dcc); diff --git a/src/auditordb/iterate_reserve_not_closed_inconsistencies.c b/src/auditordb/iterate_reserve_not_closed_inconsistencies.c @@ -126,7 +126,7 @@ TALER_AUDITORDB_iterate_reserve_not_closed_inconsistencies (struct enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "iterate_reserve_not_closed_inconsistencies_inconsistency_get_desc", + "iterate_reserve_not_closed_inconsistencies_desc", "SELECT" " row_id" ",reserve_pub" @@ -141,7 +141,7 @@ TALER_AUDITORDB_iterate_reserve_not_closed_inconsistencies (struct " LIMIT $3" ); PREPARE (pg, - "iterate_reserve_not_closed_inconsistencies_inconsistency_get_asc", + "iterate_reserve_not_closed_inconsistencies_asc", "SELECT" " row_id" ",reserve_pub" @@ -158,8 +158,8 @@ TALER_AUDITORDB_iterate_reserve_not_closed_inconsistencies (struct qs = GNUNET_PQ_eval_prepared_multi_select ( pg->conn, (limit > 0) - ? "iterate_reserve_not_closed_inconsistencies_inconsistency_get_asc" - : "iterate_reserve_not_closed_inconsistencies_inconsistency_get_desc", + ? "iterate_reserve_not_closed_inconsistencies_asc" + : "iterate_reserve_not_closed_inconsistencies_desc", params, &reserve_not_closed_inconsistency_cb, &dcc); diff --git a/src/auditordb/meson.build b/src/auditordb/meson.build @@ -53,6 +53,7 @@ auditor_0002_sql = [ generated_sql = [ ['versioning.sql', ['versioning.sql']], ['drop.sql', ['drop.sql']], + ['restart.sql', ['restart.sql']], ['procedures.sql', procedures_sql], ['auditor-0001.sql', ['auditor-0001.sql']], ['auditor-0002.sql', auditor_0002_sql], diff --git a/src/auditordb/restart.sql b/src/auditordb/restart.sql @@ -39,6 +39,7 @@ DELETE FROM auditor_coin_inconsistency; DELETE FROM auditor_denomination_key_validity_withdraw_inconsistency; DELETE FROM auditor_denomination_pending; DELETE FROM auditor_denominations_without_sigs; +DELETE FROM auditor_early_aggregations; DELETE FROM auditor_emergency; DELETE FROM auditor_emergency_by_count; DELETE FROM auditor_fee_time_inconsistency;