add auditing of deposit confirmations to auditor (#5447)
This commit is contained in:
parent
332341cb7b
commit
ac850bfcd2
@ -148,6 +148,61 @@ the tiny threshold. Below, we report {\em non-tiny} wire transfers that are lagg
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
\section{Deposit confirmation lag}
|
||||
|
||||
This section analyzes the lag, which is by how much the exchange's
|
||||
database reporting is behind in providing us with information about
|
||||
deposit confirmations. Merchants probabilisitcally report deposit
|
||||
confirmations to the auditor directly, so if the exchange is slow at
|
||||
synchronizing its database with the auditor, some deposit
|
||||
confirmations may be known at the auditor only directly. However, any
|
||||
delta not accounted for by database synchronization delays is an
|
||||
indicator of a malicious exchange (or online singing key compromise)
|
||||
and should be answered by revoking the exchange's online siging keys.
|
||||
% FIXME: reference PhD thesis?
|
||||
|
||||
The total amount the exchange currently lags behind is
|
||||
{\bf {{ data.missing_deposit_confirmation_total.value }}.{{ data.missing_deposit_confirmation_total.fraction }}
|
||||
{{ data.missing_deposit_confirmation_total.currency }}} or
|
||||
{\bf {{ data.total_missed_deposit_confirmations}} } deposit confirmations.
|
||||
|
||||
Note that some lag is perfectly normal.
|
||||
Below, we report {\em all} deposit confirmations that are lagging behind.
|
||||
|
||||
{% if data.deposit_confirmation_inconsistencies|length() == 0 %}
|
||||
{\bf No deposit confirmations that are lagging behind detected.}
|
||||
{% else %}
|
||||
\begin{longtable}{p{1.5cm}|rl|c|rl}
|
||||
{\bf Timestamp} & {\bf Amount} & {\bf Row} \\
|
||||
\multicolumn{3}{l}{\bf Target account} \\ \hline \hline
|
||||
\endfirsthead
|
||||
{\bf Timestamp} & {\bf Amount} & {\bf Row} \\
|
||||
\multicolumn{3}{l}{\bf Target account} \\ \hline \hline
|
||||
\endhead
|
||||
\hline \hline
|
||||
{\bf Timestamp} & {\bf Amount} & {\bf Row} \\
|
||||
\multicolumn{3}{l}{\bf Target account} \\
|
||||
\endfoot
|
||||
\hline \hline
|
||||
{\bf Timestamp} & {\bf Amount} & {\bf Row} \\
|
||||
\multicolumn{3}{l}{\bf Target account} \\
|
||||
\caption{Missing deposit confirmations.}
|
||||
\label{table:missing_dc}
|
||||
\endlastfoot
|
||||
{% for item in data.deposit_confirmation_inconsistencies %}
|
||||
&
|
||||
{{ item.timestamp }} &
|
||||
{{ item.amount.value }}.{{ item.amount.fraction }} &
|
||||
{{ item.amount.currency }} &
|
||||
{{ item.row }} \\
|
||||
\nopagebreak
|
||||
\multicolumn{3}{l}{ {\tt {{ item.account }} } } \\ \hline
|
||||
{% endfor %}
|
||||
\end{longtable}
|
||||
{% endif %}
|
||||
|
||||
|
||||
\section{Major irregularities}
|
||||
|
||||
This section describes the possible major irregularities that the
|
||||
|
@ -182,6 +182,11 @@ static struct TALER_Amount total_balance_reserve_not_closed;
|
||||
*/
|
||||
static json_t *report_wire_out_inconsistencies;
|
||||
|
||||
/**
|
||||
* Array of reports about missing deposit confirmations.
|
||||
*/
|
||||
static json_t *report_deposit_confirmation_inconsistencies;
|
||||
|
||||
/**
|
||||
* Total delta between calculated and stored wire out transfers,
|
||||
* for positive deltas.
|
||||
@ -235,6 +240,16 @@ static struct TALER_Amount total_arithmetic_delta_plus;
|
||||
*/
|
||||
static struct TALER_Amount total_arithmetic_delta_minus;
|
||||
|
||||
/**
|
||||
* Total number of deposit confirmations that we did not get.
|
||||
*/
|
||||
static json_int_t number_missed_deposit_confirmations;
|
||||
|
||||
/**
|
||||
* Total amount involved in deposit confirmations that we did not get.
|
||||
*/
|
||||
static struct TALER_Amount total_missed_deposit_confirmations;
|
||||
|
||||
/**
|
||||
* Total amount reported in all calls to #report_emergency().
|
||||
*/
|
||||
@ -4036,6 +4051,202 @@ analyze_coins (void *cls)
|
||||
}
|
||||
|
||||
|
||||
/* *************************** Analysis of deposit-confirmations ********** */
|
||||
|
||||
/**
|
||||
* Closure for #test_dc.
|
||||
*/
|
||||
struct DepositConfirmationContext
|
||||
{
|
||||
|
||||
/**
|
||||
* How many deposit confirmations did we NOT find in the #edb?
|
||||
*/
|
||||
unsigned long long missed_count;
|
||||
|
||||
/**
|
||||
* What is the total amount missing?
|
||||
*/
|
||||
struct TALER_Amount missed_amount;
|
||||
|
||||
/**
|
||||
* Lowest SerialID of the first coin we missed? (This is where we
|
||||
* should resume next time).
|
||||
*/
|
||||
uint64_t first_missed_coin_serial;
|
||||
|
||||
/**
|
||||
* Lowest SerialID of the first coin we missed? (This is where we
|
||||
* should resume next time).
|
||||
*/
|
||||
uint64_t last_seen_coin_serial;
|
||||
|
||||
/**
|
||||
* Success or failure of (exchange) database operations within
|
||||
* #test_dc.
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Given a deposit confirmation from #adb, check that it is also
|
||||
* in #edb. Update the deposit confirmation context accordingly.
|
||||
*
|
||||
* @param cls our `struct DepositConfirmationContext`
|
||||
* @param serial_id row of the @a dc in the database
|
||||
* @param dc the deposit confirmation we know
|
||||
*/
|
||||
static void
|
||||
test_dc (void *cls,
|
||||
uint64_t serial_id,
|
||||
const struct TALER_AUDITORDB_DepositConfirmation *dc)
|
||||
{
|
||||
struct DepositConfirmationContext *dcc = cls;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
struct TALER_EXCHANGEDB_Deposit dep;
|
||||
|
||||
dcc->last_seen_coin_serial = serial_id;
|
||||
memset (&dep,
|
||||
0,
|
||||
sizeof (dep));
|
||||
dep.coin.coin_pub = dc->coin_pub;
|
||||
dep.h_contract_terms = dc->h_contract_terms;
|
||||
dep.merchant_pub = dc->merchant;
|
||||
dep.h_wire = dc->h_wire;
|
||||
dep.refund_deadline = dc->refund_deadline;
|
||||
|
||||
qs = edb->have_deposit (edb->cls,
|
||||
esession,
|
||||
&dep,
|
||||
GNUNET_NO /* do not check refund deadline */);
|
||||
if (qs > 0)
|
||||
return; /* found, all good */
|
||||
if (qs < 0)
|
||||
{
|
||||
GNUNET_break (0); /* DB error, complain */
|
||||
dcc->qs = qs;
|
||||
return;
|
||||
}
|
||||
/* deposit confirmation missing! report! */
|
||||
report (report_deposit_confirmation_inconsistencies,
|
||||
json_pack ("{s:s, s:o, s:I, s:o}",
|
||||
"timestamp",
|
||||
GNUNET_STRINGS_absolute_time_to_string (dc->timestamp),
|
||||
"amount",
|
||||
TALER_JSON_from_amount (&dc->amount_without_fee),
|
||||
"rowid",
|
||||
(json_int_t) serial_id,
|
||||
"account",
|
||||
GNUNET_JSON_from_data_auto (&dc->h_wire)));
|
||||
dcc->first_missed_coin_serial = GNUNET_MIN (dcc->first_missed_coin_serial,
|
||||
serial_id);
|
||||
dcc->missed_count++;
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_add (&dcc->missed_amount,
|
||||
&dcc->missed_amount,
|
||||
&dc->amount_without_fee));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check that the deposit-confirmations that were reported to
|
||||
* us by merchants are also in the exchange's database.
|
||||
*
|
||||
* @param cls closure
|
||||
* @return transaction status code
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
analyze_deposit_confirmations (void *cls)
|
||||
{
|
||||
struct TALER_AUDITORDB_ProgressPointDepositConfirmation ppdc;
|
||||
struct DepositConfirmationContext dcc;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
enum GNUNET_DB_QueryStatus qsx;
|
||||
enum GNUNET_DB_QueryStatus qsp;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Analyzing deposit confirmations\n");
|
||||
ppdc.last_deposit_confirmation_serial_id = 0;
|
||||
qsp = adb->get_auditor_progress_deposit_confirmation (adb->cls,
|
||||
asession,
|
||||
&master_pub,
|
||||
&ppdc);
|
||||
if (0 > qsp)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsp);
|
||||
return qsp;
|
||||
}
|
||||
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qsp)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
_("First analysis using this auditor, starting audit from scratch\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
_("Resuming deposit confirmation audit at %llu\n"),
|
||||
(unsigned long long) ppdc.last_deposit_confirmation_serial_id);
|
||||
}
|
||||
|
||||
/* setup 'cc' */
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_get_zero (currency,
|
||||
&dcc.missed_amount));
|
||||
dcc.qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
||||
dcc.missed_count = 0LLU;
|
||||
dcc.first_missed_coin_serial = UINT64_MAX;
|
||||
qsx = adb->get_deposit_confirmations (adb->cls,
|
||||
asession,
|
||||
&master_pub,
|
||||
ppdc.last_deposit_confirmation_serial_id,
|
||||
&test_dc,
|
||||
&dcc);
|
||||
if (0 > qsx)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsx);
|
||||
return qsx;
|
||||
}
|
||||
if (0 > dcc.qs)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == dcc.qs);
|
||||
return dcc.qs;
|
||||
}
|
||||
if (UINT64_MAX == dcc.first_missed_coin_serial)
|
||||
ppdc.last_deposit_confirmation_serial_id = dcc.last_seen_coin_serial;
|
||||
else
|
||||
ppdc.last_deposit_confirmation_serial_id = dcc.first_missed_coin_serial - 1;
|
||||
|
||||
/* sync 'cc' back to disk */
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qsp)
|
||||
qs = adb->update_auditor_progress_deposit_confirmation (adb->cls,
|
||||
asession,
|
||||
&master_pub,
|
||||
&ppdc);
|
||||
else
|
||||
qs = adb->insert_auditor_progress_deposit_confirmation (adb->cls,
|
||||
asession,
|
||||
&master_pub,
|
||||
&ppdc);
|
||||
if (0 >= qs)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Failed to update auditor DB, not recording progress\n");
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return qs;
|
||||
}
|
||||
number_missed_deposit_confirmations = (json_int_t) dcc.missed_count;
|
||||
total_missed_deposit_confirmations = dcc.missed_amount;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
_("Concluded deposit confirmation audit step at %llu\n"),
|
||||
(unsigned long long) ppdc.last_deposit_confirmation_serial_id);
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *************************** General transaction logic ****************** */
|
||||
|
||||
/**
|
||||
@ -4151,6 +4362,8 @@ setup_sessions_and_run ()
|
||||
NULL);
|
||||
transact (&analyze_coins,
|
||||
NULL);
|
||||
transact (&analyze_deposit_confirmations,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -4347,6 +4560,8 @@ run (void *cls,
|
||||
(report_reserve_not_closed_inconsistencies = json_array ()));
|
||||
GNUNET_assert (NULL !=
|
||||
(report_wire_out_inconsistencies = json_array ()));
|
||||
GNUNET_assert (NULL !=
|
||||
(report_deposit_confirmation_inconsistencies = json_array ()));
|
||||
GNUNET_assert (NULL !=
|
||||
(report_coin_inconsistencies = json_array ()));
|
||||
GNUNET_assert (NULL !=
|
||||
@ -4383,7 +4598,8 @@ run (void *cls,
|
||||
" s:o, s:o, s:o, s:o, s:o,"
|
||||
" s:o, s:o, s:o, s:o, s:o,"
|
||||
" s:o, s:o, s:o, s:o, s:o,"
|
||||
" s:o, s:o, s:o }",
|
||||
" s:o, s:o, s:o, s:o, s:I,"
|
||||
" s:o }",
|
||||
/* blocks of 5 for easier counting/matching to format string */
|
||||
/* block */
|
||||
"reserve_balance_insufficient_inconsistencies",
|
||||
@ -4457,7 +4673,14 @@ run (void *cls,
|
||||
"total_refresh_hanging",
|
||||
TALER_JSON_from_amount (&total_refresh_hanging),
|
||||
"refresh_hanging",
|
||||
report_refreshs_hanging);
|
||||
report_refreshs_hanging,
|
||||
"deposit_confirmation_inconsistencies",
|
||||
report_deposit_confirmation_inconsistencies,
|
||||
"missing_deposit_confirmation_count",
|
||||
(json_int_t) number_missed_deposit_confirmations,
|
||||
/* block */
|
||||
"missing_deposit_confirmation_total",
|
||||
TALER_JSON_from_amount (&total_missed_deposit_confirmations));
|
||||
GNUNET_break (NULL != report);
|
||||
json_dumpf (report,
|
||||
stdout,
|
||||
|
@ -390,6 +390,7 @@ postgres_create_tables (void *cls)
|
||||
we must check that the exchange reported these properly. */
|
||||
GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS deposit_confirmations "
|
||||
"(master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES auditor_exchanges(master_pub) ON DELETE CASCADE"
|
||||
",serial_id BIGSERIAL UNIQUE"
|
||||
",h_contract_terms BYTEA CHECK (LENGTH(h_contract_terms)=64)"
|
||||
",h_wire BYTEA CHECK (LENGTH(h_wire)=64)"
|
||||
",timestamp INT8 NOT NULL"
|
||||
@ -567,6 +568,25 @@ postgres_prepare (PGconn *db_conn)
|
||||
",master_sig" /* master_sig could be normalized... */
|
||||
") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13);",
|
||||
11),
|
||||
/* Used in #postgres_get_deposit_confirmations() */
|
||||
GNUNET_PQ_make_prepare ("auditor_deposit_confirmation_select",
|
||||
"SELECT"
|
||||
" h_contract_terms"
|
||||
",h_wire"
|
||||
",timestamp"
|
||||
",refund_deadline"
|
||||
",amount_without_fee_val"
|
||||
",amount_without_fee_frac"
|
||||
",amount_without_fee_curr"
|
||||
",coin_pub"
|
||||
",merchant_pub"
|
||||
",exchange_sig"
|
||||
",exchange_pub"
|
||||
",master_sig" /* master_sig could be normalized... */
|
||||
" FROM deposit_confirmations"
|
||||
" WHERE master_pub=$1"
|
||||
" AND serial_id>$2",
|
||||
2),
|
||||
/* Used in #postgres_update_auditor_progress_reserve() */
|
||||
GNUNET_PQ_make_prepare ("auditor_progress_update_reserve",
|
||||
"UPDATE auditor_progress_reserve SET "
|
||||
@ -1416,6 +1436,144 @@ postgres_insert_deposit_confirmation (void *cls,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #deposit_confirmation_cb().
|
||||
*/
|
||||
struct DepositConfirmationContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Master public key that is being used.
|
||||
*/
|
||||
const struct TALER_MasterPublicKeyP *master_pub;
|
||||
|
||||
/**
|
||||
* Function to call for each deposit confirmation.
|
||||
*/
|
||||
TALER_AUDITORDB_DepositConfirmationCallback cb;
|
||||
|
||||
/**
|
||||
* Closure for @e cb
|
||||
*/
|
||||
void *cb_cls;
|
||||
|
||||
/**
|
||||
* Query status to return.
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function for #postgres_get_deposit_confirmations().
|
||||
* To be called with the results of a SELECT statement
|
||||
* that has returned @a num_results results.
|
||||
*
|
||||
* @param cls closure of type `struct DepositConfirmationContext *`
|
||||
* @param result the postgres result
|
||||
* @param num_result the number of results in @a result
|
||||
*/
|
||||
static void
|
||||
deposit_confirmation_cb (void *cls,
|
||||
PGresult *result,
|
||||
unsigned int num_results)
|
||||
{
|
||||
struct DepositConfirmationContext *dcc = cls;
|
||||
|
||||
for (unsigned int i = 0; i < num_results; i++)
|
||||
{
|
||||
uint64_t serial_id;
|
||||
struct TALER_AUDITORDB_DepositConfirmation dc = {
|
||||
.master_public_key = *dcc->master_pub
|
||||
};
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_uint64 ("serial_id",
|
||||
&serial_id),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
|
||||
&dc.h_contract_terms),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_wire",
|
||||
&dc.h_wire),
|
||||
GNUNET_PQ_result_spec_absolute_time ("timetamp",
|
||||
&dc.timestamp),
|
||||
GNUNET_PQ_result_spec_absolute_time ("refund_deadline",
|
||||
&dc.refund_deadline),
|
||||
TALER_PQ_result_spec_amount ("amount_without_fee",
|
||||
&dc.amount_without_fee),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
|
||||
&dc.coin_pub),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
|
||||
&dc.merchant),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("exchange_sig",
|
||||
&dc.exchange_sig),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("exchange_pub",
|
||||
&dc.exchange_pub),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("master_sig",
|
||||
&dc.master_sig),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result,
|
||||
rs,
|
||||
i))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
|
||||
return;
|
||||
}
|
||||
dcc->qs = i + 1;
|
||||
dcc->cb (dcc->cb_cls,
|
||||
serial_id,
|
||||
&dc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get information about deposit confirmations from the database.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session connection to the database
|
||||
* @param master_pub for which exchange do we want to get deposit confirmations
|
||||
* @param start_id row/serial ID where to start the iteration (0 from
|
||||
* the start, exclusive, i.e. serial_ids must start from 1)
|
||||
* @param cb function to call with results
|
||||
* @param cb_cls closure for @a cb
|
||||
* @return query result status
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
postgres_get_deposit_confirmations (void *cls,
|
||||
struct TALER_AUDITORDB_Session *session,
|
||||
const struct TALER_MasterPublicKeyP *master_public_key,
|
||||
uint64_t start_id,
|
||||
TALER_AUDITORDB_DepositConfirmationCallback cb,
|
||||
void *cb_cls)
|
||||
{
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_auto_from_type (master_public_key),
|
||||
GNUNET_PQ_query_param_uint64 (&start_id),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
struct DepositConfirmationContext dcc = {
|
||||
.master_pub = master_public_key,
|
||||
.cb = cb,
|
||||
.cb_cls = cb_cls
|
||||
};
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
|
||||
"auditor_deposit_confirmation_select",
|
||||
params,
|
||||
&deposit_confirmation_cb,
|
||||
&dcc);
|
||||
if (qs > 0)
|
||||
return dcc.qs;
|
||||
GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Insert information about a denomination key and in particular
|
||||
* the properties (value, fees, expiration times) the coins signed
|
||||
@ -3264,6 +3422,7 @@ libtaler_plugin_auditordb_postgres_init (void *cls)
|
||||
plugin->list_exchanges = &postgres_list_exchanges;
|
||||
plugin->insert_exchange_signkey = &postgres_insert_exchange_signkey;
|
||||
plugin->insert_deposit_confirmation = &postgres_insert_deposit_confirmation;
|
||||
plugin->get_deposit_confirmations = &postgres_get_deposit_confirmations;
|
||||
|
||||
plugin->select_denomination_info = &postgres_select_denomination_info;
|
||||
plugin->insert_denomination_info = &postgres_insert_denomination_info;
|
||||
|
@ -142,7 +142,8 @@ deposit_transaction (void *cls,
|
||||
|
||||
qs = TEH_plugin->have_deposit (TEH_plugin->cls,
|
||||
session,
|
||||
deposit);
|
||||
deposit,
|
||||
GNUNET_YES /* check refund deadline */);
|
||||
if (qs < 0)
|
||||
{
|
||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||
|
@ -2730,6 +2730,7 @@ postgres_get_reserve_history (void *cls,
|
||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||
* @param session database connection
|
||||
* @param deposit deposit to search for
|
||||
* @param check_extras wether to check extra fields match or not
|
||||
* @return 1 if we know this operation,
|
||||
* 0 if this exact deposit is unknown to us,
|
||||
* otherwise transaction error status
|
||||
@ -2737,7 +2738,8 @@ postgres_get_reserve_history (void *cls,
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
postgres_have_deposit (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct TALER_EXCHANGEDB_Deposit *deposit)
|
||||
const struct TALER_EXCHANGEDB_Deposit *deposit,
|
||||
int check_extras)
|
||||
{
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
|
||||
@ -2755,8 +2757,6 @@ postgres_have_deposit (void *cls,
|
||||
&deposit2.refund_deadline),
|
||||
TALER_PQ_result_spec_absolute_time ("wire_deadline",
|
||||
&deposit2.wire_deadline),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
|
||||
&deposit2.h_contract_terms),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_wire",
|
||||
&deposit2.h_wire),
|
||||
GNUNET_PQ_result_spec_end
|
||||
@ -2774,18 +2774,16 @@ postgres_have_deposit (void *cls,
|
||||
return qs;
|
||||
/* Now we check that the other information in @a deposit
|
||||
also matches, and if not report inconsistencies. */
|
||||
if ( (0 != TALER_amount_cmp (&deposit->amount_with_fee,
|
||||
&deposit2.amount_with_fee)) ||
|
||||
(deposit->timestamp.abs_value_us !=
|
||||
deposit2.timestamp.abs_value_us) ||
|
||||
if ( ( (check_extras) &&
|
||||
( (0 != TALER_amount_cmp (&deposit->amount_with_fee,
|
||||
&deposit2.amount_with_fee)) ||
|
||||
(deposit->timestamp.abs_value_us !=
|
||||
deposit2.timestamp.abs_value_us) ) ) ||
|
||||
(deposit->refund_deadline.abs_value_us !=
|
||||
deposit2.refund_deadline.abs_value_us) ||
|
||||
(0 != memcmp (&deposit->h_contract_terms,
|
||||
&deposit2.h_contract_terms,
|
||||
sizeof (struct GNUNET_HashCode))) ||
|
||||
deposit2.refund_deadline.abs_value_us) ||
|
||||
(0 != memcmp (&deposit->h_wire,
|
||||
&deposit2.h_wire,
|
||||
sizeof (struct GNUNET_HashCode))) )
|
||||
&deposit2.h_wire,
|
||||
sizeof (struct GNUNET_HashCode)) ) )
|
||||
{
|
||||
/* Inconsistencies detected! Does not match! (We might want to
|
||||
expand the API with a 'get_deposit' function to return the
|
||||
|
@ -345,6 +345,20 @@ struct TALER_AUDITORDB_DepositConfirmation
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Function called with deposit confirmations stored in
|
||||
* the auditor's database.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param serial_id location of the @a dc in the database
|
||||
* @param dc the deposit confirmation itself
|
||||
*/
|
||||
typedef void
|
||||
(*TALER_AUDITORDB_DepositConfirmationCallback)(void *cls,
|
||||
uint64_t serial_id,
|
||||
const struct TALER_AUDITORDB_DepositConfirmation *dc);
|
||||
|
||||
|
||||
/**
|
||||
* Handle for one session with the database.
|
||||
*/
|
||||
@ -525,6 +539,27 @@ struct TALER_AUDITORDB_Plugin
|
||||
const struct TALER_AUDITORDB_DepositConfirmation *dc);
|
||||
|
||||
|
||||
/**
|
||||
* Get information about a deposit confirmations from the database.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session connection to the database
|
||||
* @param master_pub for which exchange do we want to get deposit confirmations
|
||||
* @param start_id row/serial ID where to start the iteration (0 from
|
||||
* the start, exclusive, i.e. serial_ids must start from 1)
|
||||
* @param cb function to call with results
|
||||
* @param cb_cls closure for @a cb
|
||||
* @return query result status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*get_deposit_confirmations) (void *cls,
|
||||
struct TALER_AUDITORDB_Session *session,
|
||||
const struct TALER_MasterPublicKeyP *master_public_key,
|
||||
uint64_t start_id,
|
||||
TALER_AUDITORDB_DepositConfirmationCallback cb,
|
||||
void *cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Insert information about a denomination key and in particular
|
||||
* the properties (value, fees, expiration times) the coins signed
|
||||
|
@ -1431,6 +1431,7 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session database connection
|
||||
* @param deposit deposit to search for
|
||||
* @param check_extras wether to check extra fields or not
|
||||
* @return 1 if we know this operation,
|
||||
* 0 if this exact deposit is unknown to us,
|
||||
* otherwise transaction error status
|
||||
@ -1438,7 +1439,8 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*have_deposit) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct TALER_EXCHANGEDB_Deposit *deposit);
|
||||
const struct TALER_EXCHANGEDB_Deposit *deposit,
|
||||
int check_extras);
|
||||
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user