commit 9d6dc3cdc14b574ddff38224f6ad9fa8e0ec0a6e
parent 40cd7a3af2abe8fa556a19b1708d76cbdbc36065
Author: Christian Grothoff <christian@grothoff.org>
Date: Fri, 31 Jul 2026 23:33:46 +0200
fix test-auditor.sh
Diffstat:
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;