extending postgres plugin with functions required to store payback data on refreshed coins for #5777

This commit is contained in:
Christian Grothoff 2019-07-21 20:15:11 +02:00
parent bafe0c772a
commit 721c1ee73e
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
3 changed files with 743 additions and 165 deletions

View File

@ -99,6 +99,9 @@ common_free_coin_transaction_list (void *cls,
GNUNET_CRYPTO_rsa_signature_free (list->details.melt->session.coin.denom_sig.rsa_signature);
GNUNET_free (list->details.melt);
break;
case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK:
GNUNET_free (list->details.old_coin_payback);
break;
case TALER_EXCHANGEDB_TT_REFUND:
if (NULL != list->details.refund->coin.denom_sig.rsa_signature)
GNUNET_CRYPTO_rsa_signature_free (list->details.refund->coin.denom_sig.rsa_signature);
@ -109,6 +112,9 @@ common_free_coin_transaction_list (void *cls,
GNUNET_CRYPTO_rsa_signature_free (list->details.payback->coin.denom_sig.rsa_signature);
GNUNET_free (list->details.payback);
break;
case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH:
GNUNET_free (list->details.payback_refresh);
break;
}
GNUNET_free (list);
list = next;

View File

@ -115,6 +115,7 @@ postgres_drop_tables (void *cls)
GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS kyc_merchants CASCADE;"),
GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS prewire CASCADE;"),
GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS payback CASCADE;"),
GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS payback_refresh CASCADE;"),
GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS aggregation_tracking CASCADE;"),
GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS wire_out CASCADE;"),
GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS wire_fee CASCADE;"),
@ -317,7 +318,7 @@ postgres_create_tables (void *cls)
",newcoin_index INT4 NOT NULL"
",link_sig BYTEA NOT NULL CHECK(LENGTH(link_sig)=64)"
",denom_pub_hash BYTEA NOT NULL REFERENCES denominations (denom_pub_hash) ON DELETE CASCADE"
",coin_ev BYTEA NOT NULL"
",coin_ev BYTEA UNIQUE NOT NULL"
",ev_sig BYTEA NOT NULL"
",PRIMARY KEY (rc, newcoin_index)"
");"),
@ -449,6 +450,27 @@ postgres_create_tables (void *cls)
GNUNET_PQ_make_try_execute("CREATE INDEX payback_for_by_reserve "
"ON payback(coin_pub,denom_pub_hash,h_blind_ev);"),
/* Table for /payback-refresh information */
GNUNET_PQ_make_execute("CREATE TABLE IF NOT EXISTS payback_refresh "
"(payback_refresh_uuid BIGSERIAL UNIQUE"
",coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub)" /* do NOT CASCADE on delete, we may keep the coin alive! */
",coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)"
",coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)"
",amount_val INT8 NOT NULL"
",amount_frac INT4 NOT NULL"
",amount_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
",timestamp INT8 NOT NULL"
",h_blind_ev BYTEA NOT NULL REFERENCES refresh_revealed_coins (coin_ev) ON DELETE CASCADE"
");"),
GNUNET_PQ_make_try_execute("CREATE INDEX payback_refresh_by_coin_index "
"ON payback_refresh(coin_pub);"),
GNUNET_PQ_make_try_execute("CREATE INDEX payback_refresh_by_h_blind_ev "
"ON payback_refresh(h_blind_ev);"),
GNUNET_PQ_make_try_execute("CREATE INDEX payback_refresh_by_reserve_index "
"ON payback_refresh(reserve_pub);"),
GNUNET_PQ_make_try_execute("CREATE INDEX payback_refresh_for_by_reserve "
"ON payback_refresh(coin_pub,denom_pub_hash,h_blind_ev);"),
/* This table contains the pre-commit data for
wire transfers the exchange is about to execute. */
GNUNET_PQ_make_execute("CREATE TABLE IF NOT EXISTS prewire "
@ -658,7 +680,7 @@ postgres_prepare (PGconn *db_conn)
") VALUES "
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);",
10),
/* Used in #postgres_reserves_update() when the reserve is updated */
/* Used in #reserves_update() when the reserve is updated */
GNUNET_PQ_make_prepare ("reserve_update",
"UPDATE reserves"
" SET"
@ -1521,6 +1543,21 @@ postgres_prepare (PGconn *db_conn)
") VALUES "
"($1, $2, $3, $4, $5, $6, $7, $8);",
8),
/* Used in #postgres_insert_payback_request() to store payback-refresh
information */
GNUNET_PQ_make_prepare ("payback_refresh_insert",
"INSERT INTO payback_refresh "
"(coin_pub"
",coin_sig"
",coin_blind"
",amount_val"
",amount_frac"
",amount_curr"
",timestamp"
",h_blind_ev"
") VALUES "
"($1, $2, $3, $4, $5, $6, $7, $8);",
8),
/* Used in #postgres_select_payback_above_serial_id() to obtain payback transactions */
GNUNET_PQ_make_prepare ("payback_get_incr",
"SELECT"
@ -1547,6 +1584,35 @@ postgres_prepare (PGconn *db_conn)
" WHERE payback_uuid>=$1"
" ORDER BY payback_uuid ASC;",
1),
/* Used in #postgres_select_payback_refresh_above_serial_id() to obtain
payback-refresh transactions */
GNUNET_PQ_make_prepare ("payback_refresh_get_incr",
"SELECT"
" payback_refresh_uuid"
",timestamp"
",rc.old_coin_pub"
",coin_pub"
",coin_sig"
",coin_blind"
",h_blind_ev"
",coins.denom_pub_hash"
",denoms.denom_pub"
",coins.denom_sig"
",amount_val"
",amount_frac"
",amount_curr"
" FROM payback_refresh"
" JOIN refresh_revealed_coins rrc"
" ON (rrc.coin_ev = h_blind_ev)"
" JOIN refresh_commitments rc"
" ON (rrc.rc = rc.rc)"
" JOIN known_coins coins"
" USING (coin_pub)"
" JOIN denominations denoms"
" ON (coins.denom_pub_hash = denoms.denom_pub_hash)"
" WHERE payback_refresh_uuid>=$1"
" ORDER BY payback_refresh_uuid ASC;",
1),
/* Used in #postgres_select_reserve_closed_above_serial_id() to
obtain information about closed reserves */
GNUNET_PQ_make_prepare ("reserves_close_get_incr",
@ -1587,6 +1653,29 @@ postgres_prepare (PGconn *db_conn)
" WHERE ro.reserve_pub=$1"
" FOR UPDATE;",
1),
/* Used in #postgres_get_coin_transactions() to obtain payback transactions
affecting old coins of refreshed coins */
GNUNET_PQ_make_prepare ("payback_by_old_coin",
"SELECT"
" pr.coin_pub"
",pr.coin_sig"
",pr.coin_blind"
",pr.amount_val"
",pr.amount_frac"
",pr.amount_curr"
",pr.timestamp"
",coins.denom_pub_hash"
",coins.denom_sig"
" FROM refresh_commitments"
" JOIN refresh_revealed_coins rrc"
" USING (rc)"
" JOIN payback_refresh pr"
" ON (rrc.coin_ev = pr.h_blind_ev)"
" JOIN known_coins coins"
" ON (coins.coin_pub = pr.coin_pub)"
" WHERE old_coin_pub=$1"
" FOR UPDATE;",
1),
/* Used in #postgres_get_reserve_history() */
GNUNET_PQ_make_prepare ("close_by_reserve",
"SELECT"
@ -1637,7 +1726,31 @@ postgres_prepare (PGconn *db_conn)
" USING (coin_pub)"
" JOIN reserves_out ro"
" USING (h_blind_ev)"
" WHERE payback.coin_pub=$1;",
" WHERE payback.coin_pub=$1"
" FOR UPDATE;",
1),
/* Used in #postgres_get_coin_transactions() to obtain payback transactions
for a refreshed coin */
GNUNET_PQ_make_prepare ("payback_by_refreshed_coin",
"SELECT"
" rc.old_coin_pub"
",coin_sig"
",coin_blind"
",amount_val"
",amount_frac"
",amount_curr"
",timestamp"
",coins.denom_pub_hash"
",coins.denom_sig"
" FROM payback_refresh"
" JOIN refresh_revealed_coins rrc"
" ON (rrc.coin_ev = h_blind_ev)"
" JOIN refresh_commitments rc"
" ON (rrc.rc = rc.rc)"
" JOIN known_coins coins"
" USING (coin_pub)"
" WHERE coin_pub=$1"
" FOR UPDATE;",
1),
/* Used in #postgres_get_reserve_by_h_blind() */
GNUNET_PQ_make_prepare ("reserve_by_h_blind",
@ -4462,6 +4575,67 @@ add_coin_refund (void *cls,
}
/**
* Function to be called with the results of a SELECT statement
* that has returned @a num_results results.
*
* @param cls closure of type `struct CoinHistoryContext`
* @param result the postgres result
* @param num_result the number of results in @a result
*/
static void
add_old_coin_payback (void *cls,
PGresult *result,
unsigned int num_results)
{
struct CoinHistoryContext *chc = cls;
for (unsigned int i=0;i<num_results;i++)
{
struct TALER_EXCHANGEDB_PaybackRefresh *payback;
struct TALER_EXCHANGEDB_TransactionList *tl;
payback = GNUNET_new (struct TALER_EXCHANGEDB_PaybackRefresh);
{
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
&payback->coin.coin_pub),
GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
&payback->coin_sig),
GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
&payback->coin_blind),
TALER_PQ_result_spec_amount ("amount",
&payback->value),
TALER_PQ_result_spec_absolute_time ("timestamp",
&payback->timestamp),
GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
&payback->coin.denom_pub_hash),
GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
&payback->coin.denom_sig.rsa_signature),
GNUNET_PQ_result_spec_end
};
if (GNUNET_OK !=
GNUNET_PQ_extract_result (result,
rs,
i))
{
GNUNET_break (0);
GNUNET_free (payback);
chc->status = GNUNET_DB_STATUS_HARD_ERROR;
return;
}
payback->old_coin_pub = *chc->coin_pub;
}
tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
tl->next = chc->head;
tl->type = TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK;
tl->details.old_coin_payback = payback;
chc->head = tl;
}
}
/**
* Function to be called with the results of a SELECT statement
* that has returned @a num_results results.
@ -4523,6 +4697,67 @@ add_coin_payback (void *cls,
}
/**
* Function to be called with the results of a SELECT statement
* that has returned @a num_results results.
*
* @param cls closure of type `struct CoinHistoryContext`
* @param result the postgres result
* @param num_result the number of results in @a result
*/
static void
add_coin_payback_refresh (void *cls,
PGresult *result,
unsigned int num_results)
{
struct CoinHistoryContext *chc = cls;
for (unsigned int i=0;i<num_results;i++)
{
struct TALER_EXCHANGEDB_PaybackRefresh *payback;
struct TALER_EXCHANGEDB_TransactionList *tl;
payback = GNUNET_new (struct TALER_EXCHANGEDB_PaybackRefresh);
{
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
&payback->old_coin_pub),
GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
&payback->coin_sig),
GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
&payback->coin_blind),
TALER_PQ_result_spec_amount ("amount",
&payback->value),
TALER_PQ_result_spec_absolute_time ("timestamp",
&payback->timestamp),
GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
&payback->coin.denom_pub_hash),
GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
&payback->coin.denom_sig.rsa_signature),
GNUNET_PQ_result_spec_end
};
if (GNUNET_OK !=
GNUNET_PQ_extract_result (result,
rs,
i))
{
GNUNET_break (0);
GNUNET_free (payback);
chc->status = GNUNET_DB_STATUS_HARD_ERROR;
return;
}
payback->coin.coin_pub = *chc->coin_pub;
}
tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
tl->next = chc->head;
tl->type = TALER_EXCHANGEDB_TT_PAYBACK_REFRESH;
tl->details.payback_refresh = payback;
chc->head = tl;
}
}
/**
* Work we need to do.
*/
@ -4541,8 +4776,8 @@ struct Work
/**
* Compile a list of all (historic) transactions performed
* with the given coin (/refresh/melt, /deposit and /refund operations).
* Compile a list of all (historic) transactions performed with the given coin
* (/refresh/melt, /deposit, /refund and /payback operations).
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param session database connection
@ -4567,6 +4802,9 @@ postgres_get_coin_transactions (void *cls,
/** #TALER_EXCHANGEDB_TT_REFUND */
{ "get_refunds_by_coin",
&add_coin_refund },
/** #TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK */
{ "payback_by_old_coin",
&add_old_coin_payback },
{ NULL, NULL }
};
static const struct Work work_wp[] = {
@ -4579,9 +4817,15 @@ postgres_get_coin_transactions (void *cls,
/** #TALER_EXCHANGEDB_TT_REFUND */
{ "get_refunds_by_coin",
&add_coin_refund },
/** #TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK */
{ "payback_by_old_coin",
&add_old_coin_payback },
/** #TALER_EXCHANGEDB_TT_PAYBACK */
{ "payback_by_coin",
&add_coin_payback },
/** #TALER_EXCHANGEDB_TT_PAYBACK_REFRESH */
{ "payback_by_refreshed_coin",
&add_coin_payback_refresh },
{ NULL, NULL }
};
struct CoinHistoryContext chc;
@ -6477,6 +6721,147 @@ postgres_select_payback_above_serial_id (void *cls,
}
/**
* Closure for #payback_refresh_serial_helper_cb().
*/
struct PaybackRefreshSerialContext
{
/**
* Callback to call.
*/
TALER_EXCHANGEDB_PaybackRefreshCallback cb;
/**
* Closure for @e cb.
*/
void *cb_cls;
/**
* Status code, set to #GNUNET_SYSERR on hard errors.
*/
int status;
};
/**
* Helper function to be called with the results of a SELECT statement
* that has returned @a num_results results.
*
* @param cls closure of type `struct PaybackRefreshSerialContext`
* @param result the postgres result
* @param num_result the number of results in @a result
*/
static void
payback_refresh_serial_helper_cb (void *cls,
PGresult *result,
unsigned int num_results)
{
struct PaybackRefreshSerialContext *psc = cls;
for (unsigned int i=0;i<num_results;i++)
{
uint64_t rowid;
struct TALER_CoinSpendPublicKeyP old_coin_pub;
struct TALER_CoinPublicInfo coin;
struct TALER_CoinSpendSignatureP coin_sig;
struct TALER_DenominationBlindingKeyP coin_blind;
struct TALER_DenominationPublicKey denom_pub;
struct TALER_Amount amount;
struct GNUNET_HashCode h_blind_ev;
struct GNUNET_TIME_Absolute timestamp;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint64 ("payback_uuid",
&rowid),
TALER_PQ_result_spec_absolute_time ("timestamp",
&timestamp),
GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
&old_coin_pub),
GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
&coin.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_auto_from_type ("denom_pub_hash",
&coin.denom_pub_hash),
GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
&denom_pub.rsa_public_key),
GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
&coin.denom_sig.rsa_signature),
TALER_PQ_result_spec_amount ("amount",
&amount),
GNUNET_PQ_result_spec_end
};
int ret;
if (GNUNET_OK !=
GNUNET_PQ_extract_result (result,
rs,
i))
{
GNUNET_break (0);
psc->status = GNUNET_SYSERR;
return;
}
ret = psc->cb (psc->cb_cls,
rowid,
timestamp,
&amount,
&old_coin_pub,
&coin,
&denom_pub,
&coin_sig,
&coin_blind);
GNUNET_PQ_cleanup_result (rs);
if (GNUNET_OK != ret)
break;
}
}
/**
* Function called to select payback requests the exchange received for
* refreshed coins, 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 transaction status code
*/
static enum GNUNET_DB_QueryStatus
postgres_select_payback_refresh_above_serial_id (void *cls,
struct TALER_EXCHANGEDB_Session *session,
uint64_t serial_id,
TALER_EXCHANGEDB_PaybackRefreshCallback cb,
void *cb_cls)
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_uint64 (&serial_id),
GNUNET_PQ_query_param_end
};
struct PaybackRefreshSerialContext psc = {
.cb = cb,
.cb_cls = cb_cls,
.status = GNUNET_OK
};
enum GNUNET_DB_QueryStatus qs;
qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
"payback_refresh_get_incr",
params,
&payback_refresh_serial_helper_cb,
&psc);
if (GNUNET_OK != psc.status)
return GNUNET_DB_STATUS_HARD_ERROR;
return qs;
}
/**
* Closure for #reserve_closed_serial_helper_cb().
*/
@ -6649,13 +7034,6 @@ postgres_insert_payback_request (void *cls,
};
enum GNUNET_DB_QueryStatus qs;
#if 0
/* check if the coin is already known */
if (0 > (qs = postgres_ensure_coin_known (cls,
session,
coin)))
return qs;
#endif
/* now store actual payback information */
qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
"payback_insert",
@ -6700,6 +7078,57 @@ postgres_insert_payback_request (void *cls,
}
/**
* Function called to add a request for an emergency payback for a
* refreshed coin. The funds are to be added back to the original coin
* (which is implied via @a h_blind_ev, see the prepared statement
* "payback_by_old_coin" used in #postgres_get_coin_transactions()).
*
* @param cls closure
* @param session database connection
* @param coin public information about the refreshed coin
* @param coin_sig signature of the coin of type #TALER_SIGNATURE_WALLET_COIN_PAYBACK
* @param coin_blind blinding key of the coin
* @param h_blind_ev blinded envelope, as calculated by the exchange
* @param amount total amount to be paid back
* @param h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry)
* @param timestamp a timestamp to store
* @return transaction result status
*/
static enum GNUNET_DB_QueryStatus
postgres_insert_payback_refresh_request (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct TALER_CoinPublicInfo *coin,
const struct TALER_CoinSpendSignatureP *coin_sig,
const struct TALER_DenominationBlindingKeyP *coin_blind,
const struct TALER_Amount *amount,
const struct GNUNET_HashCode *h_blind_ev,
struct GNUNET_TIME_Absolute timestamp)
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub),
GNUNET_PQ_query_param_auto_from_type (coin_sig),
GNUNET_PQ_query_param_auto_from_type (coin_blind),
TALER_PQ_query_param_amount (amount),
TALER_PQ_query_param_absolute_time (&timestamp),
GNUNET_PQ_query_param_auto_from_type (h_blind_ev),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
/* now store actual payback information */
qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
"payback_refresh_insert",
params);
if (0 > qs)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
return qs;
}
return qs;
}
/**
* Obtain information about which reserve a coin was generated
* from given the hash of the blinded coin.
@ -7325,10 +7754,14 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &postgres_select_wire_out_above_serial_id_by_account;
plugin->select_payback_above_serial_id
= &postgres_select_payback_above_serial_id;
plugin->select_payback_refresh_above_serial_id
= &postgres_select_payback_refresh_above_serial_id;
plugin->select_reserve_closed_above_serial_id
= &postgres_select_reserve_closed_above_serial_id;
plugin->insert_payback_request
= &postgres_insert_payback_request;
plugin->insert_payback_refresh_request
= &postgres_insert_payback_refresh_request;
plugin->get_reserve_by_h_blind
= &postgres_get_reserve_by_h_blind;
plugin->insert_denomination_revocation

View File

@ -233,6 +233,47 @@ struct TALER_EXCHANGEDB_Payback
};
/**
* Information the exchange records about a /payback-refresh request.
*/
struct TALER_EXCHANGEDB_PaybackRefresh
{
/**
* Information about the coin that was paid back.
*/
struct TALER_CoinPublicInfo coin;
/**
* Blinding factor supplied to prove to the exchange that
* the coin came from this reserve.
*/
struct TALER_DenominationBlindingKeyP coin_blind;
/**
* Signature of the coin of type
* #TALER_SIGNATURE_WALLET_COIN_PAYBACK.
*/
struct TALER_CoinSpendSignatureP coin_sig;
/**
* Public key of the old coin that the refresh'ed coin was paid back to.
*/
struct TALER_CoinSpendPublicKeyP old_coin_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;
};
/**
* @brief Types of operations on a reserve.
*/
@ -571,10 +612,20 @@ enum TALER_EXCHANGEDB_TransactionType {
*/
TALER_EXCHANGEDB_TT_REFUND = 2,
/**
* /payback-refresh operation (on the old coin, adding to the old coin's value)
*/
TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK = 3,
/**
* /payback operation.
*/
TALER_EXCHANGEDB_TT_PAYBACK = 3
TALER_EXCHANGEDB_TT_PAYBACK = 4,
/**
* /payback-refresh operation (on the new coin, eliminating its value)
*/
TALER_EXCHANGEDB_TT_PAYBACK_REFRESH = 5
};
@ -603,24 +654,42 @@ struct TALER_EXCHANGEDB_TransactionList
/**
* Details if transaction was a /deposit operation.
* (#TALER_EXCHANGEDB_TT_DEPOSIT)
*/
struct TALER_EXCHANGEDB_Deposit *deposit;
/**
* Details if transaction was a /refresh/melt operation.
* (#TALER_EXCHANGEDB_TT_REFRESH_MELT)
*/
struct TALER_EXCHANGEDB_RefreshMelt *melt;
/**
* Details if transaction was a /refund operation.
* (#TALER_EXCHANGEDB_TT_REFUND)
*/
struct TALER_EXCHANGEDB_Refund *refund;
/**
* Details if transaction was a /payback-refund operation where
* this coin was the OLD coin.
* (#TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK).
*/
struct TALER_EXCHANGEDB_PaybackRefresh *old_coin_payback;
/**
* Details if transaction was a /payback operation.
* (#TALER_EXCHANGEDB_TT_PAYBACK)
*/
struct TALER_EXCHANGEDB_Payback *payback;
/**
* Details if transaction was a /payback-refund operation where
* this coin was the REFRESHED coin.
* (#TALER_EXCHANGEDB_TT_PAYBACK_REFRESH)
*/
struct TALER_EXCHANGEDB_PaybackRefresh *payback_refresh;
} details;
};
@ -1062,6 +1131,35 @@ typedef int
const struct TALER_DenominationBlindingKeyP *coin_blind);
/**
* Function called about paybacks on refreshed coins the exchange has to
* perform.
*
* @param cls closure
* @param rowid row identifier used to uniquely identify the payback operation
* @param timestamp when did we receive the payback request
* @param amount how much should be added back to the reserve
* @param old_coin_pub original coin that was refreshed to create @a coin
* @param coin public information about the coin
* @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_PAYBACK
* @param coin_blind blinding factor used to blind the coin
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
typedef int
(*TALER_EXCHANGEDB_PaybackRefreshCallback)(void *cls,
uint64_t rowid,
struct GNUNET_TIME_Absolute timestamp,
const struct TALER_Amount *amount,
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
const struct TALER_CoinPublicInfo *coin,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_CoinSpendSignatureP *coin_sig,
const struct TALER_DenominationBlindingKeyP *coin_blind);
/**
* Function called about reserve closing operations
* the aggregator triggered.
@ -2222,6 +2320,25 @@ struct TALER_EXCHANGEDB_Plugin
void *cb_cls);
/**
* Function called to select payback requests the exchange received for
* refreshed coins, 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 transaction status code
*/
enum GNUNET_DB_QueryStatus
(*select_payback_refresh_above_serial_id)(void *cls,
struct TALER_EXCHANGEDB_Session *session,
uint64_t serial_id,
TALER_EXCHANGEDB_PaybackRefreshCallback cb,
void *cb_cls);
/**
* Function called to select reserve close operations the aggregator
* triggered, ordered by serial ID (monotonically increasing).
@ -2243,10 +2360,7 @@ struct TALER_EXCHANGEDB_Plugin
/**
* Function called to add a request for an emergency payback for a
* coin. The funds are to be added back to the reserve. The
* function should return the @a deadline by which the exchange will
* trigger a wire transfer back to the customer's account for the
* reserve.
* coin. The funds are to be added back to the reserve.
*
* @param cls closure
* @param session database connection
@ -2256,9 +2370,8 @@ struct TALER_EXCHANGEDB_Plugin
* @param coin_blind blinding key of the coin
* @param h_blind_ev blinded envelope, as calculated by the exchange
* @param amount total amount to be paid back
* @param receiver_account_details who should receive the funds
* @param h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry)
* @param now timestamp to store
* @param timestamp the timestamp to store
* @return transaction result status
*/
enum GNUNET_DB_QueryStatus
@ -2273,6 +2386,32 @@ struct TALER_EXCHANGEDB_Plugin
struct GNUNET_TIME_Absolute timestamp);
/**
* Function called to add a request for an emergency payback for a
* refreshed coin. The funds are to be added back to the original coin.
*
* @param cls closure
* @param session database connection
* @param coin public information about the refreshed coin
* @param coin_sig signature of the coin of type #TALER_SIGNATURE_WALLET_COIN_PAYBACK
* @param coin_blind blinding key of the coin
* @param h_blind_ev blinded envelope, as calculated by the exchange
* @param amount total amount to be paid back
* @param h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry)
* @param timestamp a timestamp to store
* @return transaction result status
*/
enum GNUNET_DB_QueryStatus
(*insert_payback_refresh_request)(void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct TALER_CoinPublicInfo *coin,
const struct TALER_CoinSpendSignatureP *coin_sig,
const struct TALER_DenominationBlindingKeyP *coin_blind,
const struct TALER_Amount *amount,
const struct GNUNET_HashCode *h_blind_ev,
struct GNUNET_TIME_Absolute timestamp);
/**
* Obtain information about which reserve a coin was generated
* from given the hash of the blinded coin.