commit ace816572e8ae465b168db9214c2c7f895f76b88
parent d068ebf661c0cf02cde2107dd5344318d7c8f18d
Author: Özgür Kesim <oec@codeblau.de>
Date: Mon, 31 Mar 2025 18:03:02 +0200
[auditor] wip: adapt auditor to use and check new withdraw table
Diffstat:
6 files changed, 251 insertions(+), 79 deletions(-)
diff --git a/src/auditor/report-lib.c b/src/auditor/report-lib.c
@@ -77,6 +77,26 @@ struct GNUNET_TIME_Absolute start_time;
*/
static struct GNUNET_CONTAINER_MultiHashMap *denominations;
+/**
+ * Results about denominations, cached per-transaction, maps row/serial ID's
+ * to `const struct TALER_EXCHANGEDB_DenominationKeyInformation`.
+ */
+static struct GNUNET_CONTAINER_MultiUuidmap *denominations_by_serial;
+
+/**
+ * Helper to convert a serial/row id to a uuid for the lookup
+ * in a uuid hash table
+ */
+static struct GNUNET_Uuid
+serial_to_uuid (
+ uint64_t serial)
+{
+ struct GNUNET_Uuid uuid;
+ uuid.value[0] = serial;
+ uuid.value[1] = serial >> 32;
+ return uuid;
+}
+
/**
* Function called with the results of iterate_denomination_info(),
@@ -84,12 +104,14 @@ static struct GNUNET_CONTAINER_MultiHashMap *denominations;
* to our hash table.
*
* @param cls closure, NULL
+ * @param denom_serial table row of the denomaination
* @param denom_pub public key, sometimes NULL (!)
* @param issue issuing information with value, fees and other info about the denomination.
*/
static void
add_denomination (
void *cls,
+ uint64_t denom_serial,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
{
@@ -118,6 +140,7 @@ add_denomination (
#endif
{
struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
+ struct GNUNET_Uuid uuid;
i = GNUNET_new (struct TALER_EXCHANGEDB_DenominationKeyInformation);
*i = *issue;
@@ -126,6 +149,12 @@ add_denomination (
&issue->denom_hash.hash,
i,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ uuid = serial_to_uuid (denom_serial);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multiuuidmap_put (denominations_by_serial,
+ &uuid,
+ i,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
}
}
@@ -141,6 +170,10 @@ TALER_ARL_get_denomination_info_by_hash (
{
denominations = GNUNET_CONTAINER_multihashmap_create (256,
GNUNET_NO);
+ if (NULL == denominations_by_serial)
+ denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256,
+ GNUNET_NO);
+
qs = TALER_ARL_edb->iterate_denomination_info (TALER_ARL_edb->cls,
&add_denomination,
NULL);
@@ -166,9 +199,11 @@ TALER_ARL_get_denomination_info_by_hash (
/* maybe database changed since we last iterated, give it one more shot */
{
struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
+ uint64_t denom_serial;
qs = TALER_ARL_edb->get_denomination_info (TALER_ARL_edb->cls,
dh,
+ &denom_serial,
&issue);
if (qs <= 0)
{
@@ -179,7 +214,9 @@ TALER_ARL_get_denomination_info_by_hash (
TALER_B2S (dh));
return qs;
}
+
add_denomination (NULL,
+ denom_serial,
NULL,
&issue);
}
@@ -204,6 +241,87 @@ TALER_ARL_get_denomination_info_by_hash (
enum GNUNET_DB_QueryStatus
+TALER_ARL_get_denomination_info_by_serial (
+ uint64_t denom_serial,
+ const struct TALER_EXCHANGEDB_DenominationKeyInformation **issuep)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_Uuid uuid = serial_to_uuid (denom_serial);
+
+ if (NULL == denominations_by_serial)
+ {
+ denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256,
+ GNUNET_NO);
+ if (NULL == denominations)
+ denominations = GNUNET_CONTAINER_multihashmap_create (256,
+ GNUNET_NO);
+
+ qs = TALER_ARL_edb->iterate_denomination_info (TALER_ARL_edb->cls,
+ &add_denomination,
+ NULL);
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ *issuep = NULL;
+ return qs;
+ }
+ }
+ {
+ const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
+
+ i = GNUNET_CONTAINER_multiuuidmap_get (denominations_by_serial,
+ &uuid);
+ if (NULL != i)
+ {
+ /* cache hit */
+ *issuep = i;
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+ }
+ /* maybe database changed since we last iterated, give it one more shot */
+ {
+ struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
+
+ qs = TALER_ARL_edb->get_denomination_by_serial (TALER_ARL_edb->cls,
+ denom_serial,
+ &issue);
+ if (qs <= 0)
+ {
+ GNUNET_break (qs >= 0);
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Denomination with serial %lu not found\n",
+ denom_serial);
+ return qs;
+ }
+
+ add_denomination (NULL,
+ denom_serial,
+ NULL,
+ &issue);
+ }
+
+ {
+ const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
+
+ i = GNUNET_CONTAINER_multiuuidmap_get (denominations_by_serial,
+ &uuid);
+ if (NULL != i)
+ {
+ /* cache hit */
+ *issuep = i;
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+ }
+ /* We found more keys, but not the denomination we are looking for :-( */
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Denomination with serial %lu not found\n",
+ denom_serial);
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+}
+
+
+enum GNUNET_DB_QueryStatus
TALER_ARL_get_denomination_info (
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_EXCHANGEDB_DenominationKeyInformation **issue,
diff --git a/src/auditor/report-lib.h b/src/auditor/report-lib.h
@@ -144,6 +144,18 @@ TALER_ARL_get_denomination_info_by_hash (
const struct TALER_DenominationHashP *dh,
const struct TALER_EXCHANGEDB_DenominationKeyInformation **issuep);
+/**
+ * Obtain information about a @a denomination by its serial
+ *
+ * @param serial row id of the denomination to look up
+ * @param[out] issuep set to detailed information about @a denom_pub, NULL if not found, must
+ * NOT be freed by caller
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TALER_ARL_get_denomination_info_by_serial (
+ uint64_t serial,
+ const struct TALER_EXCHANGEDB_DenominationKeyInformation **issuep);
/**
* Obtain information about a @a denom_pub.
diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c
@@ -965,7 +965,7 @@ cleanup_denomination (void *cls,
* we now have additional coins that have been issued.
*
* Note that the signature was already checked in
- * taler-helper-auditor-reserves.c::#handle_reserve_out(), so we do not check
+ * taler-helper-auditor-reserves.c::#handle_withdrawals(), so we do not check
* it again here.
*
* @param cls our `struct CoinContext`
diff --git a/src/auditor/taler-helper-auditor-reserves.c b/src/auditor/taler-helper-auditor-reserves.c
@@ -58,7 +58,7 @@ static struct GNUNET_TIME_Relative idle_reserve_expiration_time;
* Checkpointing our progress for reserves.
*/
static TALER_ARL_DEF_PP (reserves_reserve_in_serial_id);
-static TALER_ARL_DEF_PP (reserves_reserve_out_serial_id);
+static TALER_ARL_DEF_PP (reserves_withdraw_serial_id);
static TALER_ARL_DEF_PP (reserves_reserve_recoup_serial_id);
static TALER_ARL_DEF_PP (reserves_reserve_open_serial_id);
static TALER_ARL_DEF_PP (reserves_reserve_close_serial_id);
@@ -255,7 +255,7 @@ struct ReserveSummary
/**
* Sum of all outgoing transfers during this transaction (includes fees).
- * Updated only in #handle_reserve_out().
+ * Updated only in #handle_withdrawals().
*/
struct TALER_Amount total_out;
@@ -513,8 +513,13 @@ handle_reserve_in (
* @param cls our `struct ReserveContext`
* @param rowid unique serial ID for the refresh session in our DB
* @param num_evs number of elements in @e h_blind_evs
- * @param h_blind_evs array @e num_evs of blinded hash of the coin's public keys
- * @param denom_pub public denomination key of the deposited coin
+ * @param h_blind_evs array @e num_evs of blinded hashes of the coin's public keys
+ * @param denom_serials array @e num_evs of serial ID's of denominations in our DB
+ * @param h_commitment hash of the commitment of the withdraw
+ * @param h_planchets running hash over all hashes of blinded planchets in the original withdraw request
+ * @param age_proof_required true if the withdraw request required an age proof.
+ * @param max_age if @e age_proof_required is true, the maximum age that was set on the coins.
+ * @param noreveal_index if @e age_proof_required is true, the index that was returned by the exchange for the reveal phase.
* @param reserve_pub public key of the reserve
* @param reserve_sig signature over the withdraw operation
* @param execution_date when did the wallet withdraw the coin
@@ -522,12 +527,17 @@ handle_reserve_in (
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
static enum GNUNET_GenericReturnValue
-handle_reserve_out (
+handle_withdrawals (
void *cls,
uint64_t rowid,
size_t num_evs,
const struct TALER_BlindedCoinHashP *h_blind_evs,
- const struct TALER_DenominationPublicKey *denom_pub,
+ const uint64_t *denom_serials,
+ const struct TALER_WithdrawCommitmentHashP *h_commitment,
+ const struct TALER_HashBlindedPlanchetsP *h_planchets,
+ bool age_proof_required,
+ uint8_t max_age,
+ uint8_t noreveal_index,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_ReserveSignatureP *reserve_sig,
struct GNUNET_TIME_Timestamp execution_date,
@@ -536,80 +546,115 @@ handle_reserve_out (
struct ReserveContext *rc = cls;
struct ReserveSummary *rs;
const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue;
+ struct TALER_Amount auditor_amount;
+ struct TALER_Amount auditor_fee;
struct TALER_Amount auditor_amount_with_fee;
enum GNUNET_DB_QueryStatus qs;
- struct TALER_DenominationHashP h_denom_pub;
/* should be monotonically increasing */
- GNUNET_assert (rowid >= TALER_ARL_USE_PP (reserves_reserve_out_serial_id));
- TALER_ARL_USE_PP (reserves_reserve_out_serial_id) = rowid + 1;
-
- /* lookup denomination pub data (make sure denom_pub is valid, establish fees);
- initializes wsrd.h_denomination_pub! */
- qs = TALER_ARL_get_denomination_info (denom_pub,
- &issue,
- &h_denom_pub);
- if (0 > qs)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Hard database error trying to get denomination %s (%s) from database!\n",
- TALER_B2S (denom_pub),
- TALER_amount2s (amount_with_fee));
- rc->qs = qs;
- return GNUNET_SYSERR;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- report_row_inconsistency ("withdraw",
- rowid,
- "denomination key not found");
- if (global_qs < 0)
- return GNUNET_SYSERR;
- return GNUNET_OK;
- }
-
- /* check that execution date is within withdraw range for denom_pub */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Checking withdraw timing: %llu, expire: %llu, timing: %llu\n",
- (unsigned long long) issue->start.abs_time.abs_value_us,
- (unsigned long long) issue->expire_withdraw.abs_time.abs_value_us,
- (unsigned long long) execution_date.abs_time.abs_value_us);
- if (GNUNET_TIME_timestamp_cmp (issue->start,
- >,
- execution_date) ||
- GNUNET_TIME_timestamp_cmp (issue->expire_withdraw,
- <,
- execution_date))
- {
- struct TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistency dkvwi ={
- .problem_row_id = rowid,
- .execution_date = execution_date.abs_time,
- .denompub_h = *&h_denom_pub,
- .reserve_pub = *reserve_pub
- };
+ GNUNET_assert (rowid >= TALER_ARL_USE_PP (reserves_withdraw_serial_id));
+ TALER_ARL_USE_PP (reserves_withdraw_serial_id) = rowid + 1;
- qs =
- TALER_ARL_adb->insert_denomination_key_validity_withdraw_inconsistency (
- TALER_ARL_adb->cls,
- &dkvwi);
+ GNUNET_assert (GNUNET_OK == TALER_amount_set_zero (TALER_ARL_currency,
+ &auditor_amount));
+ GNUNET_assert (GNUNET_OK == TALER_amount_set_zero (TALER_ARL_currency,
+ &auditor_fee));
+ GNUNET_assert (GNUNET_OK == TALER_amount_set_zero (TALER_ARL_currency,
+ &auditor_amount_with_fee));
- if (qs < 0)
+ for (size_t i = 0; i < num_evs; i++)
+ {
+ /* lookup denomination pub data (make sure denom_pub is valid, establish fees);
+ initializes wsrd.h_denomination_pub! */
+ qs = TALER_ARL_get_denomination_info_by_serial (denom_serials[i],
+ &issue);
+ if (0 > qs)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Hard database error trying to get denomination by serial %lu (%s) from database!\n",
+ denom_serials[i],
+ GNUNET_h2s (&h_commitment->hash));
rc->qs = qs;
return GNUNET_SYSERR;
}
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ report_row_inconsistency ("withdraw",
+ rowid,
+ "denomination key not found");
+ if (global_qs < 0)
+ return GNUNET_SYSERR;
+ return GNUNET_OK;
+ }
+
+ /* check that execution date is within withdraw range for denom_pub */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking withdraw timing: %llu, expire: %llu, timing: %llu\n",
+ (unsigned long long) issue->start.abs_time.abs_value_us,
+ (unsigned long
+ long) issue->expire_withdraw.abs_time.abs_value_us,
+ (unsigned long long) execution_date.abs_time.abs_value_us);
+ if (GNUNET_TIME_timestamp_cmp (issue->start,
+ >,
+ execution_date) ||
+ GNUNET_TIME_timestamp_cmp (issue->expire_withdraw,
+ <,
+ execution_date))
+ {
+ struct TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistency
+ dkvwi ={
+ .problem_row_id = rowid,
+ .execution_date = execution_date.abs_time,
+ .denompub_h = issue->denom_hash,
+ .reserve_pub = *reserve_pub
+ };
+
+ qs =
+ TALER_ARL_adb->insert_denomination_key_validity_withdraw_inconsistency (
+ TALER_ARL_adb->cls,
+ &dkvwi);
+
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ rc->qs = qs;
+ return GNUNET_SYSERR;
+ }
+ }
+ TALER_ARL_amount_add (&auditor_amount,
+ &auditor_amount,
+ &issue->value);
+ TALER_ARL_amount_add (&auditor_fee,
+ &auditor_fee,
+ &issue->fees.withdraw);
+ {
+ struct TALER_Amount amount_with_fee;
+
+ TALER_ARL_amount_add (&amount_with_fee,
+ &issue->value,
+ &issue->fees.withdraw);
+ TALER_ARL_amount_add (&auditor_amount_with_fee,
+ &auditor_amount_with_fee,
+ &amount_with_fee);
+ }
}
/* check reserve_sig (first: setup remaining members of wsrd) */
if (GNUNET_OK !=
- TALER_wallet_withdraw_verify_pre26 (&h_denom_pub,
- amount_with_fee,
- &h_blind_evs[0],
- reserve_pub,
- reserve_sig))
+ TALER_wallet_withdraw_verify (
+ &auditor_amount,
+ &auditor_fee,
+ h_planchets,
+ age_proof_required
+ ? &issue->age_mask
+ : NULL,
+ age_proof_required
+ ? max_age
+ : 0,
+ reserve_pub,
+ reserve_sig))
{
struct TALER_AUDITORDB_BadSigLosses bsl = {
.problem_row_id = rowid,
@@ -634,9 +679,6 @@ handle_reserve_out (
return GNUNET_OK; /* exit function here, we cannot add this to the legitimate withdrawals */
}
- TALER_ARL_amount_add (&auditor_amount_with_fee,
- &issue->value,
- &issue->fees.withdraw);
if (0 !=
TALER_amount_cmp (&auditor_amount_with_fee,
amount_with_fee))
@@ -1754,7 +1796,7 @@ analyze_reserves (void *cls)
qs = TALER_ARL_adb->get_auditor_progress (
TALER_ARL_adb->cls,
TALER_ARL_GET_PP (reserves_reserve_in_serial_id),
- TALER_ARL_GET_PP (reserves_reserve_out_serial_id),
+ TALER_ARL_GET_PP (reserves_withdraw_serial_id),
TALER_ARL_GET_PP (reserves_reserve_recoup_serial_id),
TALER_ARL_GET_PP (reserves_reserve_open_serial_id),
TALER_ARL_GET_PP (reserves_reserve_close_serial_id),
@@ -1779,7 +1821,7 @@ analyze_reserves (void *cls)
(unsigned long long) TALER_ARL_USE_PP (
reserves_reserve_in_serial_id),
(unsigned long long) TALER_ARL_USE_PP (
- reserves_reserve_out_serial_id),
+ reserves_withdraw_serial_id),
(unsigned long long) TALER_ARL_USE_PP (
reserves_reserve_recoup_serial_id),
(unsigned long long) TALER_ARL_USE_PP (
@@ -1827,8 +1869,8 @@ analyze_reserves (void *cls)
CHECK_DB ();
qs = TALER_ARL_edb->select_withdrawals_above_serial_id (
TALER_ARL_edb->cls,
- TALER_ARL_USE_PP (reserves_reserve_out_serial_id),
- &handle_reserve_out,
+ TALER_ARL_USE_PP (reserves_withdraw_serial_id),
+ &handle_withdrawals,
&rc);
CHECK_DB ();
qs = TALER_ARL_edb->select_recoup_above_serial_id (
@@ -1928,7 +1970,7 @@ analyze_reserves (void *cls)
qs = TALER_ARL_adb->insert_auditor_progress (
TALER_ARL_adb->cls,
TALER_ARL_SET_PP (reserves_reserve_in_serial_id),
- TALER_ARL_SET_PP (reserves_reserve_out_serial_id),
+ TALER_ARL_SET_PP (reserves_withdraw_serial_id),
TALER_ARL_SET_PP (reserves_reserve_recoup_serial_id),
TALER_ARL_SET_PP (reserves_reserve_open_serial_id),
TALER_ARL_SET_PP (reserves_reserve_close_serial_id),
@@ -1946,7 +1988,7 @@ analyze_reserves (void *cls)
qs = TALER_ARL_adb->update_auditor_progress (
TALER_ARL_adb->cls,
TALER_ARL_SET_PP (reserves_reserve_in_serial_id),
- TALER_ARL_SET_PP (reserves_reserve_out_serial_id),
+ TALER_ARL_SET_PP (reserves_withdraw_serial_id),
TALER_ARL_SET_PP (reserves_reserve_recoup_serial_id),
TALER_ARL_SET_PP (reserves_reserve_open_serial_id),
TALER_ARL_SET_PP (reserves_reserve_close_serial_id),
@@ -1967,7 +2009,7 @@ analyze_reserves (void *cls)
(unsigned long long) TALER_ARL_USE_PP (
reserves_reserve_in_serial_id),
(unsigned long long) TALER_ARL_USE_PP (
- reserves_reserve_out_serial_id),
+ reserves_withdraw_serial_id),
(unsigned long long) TALER_ARL_USE_PP (
reserves_reserve_recoup_serial_id),
(unsigned long long) TALER_ARL_USE_PP (
diff --git a/src/auditor/taler-helper-auditor-transfer.c b/src/auditor/taler-helper-auditor-transfer.c
@@ -156,7 +156,7 @@ import_wire_missing_cb (
wire_target_h_payto,
total_amount,
deadline);
- if (0 < qs)
+ if (0 > qs)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
wc->err = qs;
diff --git a/src/auditor/test-auditor.sh b/src/auditor/test-auditor.sh
@@ -462,10 +462,10 @@ 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 -n "CD... "
+ 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 -n "CD... "
+ echo "endpoint ${1} called... "
fi
}