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 %}
|
{% 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}
|
\section{Major irregularities}
|
||||||
|
|
||||||
This section describes the possible major irregularities that the
|
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;
|
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,
|
* Total delta between calculated and stored wire out transfers,
|
||||||
* for positive deltas.
|
* for positive deltas.
|
||||||
@ -235,6 +240,16 @@ static struct TALER_Amount total_arithmetic_delta_plus;
|
|||||||
*/
|
*/
|
||||||
static struct TALER_Amount total_arithmetic_delta_minus;
|
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().
|
* 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 ****************** */
|
/* *************************** General transaction logic ****************** */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4151,6 +4362,8 @@ setup_sessions_and_run ()
|
|||||||
NULL);
|
NULL);
|
||||||
transact (&analyze_coins,
|
transact (&analyze_coins,
|
||||||
NULL);
|
NULL);
|
||||||
|
transact (&analyze_deposit_confirmations,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4347,6 +4560,8 @@ run (void *cls,
|
|||||||
(report_reserve_not_closed_inconsistencies = json_array ()));
|
(report_reserve_not_closed_inconsistencies = json_array ()));
|
||||||
GNUNET_assert (NULL !=
|
GNUNET_assert (NULL !=
|
||||||
(report_wire_out_inconsistencies = json_array ()));
|
(report_wire_out_inconsistencies = json_array ()));
|
||||||
|
GNUNET_assert (NULL !=
|
||||||
|
(report_deposit_confirmation_inconsistencies = json_array ()));
|
||||||
GNUNET_assert (NULL !=
|
GNUNET_assert (NULL !=
|
||||||
(report_coin_inconsistencies = json_array ()));
|
(report_coin_inconsistencies = json_array ()));
|
||||||
GNUNET_assert (NULL !=
|
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: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 */
|
/* blocks of 5 for easier counting/matching to format string */
|
||||||
/* block */
|
/* block */
|
||||||
"reserve_balance_insufficient_inconsistencies",
|
"reserve_balance_insufficient_inconsistencies",
|
||||||
@ -4457,7 +4673,14 @@ run (void *cls,
|
|||||||
"total_refresh_hanging",
|
"total_refresh_hanging",
|
||||||
TALER_JSON_from_amount (&total_refresh_hanging),
|
TALER_JSON_from_amount (&total_refresh_hanging),
|
||||||
"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);
|
GNUNET_break (NULL != report);
|
||||||
json_dumpf (report,
|
json_dumpf (report,
|
||||||
stdout,
|
stdout,
|
||||||
|
@ -390,6 +390,7 @@ postgres_create_tables (void *cls)
|
|||||||
we must check that the exchange reported these properly. */
|
we must check that the exchange reported these properly. */
|
||||||
GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS deposit_confirmations "
|
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"
|
"(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_contract_terms BYTEA CHECK (LENGTH(h_contract_terms)=64)"
|
||||||
",h_wire BYTEA CHECK (LENGTH(h_wire)=64)"
|
",h_wire BYTEA CHECK (LENGTH(h_wire)=64)"
|
||||||
",timestamp INT8 NOT NULL"
|
",timestamp INT8 NOT NULL"
|
||||||
@ -567,6 +568,25 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
",master_sig" /* master_sig could be normalized... */
|
",master_sig" /* master_sig could be normalized... */
|
||||||
") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13);",
|
") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13);",
|
||||||
11),
|
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() */
|
/* Used in #postgres_update_auditor_progress_reserve() */
|
||||||
GNUNET_PQ_make_prepare ("auditor_progress_update_reserve",
|
GNUNET_PQ_make_prepare ("auditor_progress_update_reserve",
|
||||||
"UPDATE auditor_progress_reserve SET "
|
"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
|
* Insert information about a denomination key and in particular
|
||||||
* the properties (value, fees, expiration times) the coins signed
|
* 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->list_exchanges = &postgres_list_exchanges;
|
||||||
plugin->insert_exchange_signkey = &postgres_insert_exchange_signkey;
|
plugin->insert_exchange_signkey = &postgres_insert_exchange_signkey;
|
||||||
plugin->insert_deposit_confirmation = &postgres_insert_deposit_confirmation;
|
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->select_denomination_info = &postgres_select_denomination_info;
|
||||||
plugin->insert_denomination_info = &postgres_insert_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,
|
qs = TEH_plugin->have_deposit (TEH_plugin->cls,
|
||||||
session,
|
session,
|
||||||
deposit);
|
deposit,
|
||||||
|
GNUNET_YES /* check refund deadline */);
|
||||||
if (qs < 0)
|
if (qs < 0)
|
||||||
{
|
{
|
||||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
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 cls the `struct PostgresClosure` with the plugin-specific state
|
||||||
* @param session database connection
|
* @param session database connection
|
||||||
* @param deposit deposit to search for
|
* @param deposit deposit to search for
|
||||||
|
* @param check_extras wether to check extra fields match or not
|
||||||
* @return 1 if we know this operation,
|
* @return 1 if we know this operation,
|
||||||
* 0 if this exact deposit is unknown to us,
|
* 0 if this exact deposit is unknown to us,
|
||||||
* otherwise transaction error status
|
* otherwise transaction error status
|
||||||
@ -2737,7 +2738,8 @@ postgres_get_reserve_history (void *cls,
|
|||||||
static enum GNUNET_DB_QueryStatus
|
static enum GNUNET_DB_QueryStatus
|
||||||
postgres_have_deposit (void *cls,
|
postgres_have_deposit (void *cls,
|
||||||
struct TALER_EXCHANGEDB_Session *session,
|
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[] = {
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
|
GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
|
||||||
@ -2755,8 +2757,6 @@ postgres_have_deposit (void *cls,
|
|||||||
&deposit2.refund_deadline),
|
&deposit2.refund_deadline),
|
||||||
TALER_PQ_result_spec_absolute_time ("wire_deadline",
|
TALER_PQ_result_spec_absolute_time ("wire_deadline",
|
||||||
&deposit2.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",
|
GNUNET_PQ_result_spec_auto_from_type ("h_wire",
|
||||||
&deposit2.h_wire),
|
&deposit2.h_wire),
|
||||||
GNUNET_PQ_result_spec_end
|
GNUNET_PQ_result_spec_end
|
||||||
@ -2774,18 +2774,16 @@ postgres_have_deposit (void *cls,
|
|||||||
return qs;
|
return qs;
|
||||||
/* Now we check that the other information in @a deposit
|
/* Now we check that the other information in @a deposit
|
||||||
also matches, and if not report inconsistencies. */
|
also matches, and if not report inconsistencies. */
|
||||||
if ( (0 != TALER_amount_cmp (&deposit->amount_with_fee,
|
if ( ( (check_extras) &&
|
||||||
&deposit2.amount_with_fee)) ||
|
( (0 != TALER_amount_cmp (&deposit->amount_with_fee,
|
||||||
(deposit->timestamp.abs_value_us !=
|
&deposit2.amount_with_fee)) ||
|
||||||
deposit2.timestamp.abs_value_us) ||
|
(deposit->timestamp.abs_value_us !=
|
||||||
|
deposit2.timestamp.abs_value_us) ) ) ||
|
||||||
(deposit->refund_deadline.abs_value_us !=
|
(deposit->refund_deadline.abs_value_us !=
|
||||||
deposit2.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))) ||
|
|
||||||
(0 != memcmp (&deposit->h_wire,
|
(0 != memcmp (&deposit->h_wire,
|
||||||
&deposit2.h_wire,
|
&deposit2.h_wire,
|
||||||
sizeof (struct GNUNET_HashCode))) )
|
sizeof (struct GNUNET_HashCode)) ) )
|
||||||
{
|
{
|
||||||
/* Inconsistencies detected! Does not match! (We might want to
|
/* Inconsistencies detected! Does not match! (We might want to
|
||||||
expand the API with a 'get_deposit' function to return the
|
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.
|
* Handle for one session with the database.
|
||||||
*/
|
*/
|
||||||
@ -525,6 +539,27 @@ struct TALER_AUDITORDB_Plugin
|
|||||||
const struct TALER_AUDITORDB_DepositConfirmation *dc);
|
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
|
* Insert information about a denomination key and in particular
|
||||||
* the properties (value, fees, expiration times) the coins signed
|
* 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 cls the @e cls of this struct with the plugin-specific state
|
||||||
* @param session database connection
|
* @param session database connection
|
||||||
* @param deposit deposit to search for
|
* @param deposit deposit to search for
|
||||||
|
* @param check_extras wether to check extra fields or not
|
||||||
* @return 1 if we know this operation,
|
* @return 1 if we know this operation,
|
||||||
* 0 if this exact deposit is unknown to us,
|
* 0 if this exact deposit is unknown to us,
|
||||||
* otherwise transaction error status
|
* otherwise transaction error status
|
||||||
@ -1438,7 +1439,8 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
enum GNUNET_DB_QueryStatus
|
enum GNUNET_DB_QueryStatus
|
||||||
(*have_deposit) (void *cls,
|
(*have_deposit) (void *cls,
|
||||||
struct TALER_EXCHANGEDB_Session *session,
|
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