implement returning /paybacks as part of reserve history (#3887)

This commit is contained in:
Christian Grothoff 2017-04-02 18:02:07 +02:00
parent 94dddbbe82
commit d8542d729a
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 126 additions and 12 deletions

View File

@ -2367,6 +2367,7 @@ TEH_DB_execute_payback (struct MHD_Connection *connection,
coin_sig, coin_sig,
coin_blind, coin_blind,
&amount, &amount,
h_blind,
&payback_deadline); &payback_deadline);
if (GNUNET_SYSERR == ret) if (GNUNET_SYSERR == ret)
{ {

View File

@ -32,6 +32,7 @@ common_free_reserve_history (void *cls,
{ {
struct TALER_EXCHANGEDB_BankTransfer *bt; struct TALER_EXCHANGEDB_BankTransfer *bt;
struct TALER_EXCHANGEDB_CollectableBlindcoin *cbc; struct TALER_EXCHANGEDB_CollectableBlindcoin *cbc;
struct TALER_EXCHANGEDB_Payback *payback;
struct TALER_EXCHANGEDB_ReserveHistory *backref; struct TALER_EXCHANGEDB_ReserveHistory *backref;
while (NULL != rh) while (NULL != rh)
@ -54,7 +55,9 @@ common_free_reserve_history (void *cls,
GNUNET_free (cbc); GNUNET_free (cbc);
break; break;
case TALER_EXCHANGEDB_RO_PAYBACK_COIN: case TALER_EXCHANGEDB_RO_PAYBACK_COIN:
GNUNET_free (rh->details.payback); payback = rh->details.payback;
GNUNET_CRYPTO_rsa_public_key_free (payback->denom_pub.rsa_public_key);
GNUNET_free (payback);
break; break;
} }
backref = rh; backref = rh;

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014, 2015, 2016 GNUnet e.V. Copyright (C) 2014, 2015, 2016, 2017 GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software terms of the GNU General Public License as published by the Free Software
@ -220,6 +220,8 @@ postgres_drop_tables (void *cls)
"Dropping ALL tables\n"); "Dropping ALL tables\n");
SQLEXEC_ (conn, SQLEXEC_ (conn,
"DROP TABLE IF EXISTS prewire;"); "DROP TABLE IF EXISTS prewire;");
SQLEXEC_ (conn,
"DROP TABLE IF EXISTS payback;");
SQLEXEC_ (conn, SQLEXEC_ (conn,
"DROP TABLE IF EXISTS aggregation_tracking;"); "DROP TABLE IF EXISTS aggregation_tracking;");
SQLEXEC_ (conn, SQLEXEC_ (conn,
@ -243,7 +245,7 @@ postgres_drop_tables (void *cls)
SQLEXEC_ (conn, SQLEXEC_ (conn,
"DROP TABLE IF EXISTS known_coins CASCADE;"); "DROP TABLE IF EXISTS known_coins CASCADE;");
SQLEXEC_ (conn, SQLEXEC_ (conn,
"DROP TABLE IF EXISTS reserves_out;"); "DROP TABLE IF EXISTS reserves_out CASCADE;");
SQLEXEC_ (conn, SQLEXEC_ (conn,
"DROP TABLE IF EXISTS reserves_in;"); "DROP TABLE IF EXISTS reserves_in;");
SQLEXEC_ (conn, SQLEXEC_ (conn,
@ -521,6 +523,7 @@ postgres_create_tables (void *cls)
",amount_frac INT4 NOT NULL" ",amount_frac INT4 NOT NULL"
",amount_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" ",amount_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
",timestamp INT8 NOT NULL" ",timestamp INT8 NOT NULL"
",h_blind_ev BYTEA NOT NULL REFERENCES reserves_out (h_blind_ev) ON DELETE CASCADE"
")"); ")");
SQLEXEC_INDEX("CREATE INDEX payback_by_coin_index " SQLEXEC_INDEX("CREATE INDEX payback_by_coin_index "
"ON payback(coin_pub)"); "ON payback(coin_pub)");
@ -1410,9 +1413,30 @@ postgres_prepare (PGconn *db_conn)
",amount_frac" ",amount_frac"
",amount_curr" ",amount_curr"
",timestamp" ",timestamp"
",h_blind_ev"
") VALUES " ") VALUES "
"($1, $2, $3, $4, $5, $6, $7, $8)", "($1, $2, $3, $4, $5, $6, $7, $8, $9)",
8, NULL); 9, NULL);
/* Used in #postgres_get_reserve_history() to obtain payback transactions
for a reserve */
PREPARE ("payback_by_reserve",
"SELECT"
" coin_pub"
",coin_sig"
",coin_blind"
",amount_val"
",amount_frac"
",amount_curr"
",timestamp"
",denom.denom_pub"
",denom.denom_sig"
" FROM payback"
" JOIN reserves_out denom USING (h_blind_ev)"
" WHERE payback.reserve_pub=$1",
1, NULL);
/* Used in #postgres_get_reserve_by_h_blind() */ /* Used in #postgres_get_reserve_by_h_blind() */
PREPARE ("reserve_by_h_blind", PREPARE ("reserve_by_h_blind",
@ -2202,6 +2226,7 @@ postgres_get_reserve_history (void *cls,
rh = NULL; rh = NULL;
rh_tail = NULL; rh_tail = NULL;
ret = GNUNET_SYSERR; ret = GNUNET_SYSERR;
/** #TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE */
{ {
struct TALER_EXCHANGEDB_BankTransfer *bt; struct TALER_EXCHANGEDB_BankTransfer *bt;
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
@ -2265,6 +2290,7 @@ postgres_get_reserve_history (void *cls,
} /* end of 'while (0 < rows)' */ } /* end of 'while (0 < rows)' */
PQclear (result); PQclear (result);
} }
/** #TALER_EXCHANGEDB_RO_WITHDRAW_COIN */
{ {
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (reserve_pub), GNUNET_PQ_query_param_auto_from_type (reserve_pub),
@ -2325,6 +2351,74 @@ postgres_get_reserve_history (void *cls,
ret = GNUNET_OK; ret = GNUNET_OK;
PQclear (result); PQclear (result);
} }
/** #TALER_EXCHANGEDB_RO_PAYBACK_COIN */
{
struct TALER_EXCHANGEDB_Payback *payback;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (reserve_pub),
GNUNET_PQ_query_param_end
};
result = GNUNET_PQ_exec_prepared (session->conn,
"payback_by_reserve",
params);
if (PGRES_TUPLES_OK != PQresultStatus (result))
{
QUERY_ERR (result);
goto cleanup;
}
rows = PQntuples (result);
while (0 < rows)
{
payback = GNUNET_new (struct TALER_EXCHANGEDB_Payback);
{
struct GNUNET_PQ_ResultSpec rs[] = {
TALER_PQ_result_spec_amount ("amount",
&payback->value),
GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
&payback->coin_pub),
GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
&payback->coin_blind),
GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
&payback->coin_sig),
GNUNET_PQ_result_spec_absolute_time ("timestamp",
&payback->timestamp),
GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
&payback->denom_pub.rsa_public_key),
GNUNET_PQ_result_spec_end
};
if (GNUNET_OK !=
GNUNET_PQ_extract_result (result,
rs,
--rows))
{
GNUNET_break (0);
GNUNET_free (payback);
PQclear (result);
goto cleanup;
}
}
payback->reserve_pub = *reserve_pub;
if (NULL != rh_tail)
{
rh_tail->next = GNUNET_new (struct TALER_EXCHANGEDB_ReserveHistory);
rh_tail = rh_tail->next;
}
else
{
rh_tail = GNUNET_new (struct TALER_EXCHANGEDB_ReserveHistory);
rh = rh_tail;
}
rh_tail->type = TALER_EXCHANGEDB_RO_PAYBACK_COIN;
rh_tail->details.payback = payback;
} /* end of 'while (0 < rows)' */
PQclear (result);
}
/** #TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK */
/* TODO: #4956 */
cleanup: cleanup:
if (GNUNET_SYSERR == ret) if (GNUNET_SYSERR == ret)
{ {
@ -5453,6 +5547,7 @@ postgres_select_wire_out_above_serial_id (void *cls,
* @param coin_blind blinding key of the coin * @param coin_blind blinding key of the coin
* @param amount total amount to be paid back * @param amount total amount to be paid back
* @param receiver_account_details who should receive the funds * @param receiver_account_details who should receive the funds
* @parma h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry)
* @param[out] deadline set to absolute time by when the exchange plans to pay it back * @param[out] deadline set to absolute time by when the exchange plans to pay it back
* @return #GNUNET_OK on success, * @return #GNUNET_OK on success,
* #GNUNET_SYSERR on DB errors * #GNUNET_SYSERR on DB errors
@ -5465,6 +5560,7 @@ postgres_insert_payback_request (void *cls,
const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_CoinSpendSignatureP *coin_sig,
const struct TALER_DenominationBlindingKeyP *coin_blind, const struct TALER_DenominationBlindingKeyP *coin_blind,
const struct TALER_Amount *amount, const struct TALER_Amount *amount,
const struct GNUNET_HashCode *h_blind_ev,
struct GNUNET_TIME_Absolute *deadline) struct GNUNET_TIME_Absolute *deadline)
{ {
PGresult *result; PGresult *result;
@ -5478,6 +5574,7 @@ postgres_insert_payback_request (void *cls,
GNUNET_PQ_query_param_auto_from_type (coin_blind), GNUNET_PQ_query_param_auto_from_type (coin_blind),
TALER_PQ_query_param_amount (amount), TALER_PQ_query_param_amount (amount),
GNUNET_PQ_query_param_absolute_time (&now), GNUNET_PQ_query_param_absolute_time (&now),
GNUNET_PQ_query_param_auto_from_type (h_blind_ev),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };

View File

@ -153,14 +153,9 @@ struct TALER_EXCHANGEDB_Payback
{ {
/** /**
* Which coin was paid back? * Public key of the coin that was paid back.
*/ */
struct TALER_CoinPublicInfo coin; struct TALER_CoinSpendPublicKeyP coin_pub;
/**
* How much was the coin still worth at this time?
*/
struct TALER_Amount value;
/** /**
* Blinding factor supplied to prove to the exchange that * Blinding factor supplied to prove to the exchange that
@ -179,6 +174,22 @@ struct TALER_EXCHANGEDB_Payback
*/ */
struct TALER_ReservePublicKeyP reserve_pub; struct TALER_ReservePublicKeyP reserve_pub;
/**
* How much was the coin still worth at this time?
*/
struct TALER_Amount value;
/**
* When did the /payback operation happen?
*/
struct GNUNET_TIME_Absolute timestamp;
/**
* Public key representing the denomination of
* @e coin_pub.
*/
struct TALER_DenominationPublicKey denom_pub;
}; };
@ -1944,6 +1955,7 @@ struct TALER_EXCHANGEDB_Plugin
* @param h_blind_ev blinded envelope, as calculated by the exchange * @param h_blind_ev blinded envelope, as calculated by the exchange
* @param amount total amount to be paid back * @param amount total amount to be paid back
* @param receiver_account_details who should receive the funds * @param receiver_account_details who should receive the funds
* @parma h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry)
* @param[out] deadline set to absolute time by when the exchange plans to pay it back * @param[out] deadline set to absolute time by when the exchange plans to pay it back
* @return #GNUNET_OK on success, * @return #GNUNET_OK on success,
* #GNUNET_SYSERR on DB errors * #GNUNET_SYSERR on DB errors
@ -1956,6 +1968,7 @@ struct TALER_EXCHANGEDB_Plugin
const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_CoinSpendSignatureP *coin_sig,
const struct TALER_DenominationBlindingKeyP *coin_blind, const struct TALER_DenominationBlindingKeyP *coin_blind,
const struct TALER_Amount *amount, const struct TALER_Amount *amount,
const struct GNUNET_HashCode *h_blind_ev,
struct GNUNET_TIME_Absolute *deadline); struct GNUNET_TIME_Absolute *deadline);