handle /payback in auditor when checking reserves

This commit is contained in:
Christian Grothoff 2017-04-04 15:38:58 +02:00
parent cc3aa31732
commit 4b82a591c5
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
6 changed files with 418 additions and 103 deletions

View File

@ -799,6 +799,89 @@ handle_reserve_out (void *cls,
} }
/**
* Function called with details about withdraw operations. Verifies
* the signature and updates the reserve's balance.
*
* @param cls our `struct ReserveContext`
* @param rowid unique serial ID for the refresh session in our DB
* @param timestamp when did we receive the payback request
* @param amount how much should be added back to the reserve
* @param reserve_pub public key of the reserve
* @param coin_pub public key of the coin
* @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_PAYBACK
* @param h_denom_pub hash of the denomination key of the coin
* @param coin_blind blinding factor used to blind the coin
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
static int
handle_payback_by_reserve (void *cls,
uint64_t rowid,
struct GNUNET_TIME_Absolute timestamp,
const struct TALER_Amount *amount,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig,
const struct GNUNET_HashCode *h_denom_pub,
const struct TALER_DenominationBlindingKeyP *coin_blind)
{
struct ReserveContext *rc = cls;
struct GNUNET_HashCode key;
struct ReserveSummary *rs;
struct GNUNET_TIME_Absolute expiry;
/* should be monotonically increasing */
GNUNET_assert (rowid >= pp.last_reserve_payback_serial_id);
pp.last_reserve_payback_serial_id = rowid + 1;
GNUNET_CRYPTO_hash (reserve_pub,
sizeof (*reserve_pub),
&key);
rs = GNUNET_CONTAINER_multihashmap_get (rc->reserves,
&key);
if (NULL == rs)
{
rs = GNUNET_new (struct ReserveSummary);
rs->reserve_pub = *reserve_pub;
rs->total_in = *amount;
GNUNET_assert (GNUNET_OK ==
TALER_amount_get_zero (amount->currency,
&rs->total_out));
GNUNET_assert (GNUNET_OK ==
TALER_amount_get_zero (amount->currency,
&rs->total_fee));
if (GNUNET_OK !=
load_auditor_reserve_summary (rs))
{
GNUNET_break (0);
GNUNET_free (rs);
return GNUNET_SYSERR;
}
GNUNET_assert (GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_put (rc->reserves,
&key,
rs,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
}
else
{
GNUNET_assert (GNUNET_OK ==
TALER_amount_add (&rs->total_in,
&rs->total_in,
amount));
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Additional /payback value to for reserve `%s' of %s\n",
TALER_B2S (reserve_pub),
TALER_amount2s (amount));
expiry = GNUNET_TIME_absolute_add (timestamp,
TALER_IDLE_RESERVE_EXPIRATION_TIME);
rs->a_expiration_date = GNUNET_TIME_absolute_max (rs->a_expiration_date,
expiry);
return GNUNET_OK;
}
/** /**
* Check that the reserve summary matches what the exchange database * Check that the reserve summary matches what the exchange database
* thinks about the reserve, and update our own state of the reserve. * thinks about the reserve, and update our own state of the reserve.
@ -1041,7 +1124,20 @@ analyze_reserves (void *cls)
GNUNET_break (0); GNUNET_break (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
/* TODO: iterate over table for reserve expiration refunds! (#4956) */ if (GNUNET_SYSERR ==
edb->select_payback_above_serial_id (edb->cls,
esession,
pp.last_reserve_payback_serial_id,
&handle_payback_by_reserve,
&rc))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
/* TODO: iterate over table for reserve expiration refunds! (#4956);
should use pp.last_reserve_close_serial_id */
GNUNET_CONTAINER_multihashmap_iterate (rc.reserves, GNUNET_CONTAINER_multihashmap_iterate (rc.reserves,
&verify_reserve_balance, &verify_reserve_balance,
@ -1774,8 +1870,9 @@ get_wire_fee (struct AggregationContext *ac,
* @param wtid wire transfer subject * @param wtid wire transfer subject
* @param wire wire transfer details of the receiver * @param wire wire transfer details of the receiver
* @param amount amount that was wired * @param amount amount that was wired
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration
*/ */
static void static int
check_wire_out_cb (void *cls, check_wire_out_cb (void *cls,
uint64_t rowid, uint64_t rowid,
struct GNUNET_TIME_Absolute date, struct GNUNET_TIME_Absolute date,
@ -1809,7 +1906,7 @@ check_wire_out_cb (void *cls,
report_row_inconsistency ("wire_out", report_row_inconsistency ("wire_out",
rowid, rowid,
"specified wire address lacks type"); "specified wire address lacks type");
return; return GNUNET_OK;
} }
wcc.method = json_string_value (method); wcc.method = json_string_value (method);
wcc.ok = GNUNET_OK; wcc.ok = GNUNET_OK;
@ -1828,7 +1925,7 @@ check_wire_out_cb (void *cls,
report_row_inconsistency ("wire_out", report_row_inconsistency ("wire_out",
rowid, rowid,
"audit of associated transactions failed"); "audit of associated transactions failed");
return; return GNUNET_OK;
} }
/* Subtract aggregation fee from total */ /* Subtract aggregation fee from total */
@ -1839,7 +1936,7 @@ check_wire_out_cb (void *cls,
{ {
GNUNET_break (0); GNUNET_break (0);
ac->ret = GNUNET_SYSERR; ac->ret = GNUNET_SYSERR;
return; return GNUNET_SYSERR;
} }
if (GNUNET_SYSERR == if (GNUNET_SYSERR ==
TALER_amount_subtract (&final_amount, TALER_amount_subtract (&final_amount,
@ -1849,7 +1946,7 @@ check_wire_out_cb (void *cls,
report_row_inconsistency ("wire_out", report_row_inconsistency ("wire_out",
rowid, rowid,
"could not subtract wire fee from total amount"); "could not subtract wire fee from total amount");
return; return GNUNET_OK;
} }
/* Round down to amount supported by wire method */ /* Round down to amount supported by wire method */
@ -1860,7 +1957,7 @@ check_wire_out_cb (void *cls,
report_row_inconsistency ("wire_out", report_row_inconsistency ("wire_out",
rowid, rowid,
"could not load required wire plugin to validate"); "could not load required wire plugin to validate");
return; return GNUNET_OK;
} }
if (GNUNET_SYSERR == if (GNUNET_SYSERR ==
@ -1880,7 +1977,7 @@ check_wire_out_cb (void *cls,
{ {
GNUNET_break (0); GNUNET_break (0);
ac->ret = GNUNET_SYSERR; ac->ret = GNUNET_SYSERR;
return; return GNUNET_SYSERR;
} }
/* Sum up aggregation fees (we simply include the rounding gains) */ /* Sum up aggregation fees (we simply include the rounding gains) */
@ -1891,7 +1988,7 @@ check_wire_out_cb (void *cls,
{ {
GNUNET_break (0); GNUNET_break (0);
ac->ret = GNUNET_SYSERR; ac->ret = GNUNET_SYSERR;
return; return GNUNET_SYSERR;
} }
/* Check that calculated amount matches actual amount */ /* Check that calculated amount matches actual amount */
@ -1903,11 +2000,12 @@ check_wire_out_cb (void *cls,
&final_amount, &final_amount,
amount, amount,
"computed amount inconsistent with wire amount"); "computed amount inconsistent with wire amount");
return; return GNUNET_OK;
} }
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Wire transfer %s is OK\n", "Wire transfer %s is OK\n",
TALER_B2S (wtid)); TALER_B2S (wtid));
return GNUNET_OK;
} }

View File

@ -301,6 +301,8 @@ postgres_create_tables (void *cls)
"(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)" "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
",last_reserve_in_serial_id INT8 NOT NULL" ",last_reserve_in_serial_id INT8 NOT NULL"
",last_reserve_out_serial_id INT8 NOT NULL" ",last_reserve_out_serial_id INT8 NOT NULL"
",last_reserve_payback_serial_id INT8 NOT NULL"
",last_reserve_close_serial_id INT8 NOT NULL"
",last_withdraw_serial_id INT8 NOT NULL" ",last_withdraw_serial_id INT8 NOT NULL"
",last_deposit_serial_id INT8 NOT NULL" ",last_deposit_serial_id INT8 NOT NULL"
",last_melt_serial_id INT8 NOT NULL" ",last_melt_serial_id INT8 NOT NULL"
@ -575,32 +577,38 @@ postgres_prepare (PGconn *db_conn)
"(master_pub" "(master_pub"
",last_reserve_in_serial_id" ",last_reserve_in_serial_id"
",last_reserve_out_serial_id" ",last_reserve_out_serial_id"
",last_reserve_payback_serial_id"
",last_reserve_close_serial_id"
",last_withdraw_serial_id" ",last_withdraw_serial_id"
",last_deposit_serial_id" ",last_deposit_serial_id"
",last_melt_serial_id" ",last_melt_serial_id"
",last_refund_serial_id" ",last_refund_serial_id"
",last_wire_out_serial_id" ",last_wire_out_serial_id"
") VALUES ($1,$2,$3,$4,$5,$6,$7,$8);", ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);",
8, NULL); 10, NULL);
/* Used in #postgres_update_auditor_progress() */ /* Used in #postgres_update_auditor_progress() */
PREPARE ("auditor_progress_update", PREPARE ("auditor_progress_update",
"UPDATE auditor_progress SET " "UPDATE auditor_progress SET "
" last_reserve_in_serial_id=$1" " last_reserve_in_serial_id=$1"
",last_reserve_out_serial_id=$2" ",last_reserve_out_serial_id=$2"
",last_withdraw_serial_id=$3" ",last_reserve_payback_serial_id=$3"
",last_deposit_serial_id=$4" ",last_reserve_close_serial_id=$4"
",last_melt_serial_id=$5" ",last_withdraw_serial_id=$5"
",last_refund_serial_id=$6" ",last_deposit_serial_id=$6"
",last_wire_out_serial_id=$7" ",last_melt_serial_id=$7"
" WHERE master_pub=$8", ",last_refund_serial_id=$8"
8, NULL); ",last_wire_out_serial_id=$9"
" WHERE master_pub=$10",
10, NULL);
/* Used in #postgres_get_auditor_progress() */ /* Used in #postgres_get_auditor_progress() */
PREPARE ("auditor_progress_select", PREPARE ("auditor_progress_select",
"SELECT" "SELECT"
" last_reserve_in_serial_id" " last_reserve_in_serial_id"
",last_reserve_out_serial_id" ",last_reserve_out_serial_id"
",last_reserve_payback_serial_id"
",last_reserve_close_serial_id"
",last_withdraw_serial_id" ",last_withdraw_serial_id"
",last_deposit_serial_id" ",last_deposit_serial_id"
",last_melt_serial_id" ",last_melt_serial_id"
@ -1310,6 +1318,8 @@ postgres_insert_auditor_progress (void *cls,
GNUNET_PQ_query_param_auto_from_type (master_pub), GNUNET_PQ_query_param_auto_from_type (master_pub),
GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id), GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_reserve_out_serial_id), GNUNET_PQ_query_param_uint64 (&pp->last_reserve_out_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_reserve_payback_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_reserve_close_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_withdraw_serial_id), GNUNET_PQ_query_param_uint64 (&pp->last_withdraw_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_deposit_serial_id), GNUNET_PQ_query_param_uint64 (&pp->last_deposit_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_melt_serial_id), GNUNET_PQ_query_param_uint64 (&pp->last_melt_serial_id),
@ -1356,6 +1366,8 @@ postgres_update_auditor_progress (void *cls,
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id), GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_reserve_out_serial_id), GNUNET_PQ_query_param_uint64 (&pp->last_reserve_out_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_reserve_payback_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_reserve_close_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_withdraw_serial_id), GNUNET_PQ_query_param_uint64 (&pp->last_withdraw_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_deposit_serial_id), GNUNET_PQ_query_param_uint64 (&pp->last_deposit_serial_id),
GNUNET_PQ_query_param_uint64 (&pp->last_melt_serial_id), GNUNET_PQ_query_param_uint64 (&pp->last_melt_serial_id),
@ -1405,13 +1417,24 @@ postgres_get_auditor_progress (void *cls,
}; };
PGresult *result; PGresult *result;
struct GNUNET_PQ_ResultSpec rs[] = { struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint64 ("last_reserve_in_serial_id", &pp->last_reserve_in_serial_id), GNUNET_PQ_result_spec_uint64 ("last_reserve_in_serial_id",
GNUNET_PQ_result_spec_uint64 ("last_reserve_out_serial_id", &pp->last_reserve_out_serial_id), &pp->last_reserve_in_serial_id),
GNUNET_PQ_result_spec_uint64 ("last_withdraw_serial_id", &pp->last_withdraw_serial_id), GNUNET_PQ_result_spec_uint64 ("last_reserve_out_serial_id",
GNUNET_PQ_result_spec_uint64 ("last_deposit_serial_id", &pp->last_deposit_serial_id), &pp->last_reserve_out_serial_id),
GNUNET_PQ_result_spec_uint64 ("last_melt_serial_id", &pp->last_melt_serial_id), GNUNET_PQ_result_spec_uint64 ("last_reserve_payback_serial_id",
GNUNET_PQ_result_spec_uint64 ("last_refund_serial_id", &pp->last_refund_serial_id), &pp->last_reserve_payback_serial_id),
GNUNET_PQ_result_spec_uint64 ("last_wire_out_serial_id", &pp->last_wire_out_serial_id), GNUNET_PQ_result_spec_uint64 ("last_reserve_close_serial_id",
&pp->last_reserve_out_serial_id),
GNUNET_PQ_result_spec_uint64 ("last_withdraw_serial_id",
&pp->last_withdraw_serial_id),
GNUNET_PQ_result_spec_uint64 ("last_deposit_serial_id",
&pp->last_deposit_serial_id),
GNUNET_PQ_result_spec_uint64 ("last_melt_serial_id",
&pp->last_melt_serial_id),
GNUNET_PQ_result_spec_uint64 ("last_refund_serial_id",
&pp->last_refund_serial_id),
GNUNET_PQ_result_spec_uint64 ("last_wire_out_serial_id",
&pp->last_wire_out_serial_id),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end
}; };

View File

@ -515,7 +515,8 @@ postgres_create_tables (void *cls)
/* Table for /payback information */ /* Table for /payback information */
SQLEXEC("CREATE TABLE IF NOT EXISTS payback " SQLEXEC("CREATE TABLE IF NOT EXISTS payback "
"(reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE CASCADE" "(payback_uuid BIGSERIAL"
",reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE CASCADE"
",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)" ",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)"
",coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)" ",coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)"
",coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)" ",coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)"
@ -1418,6 +1419,26 @@ postgres_prepare (PGconn *db_conn)
"($1, $2, $3, $4, $5, $6, $7, $8, $9)", "($1, $2, $3, $4, $5, $6, $7, $8, $9)",
9, NULL); 9, NULL);
/* Used in #postgres_select_payback_above_serial_id() to obtain payback transactions */
PREPARE ("payback_get_incr",
"SELECT"
" payback_uuid"
",timestamp"
",reserve_pub"
",coin_pub"
",coin_sig"
",coin_blind"
",h_blind_ev"
",denom.denom_pub"
",amount_val"
",amount_frac"
",amount_curr"
" FROM payback"
" JOIN reserves_out denom USING (reserve_pub,h_blind_ev)"
" WHERE payback_uuid>=$1"
" ORDER BY payback_uuid ASC",
1, NULL);
/* Used in #postgres_get_reserve_history() to obtain payback transactions /* Used in #postgres_get_reserve_history() to obtain payback transactions
for a reserve */ for a reserve */
PREPARE ("payback_by_reserve", PREPARE ("payback_by_reserve",
@ -5057,7 +5078,7 @@ postgres_select_deposits_above_serial_id (void *cls,
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
int nrows; int nrows;
int i; int ret;
nrows = PQntuples (result); nrows = PQntuples (result);
if (0 == nrows) if (0 == nrows)
@ -5067,7 +5088,7 @@ postgres_select_deposits_above_serial_id (void *cls,
PQclear (result); PQclear (result);
return GNUNET_NO; return GNUNET_NO;
} }
for (i=0;i<nrows;i++) for (int i=0;i<nrows;i++)
{ {
struct TALER_EXCHANGEDB_Deposit deposit; struct TALER_EXCHANGEDB_Deposit deposit;
struct TALER_DenominationPublicKey denom_pub; struct TALER_DenominationPublicKey denom_pub;
@ -5109,7 +5130,7 @@ postgres_select_deposits_above_serial_id (void *cls,
PQclear (result); PQclear (result);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
cb (cb_cls, ret = cb (cb_cls,
rowid, rowid,
deposit.timestamp, deposit.timestamp,
&deposit.merchant_pub, &deposit.merchant_pub,
@ -5123,6 +5144,8 @@ postgres_select_deposits_above_serial_id (void *cls,
deposit.receiver_wire_account, deposit.receiver_wire_account,
done); done);
GNUNET_PQ_cleanup_result (rs); GNUNET_PQ_cleanup_result (rs);
if (GNUNET_OK != ret)
break;
} }
PQclear (result); PQclear (result);
return GNUNET_OK; return GNUNET_OK;
@ -5153,6 +5176,10 @@ postgres_select_refreshs_above_serial_id (void *cls,
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
PGresult *result; PGresult *result;
int nrows;
int i;
int ret;
result = GNUNET_PQ_exec_prepared (session->conn, result = GNUNET_PQ_exec_prepared (session->conn,
"audit_get_refresh_sessions_incr", "audit_get_refresh_sessions_incr",
params); params);
@ -5164,8 +5191,6 @@ postgres_select_refreshs_above_serial_id (void *cls,
PQclear (result); PQclear (result);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
int nrows;
int i;
nrows = PQntuples (result); nrows = PQntuples (result);
if (0 == nrows) if (0 == nrows)
@ -5215,7 +5240,7 @@ postgres_select_refreshs_above_serial_id (void *cls,
PQclear (result); PQclear (result);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
cb (cb_cls, ret = cb (cb_cls,
rowid, rowid,
&denom_pub, &denom_pub,
&coin_pub, &coin_pub,
@ -5225,6 +5250,8 @@ postgres_select_refreshs_above_serial_id (void *cls,
noreveal_index, noreveal_index,
&session_hash); &session_hash);
GNUNET_PQ_cleanup_result (rs); GNUNET_PQ_cleanup_result (rs);
if (GNUNET_OK != ret)
break;
} }
PQclear (result); PQclear (result);
return GNUNET_OK; return GNUNET_OK;
@ -5255,6 +5282,9 @@ postgres_select_refunds_above_serial_id (void *cls,
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
PGresult *result; PGresult *result;
int nrows;
int ret;
result = GNUNET_PQ_exec_prepared (session->conn, result = GNUNET_PQ_exec_prepared (session->conn,
"audit_get_refunds_incr", "audit_get_refunds_incr",
params); params);
@ -5265,8 +5295,6 @@ postgres_select_refunds_above_serial_id (void *cls,
PQclear (result); PQclear (result);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
int nrows;
int i;
nrows = PQntuples (result); nrows = PQntuples (result);
if (0 == nrows) if (0 == nrows)
@ -5276,7 +5304,7 @@ postgres_select_refunds_above_serial_id (void *cls,
PQclear (result); PQclear (result);
return GNUNET_NO; return GNUNET_NO;
} }
for (i=0;i<nrows;i++) for (int i=0;i<nrows;i++)
{ {
struct TALER_EXCHANGEDB_Refund refund; struct TALER_EXCHANGEDB_Refund refund;
struct TALER_DenominationPublicKey denom_pub; struct TALER_DenominationPublicKey denom_pub;
@ -5310,7 +5338,7 @@ postgres_select_refunds_above_serial_id (void *cls,
PQclear (result); PQclear (result);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
cb (cb_cls, ret = cb (cb_cls,
rowid, rowid,
&denom_pub, &denom_pub,
&refund.coin.coin_pub, &refund.coin.coin_pub,
@ -5320,6 +5348,8 @@ postgres_select_refunds_above_serial_id (void *cls,
refund.rtransaction_id, refund.rtransaction_id,
&refund.refund_amount); &refund.refund_amount);
GNUNET_PQ_cleanup_result (rs); GNUNET_PQ_cleanup_result (rs);
if (GNUNET_OK != ret)
break;
} }
PQclear (result); PQclear (result);
return GNUNET_OK; return GNUNET_OK;
@ -5361,7 +5391,7 @@ postgres_select_reserves_in_above_serial_id (void *cls,
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
int nrows; int nrows;
int i; int ret;
nrows = PQntuples (result); nrows = PQntuples (result);
if (0 == nrows) if (0 == nrows)
@ -5372,7 +5402,7 @@ postgres_select_reserves_in_above_serial_id (void *cls,
return GNUNET_NO; return GNUNET_NO;
} }
for (i=0;i<nrows;i++) for (int i=0;i<nrows;i++)
{ {
struct TALER_ReservePublicKeyP reserve_pub; struct TALER_ReservePublicKeyP reserve_pub;
struct TALER_Amount credit; struct TALER_Amount credit;
@ -5406,7 +5436,7 @@ postgres_select_reserves_in_above_serial_id (void *cls,
PQclear (result); PQclear (result);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
cb (cb_cls, ret = cb (cb_cls,
rowid, rowid,
&reserve_pub, &reserve_pub,
&credit, &credit,
@ -5414,6 +5444,8 @@ postgres_select_reserves_in_above_serial_id (void *cls,
transfer_details, transfer_details,
execution_date); execution_date);
GNUNET_PQ_cleanup_result (rs); GNUNET_PQ_cleanup_result (rs);
if (GNUNET_OK != ret)
break;
} }
PQclear (result); PQclear (result);
@ -5457,7 +5489,7 @@ postgres_select_reserves_out_above_serial_id (void *cls,
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
int nrows; int nrows;
int i; int ret;
nrows = PQntuples (result); nrows = PQntuples (result);
if (0 == nrows) if (0 == nrows)
@ -5467,7 +5499,7 @@ postgres_select_reserves_out_above_serial_id (void *cls,
PQclear (result); PQclear (result);
return GNUNET_NO; return GNUNET_NO;
} }
for (i=0;i<nrows;i++) for (int i=0;i<nrows;i++)
{ {
struct GNUNET_HashCode h_blind_ev; struct GNUNET_HashCode h_blind_ev;
struct TALER_DenominationPublicKey denom_pub; struct TALER_DenominationPublicKey denom_pub;
@ -5506,7 +5538,7 @@ postgres_select_reserves_out_above_serial_id (void *cls,
PQclear (result); PQclear (result);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
cb (cb_cls, ret = cb (cb_cls,
rowid, rowid,
&h_blind_ev, &h_blind_ev,
&denom_pub, &denom_pub,
@ -5516,6 +5548,8 @@ postgres_select_reserves_out_above_serial_id (void *cls,
execution_date, execution_date,
&amount_with_fee); &amount_with_fee);
GNUNET_PQ_cleanup_result (rs); GNUNET_PQ_cleanup_result (rs);
if (GNUNET_OK != ret)
break;
} }
PQclear (result); PQclear (result);
@ -5548,6 +5582,9 @@ postgres_select_wire_out_above_serial_id (void *cls,
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
PGresult *result; PGresult *result;
int nrows;
int ret;
result = GNUNET_PQ_exec_prepared (session->conn, result = GNUNET_PQ_exec_prepared (session->conn,
"audit_get_wire_incr", "audit_get_wire_incr",
params); params);
@ -5558,7 +5595,6 @@ postgres_select_wire_out_above_serial_id (void *cls,
PQclear (result); PQclear (result);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
int nrows;
nrows = PQntuples (result); nrows = PQntuples (result);
if (0 == nrows) if (0 == nrows)
@ -5600,13 +5636,126 @@ postgres_select_wire_out_above_serial_id (void *cls,
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
cb (cb_cls, ret = cb (cb_cls,
rowid, rowid,
date, date,
&wtid, &wtid,
wire, wire,
&amount); &amount);
GNUNET_PQ_cleanup_result (rs); GNUNET_PQ_cleanup_result (rs);
if (GNUNET_OK != ret)
break;
}
PQclear (result);
return GNUNET_OK;
}
/**
* Function called to select payback requests the exchange
* received, ordered by serial ID (monotonically increasing).
*
* @param cls closure
* @param session database connection
* @param serial_id lowest serial ID to include (select larger or equal)
* @param cb function to call for ONE unfinished item
* @param cb_cls closure for @a cb
* @return #GNUNET_OK on success,
* #GNUNET_NO if there are no entries,
* #GNUNET_SYSERR on DB errors
*/
static int
postgres_select_payback_above_serial_id (void *cls,
struct TALER_EXCHANGEDB_Session *session,
uint64_t serial_id,
TALER_EXCHANGEDB_PaybackCallback cb,
void *cb_cls)
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_uint64 (&serial_id),
GNUNET_PQ_query_param_end
};
PGresult *result;
result = GNUNET_PQ_exec_prepared (session->conn,
"payback_get_incr",
params);
if (PGRES_TUPLES_OK !=
PQresultStatus (result))
{
BREAK_DB_ERR (result, session->conn);
PQclear (result);
return GNUNET_SYSERR;
}
int nrows;
int ret;
nrows = PQntuples (result);
if (0 == nrows)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"select_prepare_above_serial_id() returned 0 matching rows\n");
PQclear (result);
return GNUNET_NO;
}
for (int i=0;i<nrows;i++)
{
uint64_t rowid;
struct TALER_ReservePublicKeyP reserve_pub;
struct TALER_CoinSpendPublicKeyP coin_pub;
struct TALER_CoinSpendSignatureP coin_sig;
struct TALER_DenominationBlindingKeyP coin_blind;
struct TALER_Amount amount;
struct GNUNET_HashCode h_blind_ev;
struct GNUNET_TIME_Absolute timestamp;
struct TALER_DenominationPublicKey denom_pub;
struct GNUNET_HashCode h_denom_pub;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint64 ("payback_uuid",
&rowid),
GNUNET_PQ_result_spec_absolute_time ("timestamp",
&timestamp),
GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
&reserve_pub),
GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
&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_auto_from_type ("h_blind_ev",
&h_blind_ev),
GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
&denom_pub.rsa_public_key),
TALER_PQ_result_spec_amount ("amount",
&amount),
GNUNET_PQ_result_spec_end
};
if (GNUNET_OK !=
GNUNET_PQ_extract_result (result,
rs,
i))
{
GNUNET_break (0);
PQclear (result);
return GNUNET_SYSERR;
}
GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key,
&h_denom_pub);
ret = cb (cb_cls,
rowid,
timestamp,
&amount,
&reserve_pub,
&coin_pub,
&coin_sig,
&h_denom_pub,
&coin_blind);
GNUNET_PQ_cleanup_result (rs);
if (GNUNET_OK != ret)
break;
} }
PQclear (result); PQclear (result);
@ -5868,6 +6017,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
plugin->select_reserves_in_above_serial_id = &postgres_select_reserves_in_above_serial_id; plugin->select_reserves_in_above_serial_id = &postgres_select_reserves_in_above_serial_id;
plugin->select_reserves_out_above_serial_id = &postgres_select_reserves_out_above_serial_id; plugin->select_reserves_out_above_serial_id = &postgres_select_reserves_out_above_serial_id;
plugin->select_wire_out_above_serial_id = &postgres_select_wire_out_above_serial_id; plugin->select_wire_out_above_serial_id = &postgres_select_wire_out_above_serial_id;
plugin->select_payback_above_serial_id = &postgres_select_payback_above_serial_id;
plugin->insert_payback_request = &postgres_insert_payback_request; plugin->insert_payback_request = &postgres_insert_payback_request;
plugin->get_reserve_by_h_blind = &postgres_get_reserve_by_h_blind; plugin->get_reserve_by_h_blind = &postgres_get_reserve_by_h_blind;
return plugin; return plugin;

View File

@ -1205,8 +1205,9 @@ static struct TALER_Amount wire_out_amount;
* @param wtid wire transfer subject * @param wtid wire transfer subject
* @param wire wire transfer details of the receiver * @param wire wire transfer details of the receiver
* @param amount amount that was wired * @param amount amount that was wired
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration
*/ */
static void static int
audit_wire_cb (void *cls, audit_wire_cb (void *cls,
uint64_t rowid, uint64_t rowid,
struct GNUNET_TIME_Absolute date, struct GNUNET_TIME_Absolute date,
@ -1223,6 +1224,7 @@ audit_wire_cb (void *cls,
&wire_out_wtid, &wire_out_wtid,
sizeof (*wtid))); sizeof (*wtid)));
GNUNET_assert (date.abs_value_us == wire_out_date.abs_value_us); GNUNET_assert (date.abs_value_us == wire_out_date.abs_value_us);
return GNUNET_OK;
} }

View File

@ -121,6 +121,18 @@ struct TALER_AUDITORDB_ProgressPoint
*/ */
uint64_t last_reserve_out_serial_id; uint64_t last_reserve_out_serial_id;
/**
* last_payback_serial_id serial ID of the last payback entry the auditor processed when
* considering reserves.
*/
uint64_t last_reserve_payback_serial_id;
/**
* last_reserve_close_serial_id serial ID of the last reserve_close
* entry the auditor processed.
*/
uint64_t last_reserve_close_serial_id;
/** /**
* last_reserve_out_serial_id serial ID of the last withdraw the auditor processed * last_reserve_out_serial_id serial ID of the last withdraw the auditor processed
*/ */

View File

@ -875,8 +875,9 @@ typedef void
* @param wtid wire transfer subject * @param wtid wire transfer subject
* @param wire wire transfer details of the receiver * @param wire wire transfer details of the receiver
* @param amount amount that was wired * @param amount amount that was wired
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration
*/ */
typedef void typedef int
(*TALER_EXCHANGEDB_WireTransferOutCallback)(void *cls, (*TALER_EXCHANGEDB_WireTransferOutCallback)(void *cls,
uint64_t rowid, uint64_t rowid,
struct GNUNET_TIME_Absolute date, struct GNUNET_TIME_Absolute date,
@ -894,8 +895,9 @@ typedef void
* @param buf transaction data that was persisted, NULL on error * @param buf transaction data that was persisted, NULL on error
* @param buf_size number of bytes in @a buf, 0 on error * @param buf_size number of bytes in @a buf, 0 on error
* @param finished did we complete the transfer yet? * @param finished did we complete the transfer yet?
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration
*/ */
typedef void typedef int
(*TALER_EXCHANGEDB_WirePreparationCallback)(void *cls, (*TALER_EXCHANGEDB_WirePreparationCallback)(void *cls,
uint64_t rowid, uint64_t rowid,
const char *wire_method, const char *wire_method,
@ -909,18 +911,25 @@ typedef void
* *
* @param cls closure * @param cls closure
* @param rowid row identifier used to uniquely identify the payback operation * @param rowid row identifier used to uniquely identify the payback operation
* @param deadline by when did we promise the payment * @param timestamp when did we receive the payback request
* @param receiver_account_details to whom do we need to send the funds * @param amount how much should be added back to the reserve
* @param amount how much should be transferred * @param reserve_pub public key of the reserve
* @param wire_subject what should be the wire subject * @param coin_pub public key of the coin
* @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_PAYBACK
* @param h_denom_pub hash of the denomination key of the coin
* @param coin_blind blinding factor used to blind the coin
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/ */
typedef void typedef int
(*TALER_EXCHANGEDB_PaybackCallback)(void *cls, (*TALER_EXCHANGEDB_PaybackCallback)(void *cls,
uint64_t rowid, uint64_t rowid,
struct GNUNET_TIME_Absolute deadline, struct GNUNET_TIME_Absolute timestamp,
const json_t *receiver_account_details,
const struct TALER_Amount *amount, const struct TALER_Amount *amount,
const struct TALER_WireTransferIdentifierRawP *wtid); const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig,
const struct GNUNET_HashCode *h_denom_pub,
const struct TALER_DenominationBlindingKeyP *coin_blind);
/** /**
@ -1939,6 +1948,27 @@ struct TALER_EXCHANGEDB_Plugin
void *cb_cls); void *cb_cls);
/**
* Function called to select payback requests the exchange
* received, ordered by serial ID (monotonically increasing).
*
* @param cls closure
* @param session database connection
* @param serial_id lowest serial ID to include (select larger or equal)
* @param cb function to call for ONE unfinished item
* @param cb_cls closure for @a cb
* @return #GNUNET_OK on success,
* #GNUNET_NO if there are no entries,
* #GNUNET_SYSERR on DB errors
*/
int
(*select_payback_above_serial_id)(void *cls,
struct TALER_EXCHANGEDB_Session *session,
uint64_t serial_id,
TALER_EXCHANGEDB_PaybackCallback cb,
void *cb_cls);
/** /**
* Function called to add a request for an emergency payback for a * Function called to add a request for an emergency payback for a
* coin. The funds are to be added back to the reserve. The * coin. The funds are to be added back to the reserve. The