From 342cccc384148e93142ed9dca59ad23e58388564 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 19 Jan 2020 14:22:34 +0100 Subject: [PATCH] do not rely on filetime, as Git does not preserve it --- contrib/auditor-report.tex.j2 | 30 +++++++++------- src/auditor/auditor-basedb.age | 1 + src/auditor/generate-auditor-basedb.sh | 4 ++- src/auditor/taler-auditor.c | 7 ++-- src/auditor/test-auditor.sh | 48 ++++++++++++++++++++++---- 5 files changed, 66 insertions(+), 24 deletions(-) create mode 100644 src/auditor/auditor-basedb.age diff --git a/contrib/auditor-report.tex.j2 b/contrib/auditor-report.tex.j2 index 8f142402d..a21ded1c4 100644 --- a/contrib/auditor-report.tex.j2 +++ b/contrib/auditor-report.tex.j2 @@ -236,7 +236,7 @@ The total amount the exchange currently lags behind in reserve closures is Note that some minimal lag may be normal as transactions may be in-flight. -% Table generation tested by testcase #22 in test-auditor.sh +% Table generation tested by testcase #21 in test-auditor.sh {% if wire.reserve_lag_details|length() == 0 %} {\bf No closure transfers that are lagging behind detected.} @@ -295,7 +295,7 @@ The total amount the exchange currently lags behind is Note that some lag is perfectly normal. Below, we report {\em all} deposit confirmations that are lagging behind. -% Table generation tested by testcase #25 in test-auditor.sh +% Table generation tested by testcase #24 in test-auditor.sh {% if data.deposit_confirmation_inconsistencies|length() == 0 %} {\bf No deposit confirmations that are lagging behind detected.} @@ -400,7 +400,13 @@ The total loss from emergencies detected by counting coins could be up to \subsubsection{Emergencies by value deposited} -% Table generation tested by testcase #18 in test-auditor.sh +Note that emergencies by value deposited can {\em also} arise if the exchange +fails to properly detect double spending (or simply fails to properly account +for the remaining balance of a coin). So in combintation with arithmetic +problems (Section~\ref{sec:arithmetic}) issues in this section are not a clear +indicator that the exchange's private signing key was compromised. + +% Table generation tested by testcases #18, #25 in test-auditor.sh {% if data.emergencies|length() == 0 %} {\bf No emergencies by value detected.} @@ -434,7 +440,7 @@ The total loss from emergencies detected by counting coins could be up to {% endif %} -\subsection{Arithmetic problems} +\subsection{Arithmetic problems} \label{sec:arithmetic} This section lists cases where the arithmetic of the exchange involving amounts disagrees with the arithmetic of the auditor. @@ -527,7 +533,7 @@ violations do not imply that the wire transfer was actually made (as that is a separate check). Note that not making the wire transfer would be reported separately in Section~\ref{sec:wire_check_out}. -% Table generation tested by testcase #24 in test-auditor.sh +% Table generation tested by testcase #23 in test-auditor.sh {% if data.wire_out_inconsistencies|length() == 0 %} {\bf All aggregations matched up.} @@ -569,7 +575,7 @@ in amounts that matter for profit/loss calculations of the exchange. When an exchange merely shifted money from customers to merchants (or vice versa) without any effects on its own balance, those entries are excluded from the total. -% Table generation tested by testcase #XX in test-auditor.sh +% Table generation tested by testcase #25 in test-auditor.sh {% if data.coin_inconsistencies|length() == 0 %} {\bf All coin histories were unproblematic.} @@ -896,11 +902,9 @@ have a clear financial impact. \subsection{Outgoing wire transfer subject issues} This section describes issues found by the wire auditor that -relate to outgoing wire transfers being malformed. -This happens if the exchange somehow creates wire transfers -with duplicate or malformed wire transfer subjects. +relate to outgoing wire transfers subjects being duplicated. -% Table generation tested by testcase #19 in test-auditor.sh +% Table generation tested by testcase #XX in test-auditor.sh {% if wire.wire_format_inconsistencies|length() == 0 %} {\bf No wire format inconsistencies found.} @@ -972,7 +976,7 @@ with respect to what wire fee it charges at what time. This section describes issues found that do not have a clear financial impact. -% Table generation tested by testcase #13/#15 in test-auditor.sh +% Table generation tested by testcase #13/#15/#25 in test-auditor.sh {% if data.row_inconsistencies|length() == 0 %} {\bf No row inconsistencies found.} @@ -1013,7 +1017,7 @@ This section describes cases where the exchange did not close a reserve and wire back the remaining funds when the reserve expired. -% Table generation tested by testcase #21 in test-auditor.sh +% Table generation tested by testcase #20 in test-auditor.sh {% if data.reserve_not_closed_inconsistencies|length() == 0 %} {\bf All expired reserves were closed.} @@ -1085,7 +1089,7 @@ withdrawal at the time when the exchange claims to have signed a coin with it. This would be irregular, but has no obvious financial implications. -% Table generation tested by testcase #23 in test-auditor.sh +% Table generation tested by testcase #22 in test-auditor.sh {% if data.denomination_key_validity_withdraw_inconsistencies|length() == 0 %} {\bf All denomination keys were valid at the time of withdrawals.} diff --git a/src/auditor/auditor-basedb.age b/src/auditor/auditor-basedb.age new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/src/auditor/auditor-basedb.age @@ -0,0 +1 @@ +42 diff --git a/src/auditor/generate-auditor-basedb.sh b/src/auditor/generate-auditor-basedb.sh index 3f896b31f..d23b67431 100755 --- a/src/auditor/generate-auditor-basedb.sh +++ b/src/auditor/generate-auditor-basedb.sh @@ -3,7 +3,8 @@ # testing from a 'correct' interaction between exchange, # wallet and merchant. # -# Creates $BASEDB.sql, $BASEDB.fees and $BASEDB.mpub. +# Creates $BASEDB.sql, $BASEDB.fees, $BASEDB.mpub and +# $BASEDB.age. # Default $BASEDB is "auditor-basedb", override via $1. # # Currently must be run online as it interacts with @@ -144,6 +145,7 @@ echo $MASTER_PUB > ${BASEDB}.mpub WIRE_FEE_DIR=`taler-config -c $CONF -f -s exchangedb -o WIREFEE_BASE_DIR` cp $WIRE_FEE_DIR/x-taler-bank.fee ${BASEDB}.fees +date +%s > ${BASEDB}.age # clean up echo "Final clean up" diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c index 5f484d752..6752b34ab 100644 --- a/src/auditor/taler-auditor.c +++ b/src/auditor/taler-auditor.c @@ -2422,7 +2422,7 @@ check_transaction_history_for_deposit (const struct return GNUNET_SYSERR; } - /* Now check that 'spent' is less or equal than total coin value */ + /* Now check that 'spent' is less or equal than the total coin value */ TALER_amount_ntoh (&value, &issue->value); if (1 == TALER_amount_cmp (&spent, @@ -4658,14 +4658,13 @@ analyze_coins (void *cls) if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qsp) { GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, - _ ( - "First analysis using this auditor, starting audit from scratch\n")); + "First analysis using this auditor, starting from scratch\n"); } else { ppc_start = ppc; GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _ ("Resuming coin audit at %llu/%llu/%llu/%llu/%llu\n"), + "Resuming coin audit at %llu/%llu/%llu/%llu/%llu\n", (unsigned long long) ppc.last_deposit_serial_id, (unsigned long long) ppc.last_melt_serial_id, (unsigned long long) ppc.last_refund_serial_id, diff --git a/src/auditor/test-auditor.sh b/src/auditor/test-auditor.sh index 832bfb836..06f1b3707 100755 --- a/src/auditor/test-auditor.sh +++ b/src/auditor/test-auditor.sh @@ -9,7 +9,7 @@ set -eu # Set of numbers for all the testcases. # When adding new tests, increase the last number: -ALL_TESTS=`seq 0 24` +ALL_TESTS=`seq 0 25` # $TESTS determines which tests we should run. # This construction is used to make it easy to @@ -118,7 +118,7 @@ function run_audit () { # Do a full reload of the (original) database full_reload() { - echo "Doing full reload of the database..." + echo -n "Doing full reload of the database... " dropdb $DB 2> /dev/null || true createdb -T template0 $DB || exit_skip "could not create database" # Import pre-generated database, -q(ietly) using single (-1) transaction @@ -1382,14 +1382,50 @@ full_reload } +# Test for inconsistent coin history. +function test_25() { + +echo "=========25: inconsistent coin history=========" +# Drop refund, so coin history is bogus. +echo "DELETE FROM refunds WHERE refund_serial_id=1;" | psql -Aqt $DB + +run_audit aggregator + +echo -n "Testing inconsistency detection... " + +jq -e .coin_inconsistencies[0] < test-audit.json > /dev/null || exit_fail "Coin inconsistency NOT detected" + +jq -e .row_inconsistencies[0] < test-audit.json > /dev/null || exit_fail "Coin history verification failure NOT reported" + +# Note: if the wallet withdrew much more than it spent, this might indeed +# go legitimately unnoticed. +jq -e .emergencies[0] < test-audit.json > /dev/null || exit_fail "Denomination value emergency NOT reported" + +AMOUNT=`jq -er .total_coin_delta_minus < test-audit.json` +if test x$AMOUNT = xTESTKUDOS:0 +then + exit_fail "Expected non-zero total inconsistency amount from coins" +fi +# Note: if the wallet withdrew much more than it spent, this might indeed +# go legitimately unnoticed. +COUNT=`jq -er .emergencies_risk_by_amount < test-audit.json` +if test x$AMOUNT = xTESTKUDOS:0 +then + exit_fail "Expected non-zero emergency-by-amount" +fi +echo PASS + +# cannot easily undo DELETE, hence full reload +full_reload +} + + # ************************************************** # FIXME: Add more tests here! :-) # Specifically: # - revocation (payback, accepting # of coins despite denomination revocation) -# - refunds -# - arithmetic problems # ************************************************** @@ -1413,8 +1449,8 @@ check_with_database() cp ${BASEDB}.fees $WIRE_FEE_DIR/x-taler-bank.fee # Determine database age - echo "Calculating database age based on ${BASEDB}.fees" - AGE=`stat -c %Y ${BASEDB}.fees` + echo "Calculating database age based on ${BASEDB}.age" + AGE=`cat ${BASEDB}.age` NOW=`date +%s` # NOTE: expr "fails" if the result is zero. DATABASE_AGE=`expr ${NOW} - ${AGE} || true`