From f052527ea50e9e6b1de165833e83d7f191a121d1 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 26 Mar 2020 20:54:41 +0100 Subject: fix recoup-refresh audit logic --- src/auditor/taler-helper-auditor-coins.c | 158 +++++++++++++++++++--------- src/exchangedb/plugin_exchangedb_postgres.c | 39 ++++--- src/exchangedb/test_exchangedb.c | 1 + src/include/taler_exchangedb_plugin.h | 4 + 4 files changed, 136 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c index 33591cec9..9f9f6dc93 100644 --- a/src/auditor/taler-helper-auditor-coins.c +++ b/src/auditor/taler-helper-auditor-coins.c @@ -190,6 +190,10 @@ report_emergency_by_amount ( const struct TALER_Amount *risk, const struct TALER_Amount *loss) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Reporting emergency on denomination `%s' over loss of %s\n", + GNUNET_h2s (&issue->denom_hash), + TALER_amount2s (loss)); TALER_ARL_report (report_emergencies, json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}", "denompub_hash", @@ -808,14 +812,14 @@ withdraw_cb (void *cls, GNUNET_h2s (&dh), TALER_amount2s (&value)); ds->num_issued++; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "New balance of denomination `%s' is %s\n", - GNUNET_h2s (&dh), - TALER_amount2s (&ds->denom_balance)); GNUNET_assert (GNUNET_OK == TALER_amount_add (&ds->denom_balance, &ds->denom_balance, &value)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "New balance of denomination `%s' is %s\n", + GNUNET_h2s (&dh), + TALER_amount2s (&ds->denom_balance)); GNUNET_assert (GNUNET_OK == TALER_amount_add (&total_escrow_balance, &total_escrow_balance, @@ -1349,7 +1353,6 @@ deposit_cb (void *cls, struct CoinContext *cc = cls; const struct TALER_DenominationKeyValidityPS *issue; struct DenominationSummary *ds; - struct TALER_Amount tmp; enum GNUNET_DB_QueryStatus qs; (void) wire_deadline; @@ -1459,6 +1462,8 @@ deposit_cb (void *cls, } else { + struct TALER_Amount tmp; + if (GNUNET_SYSERR == TALER_amount_subtract (&tmp, &ds->denom_balance, @@ -1696,7 +1701,6 @@ check_recoup (struct CoinContext *cc, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_DenominationBlindingKeyP *coin_blind) { - struct TALER_RecoupRequestPS pr; struct DenominationSummary *ds; enum GNUNET_DB_QueryStatus qs; const struct TALER_DenominationKeyValidityPS *issue; @@ -1711,15 +1715,14 @@ check_recoup (struct CoinContext *cc, "row", (json_int_t) rowid, "loss", TALER_JSON_from_amount (amount), "key_pub", GNUNET_JSON_from_data_auto ( - &pr.h_denom_pub))); + &coin->denom_pub_hash))); GNUNET_assert (GNUNET_OK == TALER_amount_add (&total_bad_sig_loss, &total_bad_sig_loss, amount)); } - qs = TALER_ARL_get_denomination_info (denom_pub, - &issue, - &pr.h_denom_pub); + qs = TALER_ARL_get_denomination_info_by_hash (&coin->denom_pub_hash, + &issue); if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) { report_row_inconsistency ("recoup", @@ -1735,28 +1738,34 @@ check_recoup (struct CoinContext *cc, cc->qs = qs; return GNUNET_SYSERR; } - pr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP); - pr.purpose.size = htonl (sizeof (pr)); - pr.coin_pub = coin->coin_pub; - pr.coin_blind = *coin_blind; - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP, - &pr.purpose, - &coin_sig->eddsa_signature, - &coin->coin_pub.eddsa_pub)) { - TALER_ARL_report (report_bad_sig_losses, - json_pack ("{s:s, s:I, s:o, s:o}", - "operation", "recoup", - "row", (json_int_t) rowid, - "loss", TALER_JSON_from_amount (amount), - "coin_pub", GNUNET_JSON_from_data_auto ( - &coin->coin_pub))); - GNUNET_assert (GNUNET_OK == - TALER_amount_add (&total_bad_sig_loss, - &total_bad_sig_loss, - amount)); - return GNUNET_OK; + struct TALER_RecoupRequestPS pr = { + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP), + .purpose.size = htonl (sizeof (pr)), + .coin_pub = coin->coin_pub, + .coin_blind = *coin_blind, + .h_denom_pub = coin->denom_pub_hash + }; + + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP, + &pr.purpose, + &coin_sig->eddsa_signature, + &coin->coin_pub.eddsa_pub)) + { + TALER_ARL_report (report_bad_sig_losses, + json_pack ("{s:s, s:I, s:o, s:o}", + "operation", "recoup", + "row", (json_int_t) rowid, + "loss", TALER_JSON_from_amount (amount), + "coin_pub", GNUNET_JSON_from_data_auto ( + &coin->coin_pub))); + GNUNET_assert (GNUNET_OK == + TALER_amount_add (&total_bad_sig_loss, + &total_bad_sig_loss, + amount)); + return GNUNET_OK; + } } ds = get_denomination_summary (cc, issue, @@ -1803,7 +1812,7 @@ check_recoup (struct CoinContext *cc, * @param amount how much should be added back to the reserve * @param reserve_pub public key of the reserve * @param coin public information about the coin - * @param denom_pub denomination public key of @a coin + * @param denom_pub_hash hash of denomination public key of @a coin * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_RECOUP * @param coin_blind blinding factor used to blind the coin * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop @@ -1844,6 +1853,7 @@ recoup_cb (void *cls, * @param timestamp when did we receive the recoup request * @param amount how much should be added back to the reserve * @param old_coin_pub original coin that was refreshed to create @a coin + * @param old_denom_pub public key of @a old_coin_pub * @param coin public information about the coin * @param denom_pub denomination public key of @a coin * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_RECOUP @@ -1856,17 +1866,65 @@ recoup_refresh_cb (void *cls, struct GNUNET_TIME_Absolute timestamp, const struct TALER_Amount *amount, const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + const struct GNUNET_HashCode *old_denom_pub_hash, const struct TALER_CoinPublicInfo *coin, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_DenominationBlindingKeyP *coin_blind) { struct CoinContext *cc = cls; + const struct TALER_DenominationKeyValidityPS *issue; + enum GNUNET_DB_QueryStatus qs; - GNUNET_assert (rowid >= ppc.last_recoup_refresh_serial_id); /* should be monotonically increasing */ - ppc.last_recoup_refresh_serial_id = rowid + 1; (void) timestamp; (void) old_coin_pub; + GNUNET_assert (rowid >= ppc.last_recoup_refresh_serial_id); /* should be monotonically increasing */ + ppc.last_recoup_refresh_serial_id = rowid + 1; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Recoup-refresh amount is %s\n", + TALER_amount2s (amount)); + + /* Update old coin's denomination balance summary */ + qs = TALER_ARL_get_denomination_info_by_hash (old_denom_pub_hash, + &issue); + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS >= qs) + { + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + cc->qs = qs; + return GNUNET_SYSERR; + } + report_row_inconsistency ("refresh-recoup", + rowid, + "denomination key of old coin not found"); + } + else + { + struct DenominationSummary *dso; + + dso = get_denomination_summary (cc, + issue, + old_denom_pub_hash); + if (NULL == dso) + { + report_row_inconsistency ("refresh_reveal", + rowid, + "denomination key for old coin unknown to auditor"); + } + else + { + GNUNET_assert (GNUNET_OK == + TALER_amount_add (&dso->denom_balance, + &dso->denom_balance, + amount)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "New balance of denomination `%s' after refresh-recoup is %s\n", + GNUNET_h2s (&issue->denom_hash), + TALER_amount2s (&dso->denom_balance)); + } + } + return check_recoup (cc, rowid, amount, @@ -1970,13 +2028,13 @@ analyze_coins (void *cls) if (0 > cc.qs) return cc.qs; - /* process refreshs */ + /* process recoups */ if (0 > - (qs = TALER_ARL_edb->select_refreshes_above_serial_id ( + (qs = TALER_ARL_edb->select_recoup_refresh_above_serial_id ( TALER_ARL_edb->cls, TALER_ARL_esession, - ppc.last_melt_serial_id, - &refresh_session_cb, + ppc.last_recoup_refresh_serial_id, + &recoup_refresh_cb, &cc))) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -1984,14 +2042,12 @@ analyze_coins (void *cls) } if (0 > cc.qs) return cc.qs; - - /* process deposits */ if (0 > - (qs = TALER_ARL_edb->select_deposits_above_serial_id ( + (qs = TALER_ARL_edb->select_recoup_above_serial_id ( TALER_ARL_edb->cls, TALER_ARL_esession, - ppc.last_deposit_serial_id, - &deposit_cb, + ppc.last_recoup_serial_id, + &recoup_cb, &cc))) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -2000,13 +2056,13 @@ analyze_coins (void *cls) if (0 > cc.qs) return cc.qs; - /* process recoups */ + /* process refreshs */ if (0 > - (qs = TALER_ARL_edb->select_recoup_above_serial_id ( + (qs = TALER_ARL_edb->select_refreshes_above_serial_id ( TALER_ARL_edb->cls, TALER_ARL_esession, - ppc.last_recoup_serial_id, - &recoup_cb, + ppc.last_melt_serial_id, + &refresh_session_cb, &cc))) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -2014,12 +2070,14 @@ analyze_coins (void *cls) } if (0 > cc.qs) return cc.qs; + + /* process deposits */ if (0 > - (qs = TALER_ARL_edb->select_recoup_refresh_above_serial_id ( + (qs = TALER_ARL_edb->select_deposits_above_serial_id ( TALER_ARL_edb->cls, TALER_ARL_esession, - ppc.last_recoup_refresh_serial_id, - &recoup_refresh_cb, + ppc.last_deposit_serial_id, + &deposit_cb, &cc))) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 31f92d58c..c21f1b1a9 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -1192,8 +1192,8 @@ postgres_get_session (void *cls) ",coin_blind" ",h_blind_ev" ",coins.denom_pub_hash" - ",denoms.denom_pub" ",coins.denom_sig" + ",denoms.denom_pub" ",amount_val" ",amount_frac" " FROM recoup" @@ -1213,24 +1213,27 @@ postgres_get_session (void *cls) " recoup_refresh_uuid" ",timestamp" ",rc.old_coin_pub" - ",coin_pub" + ",old_coins.denom_pub_hash AS old_denom_pub_hash" + ",recoup_refresh.coin_pub" ",coin_sig" ",coin_blind" - ",h_blind_ev" - ",coins.denom_pub_hash" ",denoms.denom_pub" - ",coins.denom_sig" + ",h_blind_ev" + ",new_coins.denom_pub_hash" + ",new_coins.denom_sig" ",amount_val" ",amount_frac" " FROM recoup_refresh" - " JOIN refresh_revealed_coins rrc" + " INNER JOIN refresh_revealed_coins rrc" " ON (rrc.h_coin_ev = h_blind_ev)" - " JOIN refresh_commitments rc" + " INNER JOIN refresh_commitments rc" " ON (rrc.rc = rc.rc)" - " JOIN known_coins coins" - " USING (coin_pub)" - " JOIN denominations denoms" - " ON (coins.denom_pub_hash = denoms.denom_pub_hash)" + " INNER JOIN known_coins old_coins" + " ON (rc.old_coin_pub = old_coins.coin_pub)" + " INNER JOIN known_coins new_coins" + " ON (new_coins.coin_pub = recoup_refresh.coin_pub)" + " INNER JOIN denominations denoms" + " ON (new_coins.denom_pub_hash = denoms.denom_pub_hash)" " WHERE recoup_refresh_uuid>=$1" " ORDER BY recoup_refresh_uuid ASC;", 1), @@ -6381,8 +6384,8 @@ recoup_serial_helper_cb (void *cls, struct TALER_CoinPublicInfo coin; struct TALER_CoinSpendSignatureP coin_sig; struct TALER_DenominationBlindingKeyP coin_blind; - struct TALER_DenominationPublicKey denom_pub; struct TALER_Amount amount; + struct TALER_DenominationPublicKey denom_pub; struct GNUNET_HashCode h_blind_ev; struct GNUNET_TIME_Absolute timestamp; struct GNUNET_PQ_ResultSpec rs[] = { @@ -6394,6 +6397,8 @@ recoup_serial_helper_cb (void *cls, &reserve_pub), GNUNET_PQ_result_spec_auto_from_type ("coin_pub", &coin.coin_pub), + GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", + &denom_pub.rsa_public_key), GNUNET_PQ_result_spec_auto_from_type ("coin_sig", &coin_sig), GNUNET_PQ_result_spec_auto_from_type ("coin_blind", @@ -6402,8 +6407,6 @@ recoup_serial_helper_cb (void *cls, &h_blind_ev), GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &coin.denom_pub_hash), - GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", - &denom_pub.rsa_public_key), GNUNET_PQ_result_spec_rsa_signature ("denom_sig", &coin.denom_sig.rsa_signature), TALER_PQ_RESULT_SPEC_AMOUNT ("amount", @@ -6532,6 +6535,7 @@ recoup_refresh_serial_helper_cb (void *cls, struct TALER_CoinSpendSignatureP coin_sig; struct TALER_DenominationBlindingKeyP coin_blind; struct TALER_DenominationPublicKey denom_pub; + struct GNUNET_HashCode old_denom_pub_hash; struct TALER_Amount amount; struct GNUNET_HashCode h_blind_ev; struct GNUNET_TIME_Absolute timestamp; @@ -6542,18 +6546,20 @@ recoup_refresh_serial_helper_cb (void *cls, ×tamp), GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", &old_coin_pub), + GNUNET_PQ_result_spec_auto_from_type ("old_denom_pub_hash", + &old_denom_pub_hash), GNUNET_PQ_result_spec_auto_from_type ("coin_pub", &coin.coin_pub), GNUNET_PQ_result_spec_auto_from_type ("coin_sig", &coin_sig), GNUNET_PQ_result_spec_auto_from_type ("coin_blind", &coin_blind), + GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", + &denom_pub.rsa_public_key), GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", &h_blind_ev), GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &coin.denom_pub_hash), - GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", - &denom_pub.rsa_public_key), GNUNET_PQ_result_spec_rsa_signature ("denom_sig", &coin.denom_sig.rsa_signature), TALER_PQ_RESULT_SPEC_AMOUNT ("amount", @@ -6576,6 +6582,7 @@ recoup_refresh_serial_helper_cb (void *cls, timestamp, &amount, &old_coin_pub, + &old_denom_pub_hash, &coin, &denom_pub, &coin_sig, diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index e9b47942a..96fbe3dc2 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -1317,6 +1317,7 @@ drop: * @param amount how much should be added back to the reserve * @param reserve_pub public key of the reserve * @param coin public information about the coin + * @param denom_pub denomination key of @a coin * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_RECOUP * @param coin_blind blinding factor used to blind the coin * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index f81c28bbb..c19428b18 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -1346,6 +1346,7 @@ typedef int * @param amount how much should be added back to the reserve * @param reserve_pub public key of the reserve * @param coin public information about the coin + * @param denom_pub denomination key of @a coin * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_RECOUP * @param coin_blind blinding factor used to blind the coin * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop @@ -1372,7 +1373,9 @@ typedef int * @param timestamp when did we receive the recoup request * @param amount how much should be added back to the reserve * @param old_coin_pub original coin that was refreshed to create @a coin + * @param old_denom_pub_hash hash of public key of @a old_coin_pub * @param coin public information about the coin + * @param denom_pub denomination key of @a coin * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_RECOUP * @param coin_blind blinding factor used to blind the coin * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop @@ -1384,6 +1387,7 @@ typedef int struct GNUNET_TIME_Absolute timestamp, const struct TALER_Amount *amount, const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + const struct GNUNET_HashCode *old_denom_pub_hash, const struct TALER_CoinPublicInfo *coin, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, -- cgit v1.2.3