-add dB logic for auditor iteration over purse deposits

This commit is contained in:
Christian Grothoff 2022-06-12 17:23:31 +02:00
parent e71782ea77
commit 393ae7f9a3
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
3 changed files with 311 additions and 7 deletions

View File

@ -2215,6 +2215,30 @@ check_denomination (
} }
/**
* Function called with details about purse deposits that have been made, with
* the goal of auditing the deposit's execution.
*
* @param cls closure
* @param rowid unique serial ID for the deposit in our DB
* @param deposit deposit details
* @param denom_pub denomination public key of @a coin_pub
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
static enum GNUNET_GenericReturnValue
purse_deposit_cb (
void *cls,
uint64_t rowid,
const struct TALER_EXCHANGEDB_PurseDeposit *deposit,
const struct TALER_DenominationPublicKey *denom_pub)
{
struct CoinContext *cc = cls;
GNUNET_break (0); // FIXME: not implemented!
return GNUNET_SYSERR;
}
/** /**
* Analyze the exchange's processing of coins. * Analyze the exchange's processing of coins.
* *
@ -2259,12 +2283,13 @@ analyze_coins (void *cls)
{ {
ppc_start = ppc; ppc_start = ppc;
GNUNET_log (GNUNET_ERROR_TYPE_INFO, 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/%llu\n",
(unsigned long long) ppc.last_deposit_serial_id, (unsigned long long) ppc.last_deposit_serial_id,
(unsigned long long) ppc.last_melt_serial_id, (unsigned long long) ppc.last_melt_serial_id,
(unsigned long long) ppc.last_refund_serial_id, (unsigned long long) ppc.last_refund_serial_id,
(unsigned long long) ppc.last_withdraw_serial_id, (unsigned long long) ppc.last_withdraw_serial_id,
(unsigned long long) ppc.last_recoup_refresh_serial_id); (unsigned long long) ppc.last_recoup_refresh_serial_id,
(unsigned long long) ppc.last_purse_deposits_serial_id);
} }
/* setup 'cc' */ /* setup 'cc' */
@ -2368,6 +2393,20 @@ analyze_coins (void *cls)
if (0 > cc.qs) if (0 > cc.qs)
return cc.qs; return cc.qs;
/* process purse_deposits */
if (0 >
(qs = TALER_ARL_edb->select_purse_deposits_above_serial_id (
TALER_ARL_edb->cls,
ppc.last_purse_deposits_serial_id,
&purse_deposit_cb,
&cc)))
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
return qs;
}
if (0 > cc.qs)
return cc.qs;
/* sync 'cc' back to disk */ /* sync 'cc' back to disk */
cc.qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; cc.qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
GNUNET_CONTAINER_multihashmap_iterate (cc.denom_summaries, GNUNET_CONTAINER_multihashmap_iterate (cc.denom_summaries,
@ -2421,12 +2460,13 @@ analyze_coins (void *cls)
return qs; return qs;
} }
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Concluded coin audit step at %llu/%llu/%llu/%llu/%llu\n", "Concluded coin audit step at %llu/%llu/%llu/%llu/%llu/%llu\n",
(unsigned long long) ppc.last_deposit_serial_id, (unsigned long long) ppc.last_deposit_serial_id,
(unsigned long long) ppc.last_melt_serial_id, (unsigned long long) ppc.last_melt_serial_id,
(unsigned long long) ppc.last_refund_serial_id, (unsigned long long) ppc.last_refund_serial_id,
(unsigned long long) ppc.last_withdraw_serial_id, (unsigned long long) ppc.last_withdraw_serial_id,
(unsigned long long) ppc.last_recoup_refresh_serial_id); (unsigned long long) ppc.last_recoup_refresh_serial_id,
(unsigned long long) ppc.last_purse_deposits_serial_id);
return qs; return qs;
} }

View File

@ -1482,10 +1482,32 @@ prepare_statements (struct PostgresClosure *pg)
" JOIN known_coins kc USING (coin_pub)" " JOIN known_coins kc USING (coin_pub)"
" JOIN denominations denom USING (denominations_serial)" " JOIN denominations denom USING (denominations_serial)"
" WHERE (" " WHERE ("
" (deposit_serial_id>=$1)" // FIXME: also select by shard!? " (deposit_serial_id>=$1)"
" )" " )"
" ORDER BY deposit_serial_id ASC;", " ORDER BY deposit_serial_id ASC;",
1), 1),
/* Fetch purse deposits with rowid '\geq' the given parameter */
GNUNET_PQ_make_prepare (
"audit_get_purse_deposits_incr",
"SELECT"
" amount_with_fee_val"
",amount_with_fee_frac"
",purse_pub"
",coin_sig"
",partner_base_url"
",denom.denom_pub"
",kc.coin_pub"
",kc.age_commitment_hash"
",purse_deposit_serial_id"
" FROM purse_deposits"
" LEFT JOIN partners USING (partner_serial_id)"
" JOIN known_coins kc USING (coin_pub)"
" JOIN denominations denom USING (denominations_serial)"
" WHERE ("
" (purse_deposit_serial_id>=$1)"
" )"
" ORDER BY purse_deposit_serial_id ASC;",
1),
/* Fetch an existing deposit request. /* Fetch an existing deposit request.
Used in #postgres_lookup_transfer_by_deposit(). */ Used in #postgres_lookup_transfer_by_deposit(). */
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
@ -10131,7 +10153,7 @@ struct DepositSerialContext
/** /**
* Status code, set to #GNUNET_SYSERR on hard errors. * Status code, set to #GNUNET_SYSERR on hard errors.
*/ */
int status; enum GNUNET_GenericReturnValue status;
}; };
@ -10193,7 +10215,7 @@ deposit_serial_helper_cb (void *cls,
&rowid), &rowid),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end
}; };
int ret; enum GNUNET_GenericReturnValue ret;
memset (&deposit, memset (&deposit,
0, 0,
@ -10261,6 +10283,148 @@ postgres_select_deposits_above_serial_id (
} }
/**
* Closure for #purse_deposit_serial_helper_cb().
*/
struct PurseDepositSerialContext
{
/**
* Callback to call.
*/
TALER_EXCHANGEDB_PurseDepositCallback cb;
/**
* Closure for @e cb.
*/
void *cb_cls;
/**
* Plugin context.
*/
struct PostgresClosure *pg;
/**
* Status code, set to #GNUNET_SYSERR on hard errors.
*/
enum GNUNET_GenericReturnValue status;
};
/**
* Helper function to be called with the results of a SELECT statement
* that has returned @a num_results results.
*
* @param cls closure of type `struct DepositSerialContext`
* @param result the postgres result
* @param num_results the number of results in @a result
*/
static void
purse_deposit_serial_helper_cb (void *cls,
PGresult *result,
unsigned int num_results)
{
struct PurseDepositSerialContext *dsc = cls;
struct PostgresClosure *pg = dsc->pg;
for (unsigned int i = 0; i<num_results; i++)
{
struct TALER_EXCHANGEDB_PurseDeposit deposit = {
.exchange_base_url = NULL
};
struct TALER_DenominationPublicKey denom_pub;
uint64_t rowid;
struct GNUNET_PQ_ResultSpec rs[] = {
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
&deposit.amount),
TALER_PQ_RESULT_SPEC_AMOUNT ("deposit_fee",
&deposit.deposit_fee),
GNUNET_PQ_result_spec_allow_null (
GNUNET_PQ_result_spec_string ("partner_base_url",
&deposit.exchange_base_url),
NULL),
TALER_PQ_result_spec_denom_pub ("denom_pub",
&denom_pub),
GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
&deposit.purse_pub),
GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
&deposit.coin_sig),
GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
&deposit.coin_pub),
GNUNET_PQ_result_spec_allow_null (
GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
&deposit.h_age_commitment),
&deposit.no_age_commitment),
GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
&rowid),
GNUNET_PQ_result_spec_end
};
enum GNUNET_GenericReturnValue ret;
memset (&deposit,
0,
sizeof (deposit));
if (GNUNET_OK !=
GNUNET_PQ_extract_result (result,
rs,
i))
{
GNUNET_break (0);
dsc->status = GNUNET_SYSERR;
return;
}
ret = dsc->cb (dsc->cb_cls,
rowid,
&deposit,
&denom_pub);
GNUNET_PQ_cleanup_result (rs);
if (GNUNET_OK != ret)
break;
}
}
/**
* Select deposits above @a serial_id in monotonically increasing
* order.
*
* @param cls closure
* @param serial_id highest serial ID to exclude (select strictly larger)
* @param cb function to call on each result
* @param cb_cls closure for @a cb
* @return transaction status code
*/
static enum GNUNET_DB_QueryStatus
postgres_select_purse_deposits_above_serial_id (
void *cls,
uint64_t serial_id,
TALER_EXCHANGEDB_PurseDepositCallback cb,
void *cb_cls)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_uint64 (&serial_id),
GNUNET_PQ_query_param_end
};
struct PurseDepositSerialContext dsc = {
.cb = cb,
.cb_cls = cb_cls,
.pg = pg,
.status = GNUNET_OK
};
enum GNUNET_DB_QueryStatus qs;
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
"audit_get_purse_deposits_incr",
params,
&purse_deposit_serial_helper_cb,
&dsc);
if (GNUNET_OK != dsc.status)
return GNUNET_DB_STATUS_HARD_ERROR;
return qs;
}
/** /**
* Closure for #refreshs_serial_helper_cb(). * Closure for #refreshs_serial_helper_cb().
*/ */
@ -14936,6 +15100,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
plugin->gc = &postgres_gc; plugin->gc = &postgres_gc;
plugin->select_deposits_above_serial_id plugin->select_deposits_above_serial_id
= &postgres_select_deposits_above_serial_id; = &postgres_select_deposits_above_serial_id;
plugin->select_purse_deposits_above_serial_id
= &postgres_select_purse_deposits_above_serial_id;
plugin->select_refreshes_above_serial_id plugin->select_refreshes_above_serial_id
= &postgres_select_refreshes_above_serial_id; = &postgres_select_refreshes_above_serial_id;
plugin->select_refunds_above_serial_id plugin->select_refunds_above_serial_id

View File

@ -1680,6 +1680,16 @@ struct TALER_EXCHANGEDB_PurseDepositListEntry
*/ */
struct TALER_CoinSpendSignatureP coin_sig; struct TALER_CoinSpendSignatureP coin_sig;
/**
* FIXME-Oec: probably needed here, not yet used
* anywhere!
*
* Hash of the age commitment used to sign the coin, if age restriction was
* applicable to the denomination. May be all zeroes if no age restriction
* applies.
*/
struct TALER_AgeCommitmentHash h_age_commitment_FIXME;
/** /**
* Set to true if the coin was refunded. * Set to true if the coin was refunded.
*/ */
@ -1687,6 +1697,58 @@ struct TALER_EXCHANGEDB_PurseDepositListEntry
}; };
/**
* Information about a /purses/$PID/deposit operation.
*/
struct TALER_EXCHANGEDB_PurseDeposit
{
/**
* Exchange hosting the purse, NULL for this exchange.
*/
char *exchange_base_url;
/**
* Public key of the purse.
*/
struct TALER_PurseContractPublicKeyP purse_pub;
/**
* Contribution of the coin to the purse, including
* deposit fee.
*/
struct TALER_Amount amount;
/**
* Depositing fee.
*/
struct TALER_Amount deposit_fee;
/**
* Signature by the coin affirming the deposit.
*/
struct TALER_CoinSpendSignatureP coin_sig;
/**
* Public key of the coin.
*/
struct TALER_CoinSpendPublicKeyP coin_pub;
/**
* Hash of the age commitment used to sign the coin, if age restriction was
* applicable to the denomination. May be all zeroes if no age restriction
* applies.
*/
struct TALER_AgeCommitmentHash h_age_commitment;
/**
* Set to true if @e h_age_commitment is not available.
*/
bool no_age_commitment;
};
/** /**
* Information about a melt operation. * Information about a melt operation.
*/ */
@ -1915,6 +1977,24 @@ typedef enum GNUNET_GenericReturnValue
bool done); bool done);
/**
* Function called with details about purse deposits that have been made, with
* the goal of auditing the deposit's execution.
*
* @param cls closure
* @param rowid unique serial ID for the deposit in our DB
* @param deposit deposit details
* @param denom_pub denomination public key of @a coin_pub
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
typedef enum GNUNET_GenericReturnValue
(*TALER_EXCHANGEDB_PurseDepositCallback)(
void *cls,
uint64_t rowid,
const struct TALER_EXCHANGEDB_PurseDeposit *deposit,
const struct TALER_DenominationPublicKey *denom_pub);
/** /**
* Function called with details about coins that were melted, * Function called with details about coins that were melted,
* with the goal of auditing the refresh's execution. * with the goal of auditing the refresh's execution.
@ -3960,6 +4040,24 @@ struct TALER_EXCHANGEDB_Plugin
TALER_EXCHANGEDB_DepositCallback cb, TALER_EXCHANGEDB_DepositCallback cb,
void *cb_cls); void *cb_cls);
/**
* Select purse deposits above @a serial_id in monotonically increasing
* order.
*
* @param cls closure
* @param serial_id highest serial ID to exclude (select strictly larger)
* @param cb function to call on each result
* @param cb_cls closure for @a cb
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
(*select_purse_deposits_above_serial_id)(
void *cls,
uint64_t serial_id,
TALER_EXCHANGEDB_PurseDepositCallback cb,
void *cb_cls);
/** /**
* Select refresh sessions above @a serial_id in monotonically increasing * Select refresh sessions above @a serial_id in monotonically increasing
* order. * order.