-towards coin audits with purse deposits
This commit is contained in:
parent
70a5ceecc1
commit
58a0882909
@ -1 +1 @@
|
||||
1655064974
|
||||
1655124520
|
||||
|
@ -113,7 +113,7 @@ currency = TESTKUDOS
|
||||
[merchant-exchange-default]
|
||||
CURRENCY = TESTKUDOS
|
||||
EXCHANGE_BASE_URL = http://localhost:8081/
|
||||
MASTER_KEY = QRZFN2H2C1FANGHV76FBN11ESTK72VFCG3BVSRZA6PHJNT9WG3SG
|
||||
MASTER_KEY = GPB1CSPV6E49MET2PX6BFWVBGFF8BAE14M05RJB54C28EY1HX42G
|
||||
|
||||
[merchant-account-merchant]
|
||||
ACTIVE_default = YES
|
||||
@ -157,7 +157,7 @@ CONFIG = postgres:///auditor-basedb
|
||||
[exchange]
|
||||
LOOKAHEAD_SIGN = 32 weeks 1 day
|
||||
SIGNKEY_DURATION = 4 weeks
|
||||
MASTER_PUBLIC_KEY = QRZFN2H2C1FANGHV76FBN11ESTK72VFCG3BVSRZA6PHJNT9WG3SG
|
||||
MASTER_PUBLIC_KEY = GPB1CSPV6E49MET2PX6BFWVBGFF8BAE14M05RJB54C28EY1HX42G
|
||||
SIGNKEY_LEGAL_DURATION = 4 weeks
|
||||
UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http
|
||||
|
||||
@ -175,7 +175,7 @@ DATABASE = postgres:///auditor-basedb
|
||||
CONFIG = postgres:///auditor-basedb
|
||||
|
||||
[auditor]
|
||||
PUBLIC_KEY = X25D3Y3K4SJZHP3KPP48R3PM9ZSYCEVEZK1SBXAMCRTTGN6CV32G
|
||||
PUBLIC_KEY = FBVV6V14GCCR95X2W2PMCBTFYZ4S3SX3JN504M8SJTMK1JBBV99G
|
||||
TINY_AMOUNT = TESTKUDOS:0.01
|
||||
BASE_URL = http://localhost:8083/
|
||||
|
||||
|
@ -1 +1 @@
|
||||
QRZFN2H2C1FANGHV76FBN11ESTK72VFCG3BVSRZA6PHJNT9WG3SG
|
||||
GPB1CSPV6E49MET2PX6BFWVBGFF8BAE14M05RJB54C28EY1HX42G
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -61,6 +61,11 @@ struct TALER_AuditorPublicKeyP TALER_ARL_auditor_pub;
|
||||
*/
|
||||
char *TALER_ARL_auditor_url;
|
||||
|
||||
/**
|
||||
* REST API endpoint of the exchange.
|
||||
*/
|
||||
char *TALER_ARL_exchange_url;
|
||||
|
||||
/**
|
||||
* At what time did the auditor process start?
|
||||
*/
|
||||
@ -371,10 +376,13 @@ test_master_present (void *cls,
|
||||
{
|
||||
int *found = cls;
|
||||
|
||||
(void) exchange_url;
|
||||
if (0 == GNUNET_memcmp (mpub,
|
||||
&TALER_ARL_master_pub))
|
||||
{
|
||||
*found = GNUNET_YES;
|
||||
GNUNET_free (TALER_ARL_exchange_url);
|
||||
TALER_ARL_exchange_url = GNUNET_strdup (exchange_url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -765,6 +773,7 @@ TALER_ARL_done (json_t *report)
|
||||
JSON_INDENT (2));
|
||||
json_decref (report);
|
||||
}
|
||||
GNUNET_free (TALER_ARL_exchange_url);
|
||||
GNUNET_free (TALER_ARL_auditor_url);
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,11 @@ extern struct TALER_AuditorPublicKeyP TALER_ARL_auditor_pub;
|
||||
*/
|
||||
extern char *TALER_ARL_auditor_url;
|
||||
|
||||
/**
|
||||
* REST API endpoint of the exchange.
|
||||
*/
|
||||
extern char *TALER_ARL_exchange_url;
|
||||
|
||||
/**
|
||||
* At what time did the auditor process start?
|
||||
*/
|
||||
|
@ -1 +1 @@
|
||||
1655066138
|
||||
1655124599
|
||||
|
@ -1 +1 @@
|
||||
RJD4G3ERAWDZRH8W4PMNKB9X75HB3N1A3MFKMHBH4FTAAD71GA90
|
||||
6CF031C2JWXQB98SNHARWSPJMYR8JM26BVDV08CPH63T2M9JXV30
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -115,6 +115,7 @@ static struct Table tables[] = {
|
||||
{ .rt = TALER_EXCHANGEDB_RT_EXTENSIONS},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_EXTENSION_DETAILS },
|
||||
{ .rt = TALER_EXCHANGEDB_RT_PURSE_REQUESTS},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_PURSE_REFUNDS},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_PURSE_MERGES},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_PURSE_DEPOSITS},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_ACCOUNT_MERGES},
|
||||
|
@ -17,9 +17,6 @@
|
||||
* @file auditor/taler-helper-auditor-coins.c
|
||||
* @brief audits coins in an exchange database.
|
||||
* @author Christian Grothoff
|
||||
*
|
||||
* UNDECIDED:
|
||||
* - do we care about checking the 'done' flag in deposit_cb?
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
@ -248,8 +245,9 @@ get_cached_history (const struct TALER_CoinSpendPublicKeyP *coin_pub)
|
||||
{
|
||||
unsigned int i = coin_history_index (coin_pub);
|
||||
|
||||
if (0 == GNUNET_memcmp (coin_pub,
|
||||
&coin_histories[i].coin_pub))
|
||||
if (0 ==
|
||||
GNUNET_memcmp (coin_pub,
|
||||
&coin_histories[i].coin_pub))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Found verification of %s in cache\n",
|
||||
@ -479,7 +477,6 @@ check_coin_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
&tl);
|
||||
if (0 >= qs)
|
||||
return qs;
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_set_zero (value->currency,
|
||||
&refunded));
|
||||
@ -538,6 +535,7 @@ check_coin_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
&pos->details.recoup_refresh->value);
|
||||
break;
|
||||
case TALER_EXCHANGEDB_TT_PURSE_DEPOSIT:
|
||||
/* spent += pos->value */
|
||||
TALER_ARL_amount_add (&spent,
|
||||
&spent,
|
||||
&pos->details.purse_deposit->amount);
|
||||
@ -628,22 +626,22 @@ struct DenominationSummary
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue;
|
||||
|
||||
/**
|
||||
* #GNUNET_YES if this record already existed in the DB.
|
||||
* True if this record already existed in the DB.
|
||||
* Used to decide between insert/update in
|
||||
* #sync_denomination().
|
||||
*/
|
||||
int in_db;
|
||||
bool in_db;
|
||||
|
||||
/**
|
||||
* Should we report an emergency for this denomination, causing it to be
|
||||
* revoked (because more coins were deposited than issued)?
|
||||
*/
|
||||
int report_emergency;
|
||||
bool report_emergency;
|
||||
|
||||
/**
|
||||
* #GNUNET_YES if this denomination was revoked.
|
||||
* True if this denomination was revoked.
|
||||
*/
|
||||
int was_revoked;
|
||||
bool was_revoked;
|
||||
};
|
||||
|
||||
|
||||
@ -695,7 +693,7 @@ init_denomination (const struct TALER_DenominationHashP *denom_hash,
|
||||
}
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
|
||||
{
|
||||
ds->in_db = GNUNET_YES;
|
||||
ds->in_db = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -741,10 +739,10 @@ init_denomination (const struct TALER_DenominationHashP *denom_hash,
|
||||
}
|
||||
else
|
||||
{
|
||||
ds->was_revoked = GNUNET_YES;
|
||||
ds->was_revoked = true;
|
||||
}
|
||||
}
|
||||
return (GNUNET_YES == ds->in_db)
|
||||
return ds->in_db
|
||||
? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
|
||||
: GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
|
||||
}
|
||||
@ -900,7 +898,7 @@ sync_denomination (void *cls,
|
||||
cnt,
|
||||
&ds->denom_risk);
|
||||
}
|
||||
if (GNUNET_YES == ds->report_emergency)
|
||||
if (ds->report_emergency)
|
||||
{
|
||||
/* Value of coins deposited exceed value of coins
|
||||
issued! Also very bad! */
|
||||
@ -1139,13 +1137,13 @@ reveal_data_cb (void *cls,
|
||||
* #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
check_known_coin (const char *operation,
|
||||
const struct
|
||||
TALER_EXCHANGEDB_DenominationKeyInformation *issue,
|
||||
uint64_t rowid,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_DenominationPublicKey *denom_pub,
|
||||
const struct TALER_Amount *loss_potential)
|
||||
check_known_coin (
|
||||
const char *operation,
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue,
|
||||
uint64_t rowid,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_DenominationPublicKey *denom_pub,
|
||||
const struct TALER_Amount *loss_potential)
|
||||
{
|
||||
struct TALER_CoinPublicInfo ci;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
@ -1463,6 +1461,7 @@ refresh_session_cb (void *cls,
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: refactor: repeated logic!
|
||||
if (TALER_ARL_SR_INVALID_NEGATIVE ==
|
||||
TALER_ARL_amount_subtract_neg (&tmp,
|
||||
&dso->denom_balance,
|
||||
@ -1471,7 +1470,7 @@ refresh_session_cb (void *cls,
|
||||
TALER_ARL_amount_add (&dso->denom_loss,
|
||||
&dso->denom_loss,
|
||||
amount_with_fee);
|
||||
dso->report_emergency = GNUNET_YES;
|
||||
dso->report_emergency = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1650,6 +1649,7 @@ deposit_cb (void *cls,
|
||||
{
|
||||
struct TALER_Amount tmp;
|
||||
|
||||
// FIXME: refactor: repeated logic!
|
||||
if (TALER_ARL_SR_INVALID_NEGATIVE ==
|
||||
TALER_ARL_amount_subtract_neg (&tmp,
|
||||
&ds->denom_balance,
|
||||
@ -1658,7 +1658,7 @@ deposit_cb (void *cls,
|
||||
TALER_ARL_amount_add (&ds->denom_loss,
|
||||
&ds->denom_loss,
|
||||
&deposit->amount_with_fee);
|
||||
ds->report_emergency = GNUNET_YES;
|
||||
ds->report_emergency = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1718,6 +1718,7 @@ deposit_cb (void *cls,
|
||||
* @param merchant_sig signature of the merchant
|
||||
* @param h_contract_terms hash of the proposal data known to merchant and customer
|
||||
* @param rtransaction_id refund transaction ID chosen by the merchant
|
||||
* @param full_refund true if the refunds total up to the entire deposited value
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
@ -1730,6 +1731,7 @@ refund_cb (void *cls,
|
||||
const struct TALER_MerchantSignatureP *merchant_sig,
|
||||
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||
uint64_t rtransaction_id,
|
||||
bool full_refund,
|
||||
const struct TALER_Amount *amount_with_fee)
|
||||
{
|
||||
struct CoinContext *cc = cls;
|
||||
@ -1840,6 +1842,153 @@ refund_cb (void *cls,
|
||||
TALER_ARL_amount_add (&total_refund_fee_income,
|
||||
&total_refund_fee_income,
|
||||
&issue->fees.refund);
|
||||
if (full_refund)
|
||||
{
|
||||
TALER_ARL_amount_subtract (&total_deposit_fee_income,
|
||||
&total_deposit_fee_income,
|
||||
&issue->fees.deposit);
|
||||
}
|
||||
if (TALER_ARL_do_abort ())
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about purse refunds that have been made, with
|
||||
* the goal of auditing the purse refund's execution.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param amount_with_fee amount of the deposit into the purse
|
||||
* @param coin_pub coin that is to be refunded the @a given amount_with_fee
|
||||
* @param denom_pub denomination of @a coin_pub
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
purse_refund_coin_cb (
|
||||
void *cls,
|
||||
const struct TALER_Amount *amount_with_fee,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_DenominationPublicKey *denom_pub)
|
||||
{
|
||||
struct CoinContext *cc = cls;
|
||||
|
||||
#if FIXME
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue;
|
||||
struct DenominationSummary *ds;
|
||||
struct TALER_Amount amount_without_fee;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = TALER_ARL_get_denomination_info (denom_pub,
|
||||
&issue,
|
||||
NULL);
|
||||
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
|
||||
{
|
||||
report_row_inconsistency ("purse-refunds",
|
||||
rowid,
|
||||
"denomination key not found");
|
||||
if (TALER_ARL_do_abort ())
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
if (TALER_ARL_SR_INVALID_NEGATIVE ==
|
||||
TALER_ARL_amount_subtract_neg (&amount_without_fee,
|
||||
amount_with_fee,
|
||||
&issue->fees.refund))
|
||||
{
|
||||
report_amount_arithmetic_inconsistency ("refund (fee)",
|
||||
rowid,
|
||||
&amount_without_fee,
|
||||
&issue->fees.refund,
|
||||
-1);
|
||||
if (TALER_ARL_do_abort ())
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Refunding coin %s in denomination `%s' value %s\n",
|
||||
TALER_B2S (coin_pub),
|
||||
GNUNET_h2s (&issue->denom_hash.hash),
|
||||
TALER_amount2s (amount_with_fee));
|
||||
|
||||
/* update coin's denomination balance */
|
||||
ds = get_denomination_summary (cc,
|
||||
issue,
|
||||
&issue->denom_hash);
|
||||
if (NULL == ds)
|
||||
{
|
||||
report_row_inconsistency ("refund",
|
||||
rowid,
|
||||
"denomination key for refunded coin unknown to auditor");
|
||||
}
|
||||
else
|
||||
{
|
||||
TALER_ARL_amount_add (&ds->denom_balance,
|
||||
&ds->denom_balance,
|
||||
&amount_without_fee);
|
||||
TALER_ARL_amount_add (&ds->denom_risk,
|
||||
&ds->denom_risk,
|
||||
&amount_without_fee);
|
||||
TALER_ARL_amount_add (&total_escrow_balance,
|
||||
&total_escrow_balance,
|
||||
&amount_without_fee);
|
||||
TALER_ARL_amount_add (&total_risk,
|
||||
&total_risk,
|
||||
&amount_without_fee);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"New balance of denomination `%s' after refund is %s\n",
|
||||
GNUNET_h2s (&issue->denom_hash.hash),
|
||||
TALER_amount2s (&ds->denom_balance));
|
||||
}
|
||||
/* update total refund fee balance */
|
||||
TALER_ARL_amount_add (&total_refund_fee_income,
|
||||
&total_refund_fee_income,
|
||||
&issue->fees.refund);
|
||||
TALER_ARL_amount_subtract (&total_deposit_fee_income,
|
||||
&total_deposit_fee_income,
|
||||
&issue->fees.deposit);
|
||||
|
||||
#endif
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about a purse that was refunded. Adds the
|
||||
* refunded amounts back to the outstanding balance of the respective
|
||||
* denominations.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid unique serial ID for the refund in our DB
|
||||
* @param purse_pub public key of the purse
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
purse_refund_cb (void *cls,
|
||||
uint64_t rowid,
|
||||
const struct TALER_PurseContractPublicKeyP *purse_pub)
|
||||
{
|
||||
struct CoinContext *cc = cls;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
GNUNET_assert (rowid >= ppc.last_purse_refunds_serial_id); /* should be monotonically increasing */
|
||||
ppc.last_purse_refunds_serial_id = rowid + 1;
|
||||
qs = TALER_ARL_edb->select_purse_deposits_by_purse (TALER_ARL_edb->cls,
|
||||
purse_pub,
|
||||
&purse_refund_coin_cb,
|
||||
cc);
|
||||
if (qs < 0)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (TALER_ARL_do_abort ())
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_OK;
|
||||
@ -1934,7 +2083,7 @@ check_recoup (struct CoinContext *cc,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GNUNET_NO == ds->was_revoked)
|
||||
if (! ds->was_revoked)
|
||||
{
|
||||
/* Woopsie, we allowed recoup on non-revoked denomination!? */
|
||||
TALER_ARL_report (report_bad_sig_losses,
|
||||
@ -2233,9 +2382,131 @@ purse_deposit_cb (
|
||||
const struct TALER_DenominationPublicKey *denom_pub)
|
||||
{
|
||||
struct CoinContext *cc = cls;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
struct TALER_DenominationHashP dh;
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue;
|
||||
struct DenominationSummary *ds;
|
||||
|
||||
GNUNET_break (0); // FIXME: not implemented!
|
||||
return GNUNET_SYSERR;
|
||||
GNUNET_assert (rowid >= ppc.last_purse_deposits_serial_id);
|
||||
ppc.last_purse_deposits_serial_id = rowid + 1;
|
||||
qs = TALER_ARL_get_denomination_info (denom_pub,
|
||||
&issue,
|
||||
&dh);
|
||||
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
|
||||
{
|
||||
report_row_inconsistency ("purse-deposits",
|
||||
rowid,
|
||||
"denomination key not found");
|
||||
if (TALER_ARL_do_abort ())
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
qs = check_known_coin ("purse-deposit",
|
||||
issue,
|
||||
rowid,
|
||||
&deposit->coin_pub,
|
||||
denom_pub,
|
||||
&deposit->amount);
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
cc->qs = qs;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_purse_deposit_verify (
|
||||
NULL != deposit->exchange_base_url
|
||||
? deposit->exchange_base_url
|
||||
: TALER_ARL_exchange_url,
|
||||
&deposit->purse_pub,
|
||||
&deposit->amount,
|
||||
&deposit->coin_pub,
|
||||
&deposit->coin_sig))
|
||||
{
|
||||
TALER_ARL_report (report_bad_sig_losses,
|
||||
GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_string ("operation",
|
||||
"purse-deposit"),
|
||||
GNUNET_JSON_pack_uint64 ("row",
|
||||
rowid),
|
||||
TALER_JSON_pack_amount ("loss",
|
||||
&deposit->amount),
|
||||
GNUNET_JSON_pack_data_auto ("coin_pub",
|
||||
&deposit->coin_pub)));
|
||||
TALER_ARL_amount_add (&total_bad_sig_loss,
|
||||
&total_bad_sig_loss,
|
||||
&deposit->amount);
|
||||
if (TALER_ARL_do_abort ())
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
/* update coin's denomination balance */
|
||||
ds = get_denomination_summary (cc,
|
||||
issue,
|
||||
&issue->denom_hash);
|
||||
if (NULL == ds)
|
||||
{
|
||||
report_row_inconsistency ("purse-deposit",
|
||||
rowid,
|
||||
"denomination key for purse-deposited coin unknown to auditor");
|
||||
}
|
||||
else
|
||||
{
|
||||
struct TALER_Amount tmp;
|
||||
|
||||
// FIXME: refactor: repeated logic!
|
||||
if (TALER_ARL_SR_INVALID_NEGATIVE ==
|
||||
TALER_ARL_amount_subtract_neg (&tmp,
|
||||
&ds->denom_balance,
|
||||
&deposit->amount))
|
||||
{
|
||||
TALER_ARL_amount_add (&ds->denom_loss,
|
||||
&ds->denom_loss,
|
||||
&deposit->amount);
|
||||
ds->report_emergency = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ds->denom_balance = tmp;
|
||||
}
|
||||
if (-1 == TALER_amount_cmp (&total_escrow_balance,
|
||||
&deposit->amount))
|
||||
{
|
||||
/* This can theoretically happen if for example the exchange
|
||||
never issued any coins (i.e. escrow balance is zero), but
|
||||
accepted a forged coin (i.e. emergency situation after
|
||||
private key compromise). In that case, we cannot even
|
||||
subtract the profit we make from the fee from the escrow
|
||||
balance. Tested as part of test-auditor.sh, case #18 */
|
||||
report_amount_arithmetic_inconsistency (
|
||||
"subtracting purse deposit fee from escrow balance",
|
||||
rowid,
|
||||
&total_escrow_balance,
|
||||
&deposit->amount,
|
||||
0);
|
||||
}
|
||||
else
|
||||
{
|
||||
TALER_ARL_amount_subtract (&total_escrow_balance,
|
||||
&total_escrow_balance,
|
||||
&deposit->amount);
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"New balance of denomination `%s' after purse deposit is %s\n",
|
||||
GNUNET_h2s (&issue->denom_hash.hash),
|
||||
TALER_amount2s (&ds->denom_balance));
|
||||
}
|
||||
|
||||
/* update global deposit fees */
|
||||
TALER_ARL_amount_add (&total_deposit_fee_income,
|
||||
&total_deposit_fee_income,
|
||||
&issue->fees.deposit);
|
||||
if (TALER_ARL_do_abort ())
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -2339,6 +2610,20 @@ analyze_coins (void *cls)
|
||||
if (0 > cc.qs)
|
||||
return cc.qs;
|
||||
|
||||
/* process purse_refunds */
|
||||
if (0 >
|
||||
(qs = TALER_ARL_edb->select_purse_refunds_above_serial_id (
|
||||
TALER_ARL_edb->cls,
|
||||
ppc.last_purse_refunds_serial_id,
|
||||
&purse_refund_cb,
|
||||
&cc)))
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return qs;
|
||||
}
|
||||
if (0 > cc.qs)
|
||||
return cc.qs;
|
||||
|
||||
/* process recoups */
|
||||
if (0 >
|
||||
(qs = TALER_ARL_edb->select_recoup_refresh_above_serial_id (
|
||||
@ -2631,8 +2916,11 @@ run (void *cls,
|
||||
GNUNET_JSON_pack_uint64 ("start_ppc_recoup_serial_id",
|
||||
ppc_start.last_recoup_serial_id),
|
||||
GNUNET_JSON_pack_uint64 ("start_ppc_recoup_refresh_serial_id",
|
||||
ppc_start.
|
||||
last_recoup_refresh_serial_id),
|
||||
ppc_start.last_recoup_refresh_serial_id),
|
||||
GNUNET_JSON_pack_uint64 ("start_ppc_purse_deposits_serial_id",
|
||||
ppc_start.last_purse_deposits_serial_id),
|
||||
GNUNET_JSON_pack_uint64 ("start_ppc_purse_refunds_serial_id",
|
||||
ppc_start.last_purse_refunds_serial_id),
|
||||
GNUNET_JSON_pack_uint64 ("end_ppc_withdraw_serial_id",
|
||||
ppc.last_withdraw_serial_id),
|
||||
GNUNET_JSON_pack_uint64 ("end_ppc_deposit_serial_id",
|
||||
@ -2645,6 +2933,10 @@ run (void *cls,
|
||||
ppc.last_recoup_serial_id),
|
||||
GNUNET_JSON_pack_uint64 ("end_ppc_recoup_refresh_serial_id",
|
||||
ppc.last_recoup_refresh_serial_id),
|
||||
GNUNET_JSON_pack_uint64 ("end_ppc_purse_deposits_serial_id",
|
||||
ppc.last_purse_deposits_serial_id),
|
||||
GNUNET_JSON_pack_uint64 ("end_ppc_purse_refunds_serial_id",
|
||||
ppc.last_purse_refunds_serial_id),
|
||||
TALER_JSON_pack_time_abs_human ("auditor_start_time",
|
||||
start_time),
|
||||
TALER_JSON_pack_time_abs_human ("auditor_end_time",
|
||||
|
@ -87,6 +87,7 @@ CREATE TABLE IF NOT EXISTS auditor_progress_coin
|
||||
,last_recoup_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_recoup_refresh_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_purse_deposits_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_purse_refunds_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,PRIMARY KEY (master_pub)
|
||||
);
|
||||
COMMENT ON TABLE auditor_progress_coin
|
||||
|
@ -314,8 +314,9 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",last_recoup_serial_id=$5"
|
||||
",last_recoup_refresh_serial_id=$6"
|
||||
",last_purse_deposits_serial_id=$7"
|
||||
" WHERE master_pub=$8",
|
||||
8),
|
||||
",last_purse_refunds_serial_id=$8"
|
||||
" WHERE master_pub=$9",
|
||||
9),
|
||||
/* Used in #postgres_get_auditor_progress_coin() */
|
||||
GNUNET_PQ_make_prepare ("auditor_progress_select_coin",
|
||||
"SELECT"
|
||||
@ -326,6 +327,7 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",last_recoup_serial_id"
|
||||
",last_recoup_refresh_serial_id"
|
||||
",last_purse_deposits_serial_id"
|
||||
",last_purse_refunds_serial_id"
|
||||
" FROM auditor_progress_coin"
|
||||
" WHERE master_pub=$1;",
|
||||
1),
|
||||
@ -340,8 +342,9 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",last_recoup_serial_id"
|
||||
",last_recoup_refresh_serial_id"
|
||||
",last_purse_deposits_serial_id"
|
||||
") VALUES ($1,$2,$3,$4,$5,$6,$7,$8);",
|
||||
8),
|
||||
",last_purse_refunds_serial_id"
|
||||
") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9);",
|
||||
9),
|
||||
/* Used in #postgres_insert_wire_auditor_account_progress() */
|
||||
GNUNET_PQ_make_prepare ("wire_auditor_account_progress_insert",
|
||||
"INSERT INTO wire_auditor_account_progress "
|
||||
@ -1535,6 +1538,7 @@ postgres_insert_auditor_progress_coin (
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_refresh_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_purse_deposits_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_purse_refunds_serial_id),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
|
||||
@ -1568,6 +1572,7 @@ postgres_update_auditor_progress_coin (
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_refresh_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_purse_deposits_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_purse_refunds_serial_id),
|
||||
GNUNET_PQ_query_param_auto_from_type (master_pub),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
@ -1612,6 +1617,8 @@ postgres_get_auditor_progress_coin (
|
||||
&ppc->last_recoup_refresh_serial_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("last_purse_deposits_serial_id",
|
||||
&ppc->last_purse_deposits_serial_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("last_purse_refunds_serial_id",
|
||||
&ppc->last_purse_refunds_serial_id),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
|
@ -14,16 +14,24 @@ pkgcfg_DATA = \
|
||||
|
||||
sqldir = $(prefix)/share/taler/sql/exchange/
|
||||
|
||||
sqlinputs = \
|
||||
common-0001.sql \
|
||||
drop-common.sql \
|
||||
exchange-0001-part.sql \
|
||||
drop0001-exchange-part.sql \
|
||||
shard-0001-part.sql \
|
||||
drop0001-shard-part.sql
|
||||
|
||||
sql_DATA = \
|
||||
benchmark-0000.sql \
|
||||
benchmark-0001.sql \
|
||||
exchange-0000.sql \
|
||||
exchange-0001-part.sql \
|
||||
shard-0001-part.sql \
|
||||
common-0001.sql \
|
||||
drop-common.sql \
|
||||
drop0001-exchange-part.sql \
|
||||
drop0001-shard-part.sql
|
||||
exchange-0001.sql \
|
||||
drop0001.sql \
|
||||
shard-0000.sql \
|
||||
shard-0001.sql \
|
||||
shard-drop0001.sql
|
||||
|
||||
|
||||
BUILT_SOURCES = \
|
||||
shard-0000.sql \
|
||||
@ -40,22 +48,27 @@ CLEANFILES = \
|
||||
shard-drop0001.sql
|
||||
|
||||
exchange-0001.sql: common-0001.sql exchange-0001-part.sql
|
||||
chmod +w $@ || true
|
||||
cat common-0001.sql exchange-0001-part.sql >$@
|
||||
chmod -w $@
|
||||
|
||||
shard-0001.sql: common-0001.sql shard-0001-part.sql
|
||||
chmod +w $@ || true
|
||||
cat common-0001.sql shard-0001-part.sql >$@
|
||||
chmod -w $@
|
||||
|
||||
shard-0000.sql: exchange-0000.sql
|
||||
chmod +w $@ || true
|
||||
cp exchange-0000.sql $@
|
||||
chmod -w $@
|
||||
|
||||
drop0001.sql: drop-common.sql drop0001-exchange-part.sql
|
||||
chmod +w $@ || true
|
||||
cat drop-common.sql drop0001-exchange-part.sql >$@
|
||||
chmod -w $@
|
||||
|
||||
shard-drop0001.sql: drop-common.sql drop0001-shard-part.sql
|
||||
chmod +w $@ || true
|
||||
cat drop-common.sql drop0001-shard-part.sql >$@
|
||||
chmod -w $@
|
||||
|
||||
@ -67,6 +80,7 @@ EXTRA_DIST = \
|
||||
lrbt_callbacks.c \
|
||||
bench-db-postgres.conf \
|
||||
test-exchange-db-postgres.conf \
|
||||
$(sqlinputs) \
|
||||
$(sql_DATA)
|
||||
|
||||
plugindir = $(libdir)/taler
|
||||
|
@ -1219,6 +1219,54 @@ BEGIN
|
||||
END
|
||||
$$;
|
||||
|
||||
|
||||
------------------------------- purse_refunds ----------------------------------------
|
||||
|
||||
CREATE OR REPLACE FUNCTION create_table_purse_refunds(
|
||||
IN shard_suffix VARCHAR DEFAULT NULL
|
||||
)
|
||||
RETURNS VOID
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
table_name VARCHAR DEFAULT 'purse_refunds';
|
||||
BEGIN
|
||||
|
||||
PERFORM create_partitioned_table(
|
||||
'CREATE TABLE IF NOT EXISTS %I '
|
||||
'(purse_refunds_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' --UNIQUE
|
||||
',purse_pub BYTEA NOT NULL CHECK (LENGTH(purse_pub)=32)'
|
||||
',PRIMARY KEY (purse_pub)'
|
||||
') %s ;'
|
||||
,table_name
|
||||
,'PARTITION BY HASH (purse_pub)'
|
||||
,shard_suffix
|
||||
);
|
||||
|
||||
table_name = concat_ws('_', table_name, shard_suffix);
|
||||
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION add_constraints_to_purse_refunds_partition(
|
||||
IN partition_suffix VARCHAR
|
||||
)
|
||||
RETURNS VOID
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
EXECUTE FORMAT (
|
||||
'ALTER TABLE purse_refunds_' || partition_suffix || ' '
|
||||
'ADD CONSTRAINT purse_refunds_' || partition_suffix || '_purse_refunds_serial_id_key '
|
||||
'UNIQUE (purse_refunds_serial_id) '
|
||||
);
|
||||
END
|
||||
$$;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------- purse_merges -----------------------------
|
||||
|
||||
CREATE OR REPLACE FUNCTION create_table_purse_merges(
|
||||
@ -1828,6 +1876,9 @@ BEGIN
|
||||
ALTER TABLE IF EXISTS purse_requests
|
||||
DETACH partition purse_requests_default;
|
||||
|
||||
ALTER TABLE IF EXISTS purse_refunds
|
||||
DETACH partition purse_refunds_default;
|
||||
|
||||
ALTER TABLE IF EXISTS purse_merges
|
||||
DETACH partition purse_merges_default;
|
||||
|
||||
@ -1894,6 +1945,7 @@ BEGIN
|
||||
DROP TABLE IF EXISTS cs_nonce_locks_default;
|
||||
|
||||
DROP TABLE IF EXISTS purse_requests_default;
|
||||
DROP TABLE IF EXISTS purse_refunds_default;
|
||||
DROP TABLE IF EXISTS purse_merges_default;
|
||||
DROP TABLE IF EXISTS account_merges_default;
|
||||
DROP TABLE IF EXISTS contracts_default;
|
||||
@ -2105,6 +2157,13 @@ BEGIN
|
||||
);
|
||||
PERFORM add_constraints_to_purse_requests_partition(num_partitions::varchar);
|
||||
|
||||
PERFORM create_hash_partition(
|
||||
'purse_refunds'
|
||||
,modulus
|
||||
,num_partitions
|
||||
);
|
||||
PERFORM add_constraints_to_purse_refunds_partition(num_partitions::varchar);
|
||||
|
||||
PERFORM create_hash_partition(
|
||||
'purse_merges'
|
||||
,modulus
|
||||
@ -2316,6 +2375,10 @@ BEGIN
|
||||
DROP CONSTRAINT IF EXISTS purse_requests_pkey CASCADE
|
||||
;
|
||||
|
||||
ALTER TABLE IF EXISTS purse_refunds
|
||||
DROP CONSTRAINT IF EXISTS purse_refunds_pkey CASCADE
|
||||
;
|
||||
|
||||
ALTER TABLE IF EXISTS purse_merges
|
||||
DROP CONSTRAINT IF EXISTS purse_merges_pkey CASCADE
|
||||
;
|
||||
@ -2571,6 +2634,13 @@ BEGIN
|
||||
,current_shard_num
|
||||
,local_user
|
||||
);
|
||||
PERFORM create_foreign_hash_partition(
|
||||
'purse_refunds'
|
||||
,total_num_shards
|
||||
,shard_suffix
|
||||
,current_shard_num
|
||||
,local_user
|
||||
);
|
||||
PERFORM create_foreign_hash_partition(
|
||||
'purse_merges'
|
||||
,total_num_shards
|
||||
|
@ -63,6 +63,8 @@ DROP FUNCTION IF EXISTS add_constraints_to_cs_nonce_locks_partition;
|
||||
|
||||
DROP FUNCTION IF EXISTS create_table_purse_requests;
|
||||
DROP FUNCTION IF EXISTS add_constraints_to_purse_requests_partition;
|
||||
DROP FUNCTION IF EXISTS create_table_purse_refunds;
|
||||
DROP FUNCTION IF EXISTS add_constraints_to_purse_refunds_partition;
|
||||
DROP FUNCTION IF EXISTS create_table_purse_merges;
|
||||
DROP FUNCTION IF EXISTS add_constraints_to_purse_merges_partition;
|
||||
DROP FUNCTION IF EXISTS create_table_account_merges;
|
||||
|
@ -73,6 +73,7 @@ DROP TABLE IF EXISTS contracts CASCADE;
|
||||
DROP TABLE IF EXISTS history_requests CASCADE;
|
||||
DROP TABLE IF EXISTS close_requests CASCADE;
|
||||
DROP TABLE IF EXISTS purse_requests CASCADE;
|
||||
DROP TABLE IF EXISTS purse_refunds CASCADE;
|
||||
DROP TABLE IF EXISTS wads_out CASCADE;
|
||||
DROP TABLE IF EXISTS wad_out_entries CASCADE;
|
||||
DROP TABLE IF EXISTS wads_in CASCADE;
|
||||
|
@ -1040,6 +1040,21 @@ CREATE TABLE IF NOT EXISTS purse_requests_default
|
||||
SELECT add_constraints_to_purse_requests_partition('default');
|
||||
|
||||
|
||||
-- ------------------------------ purse_refunds ----------------------------------------
|
||||
|
||||
SELECT create_table_purse_refunds();
|
||||
|
||||
COMMENT ON TABLE purse_refunds
|
||||
IS 'Purses that were refunded due to expiration';
|
||||
COMMENT ON COLUMN purse_refunds.purse_pub
|
||||
IS 'Public key of the purse';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS purse_refunds_default
|
||||
PARTITION OF purse_refunds
|
||||
FOR VALUES WITH (MODULUS 1, REMAINDER 0);
|
||||
|
||||
SELECT add_constraints_to_purse_refunds_partition('default');
|
||||
|
||||
|
||||
-- ------------------------------ purse_merges ----------------------------------------
|
||||
|
||||
@ -3485,6 +3500,11 @@ UPDATE purse_requests
|
||||
finished=TRUE
|
||||
WHERE purse_pub=my_purse_pub;
|
||||
|
||||
INSERT INTO purse_refunds
|
||||
(purse_pub)
|
||||
VALUES
|
||||
(my_purse_pub);
|
||||
|
||||
-- restore balance to each coin deposited into the purse
|
||||
FOR my_deposit IN
|
||||
SELECT coin_pub
|
||||
|
@ -809,6 +809,8 @@ irbt_cb_table_purse_requests (struct PostgresClosure *pg,
|
||||
{
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_uint64 (&td->serial),
|
||||
GNUNET_PQ_query_param_auto_from_type (
|
||||
&td->details.purse_requests.purse_pub),
|
||||
GNUNET_PQ_query_param_auto_from_type (
|
||||
&td->details.purse_requests.merge_pub),
|
||||
GNUNET_PQ_query_param_timestamp (
|
||||
@ -832,6 +834,29 @@ irbt_cb_table_purse_requests (struct PostgresClosure *pg,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with purse_refunds records to insert into table.
|
||||
*
|
||||
* @param pg plugin context
|
||||
* @param td record to insert
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
irbt_cb_table_purse_refunds (struct PostgresClosure *pg,
|
||||
const struct TALER_EXCHANGEDB_TableData *td)
|
||||
{
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_uint64 (&td->serial),
|
||||
GNUNET_PQ_query_param_auto_from_type (
|
||||
&td->details.purse_refunds.purse_pub),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
|
||||
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
|
||||
"insert_into_table_purse_refunds",
|
||||
params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with purse_merges records to insert into table.
|
||||
*
|
||||
|
@ -1549,6 +1549,51 @@ lrbt_cb_table_purse_requests (void *cls,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with purse_refunds table entries.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param result the postgres result
|
||||
* @param num_results the number of results in @a result
|
||||
*/
|
||||
static void
|
||||
lrbt_cb_table_purse_refunds (void *cls,
|
||||
PGresult *result,
|
||||
unsigned int num_results)
|
||||
{
|
||||
struct LookupRecordsByTableContext *ctx = cls;
|
||||
struct TALER_EXCHANGEDB_TableData td = {
|
||||
.table = TALER_EXCHANGEDB_RT_PURSE_REFUNDS
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i<num_results; i++)
|
||||
{
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_uint64 (
|
||||
"purse_refunds_serial_id",
|
||||
&td.serial),
|
||||
GNUNET_PQ_result_spec_auto_from_type (
|
||||
"purse_pub",
|
||||
&td.details.purse_refunds.purse_pub),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result,
|
||||
rs,
|
||||
i))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ctx->error = true;
|
||||
return;
|
||||
}
|
||||
ctx->cb (ctx->cb_cls,
|
||||
&td);
|
||||
GNUNET_PQ_cleanup_result (rs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with purse_merges table entries.
|
||||
*
|
||||
|
@ -1407,6 +1407,19 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
" WHERE ref.refund_serial_id>=$1"
|
||||
" ORDER BY ref.refund_serial_id ASC;",
|
||||
1),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"test_refund_full",
|
||||
"SELECT"
|
||||
" CAST(SUM(CAST(ref.amount_with_fee_frac AS INT8)) AS INT8) AS s_f"
|
||||
",CAST(SUM(ref.amount_with_fee_val) AS INT8) AS s_v"
|
||||
",dep.amount_with_fee_val"
|
||||
",dep.amount_with_fee_frac"
|
||||
" FROM refunds ref"
|
||||
" JOIN deposits dep"
|
||||
" ON (ref.coin_pub=dep.coin_pub AND ref.deposit_serial_id=dep.deposit_serial_id)"
|
||||
" WHERE ref.refund_serial_id=$1"
|
||||
" GROUP BY (dep.amount_with_fee_val, dep.amount_with_fee_frac);",
|
||||
1),
|
||||
|
||||
/* Store information about a /deposit the exchange is to execute.
|
||||
Used in #postgres_insert_deposit(). Only used in test cases. */
|
||||
@ -1508,6 +1521,29 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
" )"
|
||||
" ORDER BY purse_deposit_serial_id ASC;",
|
||||
1),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"audit_get_purse_deposits_by_purse",
|
||||
"SELECT"
|
||||
" pd.amount_with_fee_val"
|
||||
",pd.amount_with_fee_frac"
|
||||
",pd.coin_pub"
|
||||
",denom.denom_pub"
|
||||
" FROM purse_deposits pd"
|
||||
" JOIN known_coins kc USING (coin_pub)"
|
||||
" JOIN denominations denom USING (denominations_serial)"
|
||||
" WHERE purse_pub=$1;",
|
||||
1),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"audit_get_purse_refunds_incr",
|
||||
"SELECT"
|
||||
" purse_pub"
|
||||
",purse_refunds_serial_id"
|
||||
" FROM purse_refunds"
|
||||
" WHERE ("
|
||||
" (purse_refunds_serial_id>=$1)"
|
||||
" )"
|
||||
" ORDER BY purse_refunds_serial_id ASC;",
|
||||
1),
|
||||
/* Fetch an existing deposit request.
|
||||
Used in #postgres_lookup_transfer_by_deposit(). */
|
||||
GNUNET_PQ_make_prepare (
|
||||
@ -2778,6 +2814,14 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
" ORDER BY purse_requests_serial_id DESC"
|
||||
" LIMIT 1;",
|
||||
0),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"select_serial_by_table_purse_refunds",
|
||||
"SELECT"
|
||||
" purse_refunds_serial_id AS serial"
|
||||
" FROM purse_refunds"
|
||||
" ORDER BY purse_refunds_serial_id DESC"
|
||||
" LIMIT 1;",
|
||||
0),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"select_serial_by_table_purse_merges",
|
||||
"SELECT"
|
||||
@ -3212,6 +3256,15 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
" WHERE purse_requests_serial_id > $1"
|
||||
" ORDER BY purse_requests_serial_id ASC;",
|
||||
1),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"select_above_serial_by_table_purse_refunds",
|
||||
"SELECT"
|
||||
" purse_refunds_serial_id"
|
||||
",purse_pub"
|
||||
" FROM purse_refunds"
|
||||
" WHERE purse_refunds_serial_id > $1"
|
||||
" ORDER BY purse_refunds_serial_id ASC;",
|
||||
1),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"select_above_serial_by_table_purse_merges",
|
||||
"SELECT"
|
||||
@ -3688,6 +3741,14 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
") VALUES "
|
||||
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);",
|
||||
13),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"insert_into_table_purse_refunds",
|
||||
"INSERT INTO purse_refunds"
|
||||
"(purse_refunds_serial_id"
|
||||
",purse_pub"
|
||||
") VALUES "
|
||||
"($1, $2);",
|
||||
2),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"insert_into_table_purse_merges",
|
||||
"INSERT INTO purse_merges"
|
||||
@ -10496,6 +10557,242 @@ postgres_select_purse_deposits_above_serial_id (
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #purse_refund_serial_helper_cb().
|
||||
*/
|
||||
struct PurseRefundSerialContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Callback to call.
|
||||
*/
|
||||
TALER_EXCHANGEDB_PurseRefundCallback cb;
|
||||
|
||||
/**
|
||||
* Closure for @e cb.
|
||||
*/
|
||||
void *cb_cls;
|
||||
|
||||
/**
|
||||
* Plugin context.
|
||||
*/
|
||||
struct PostgresClosure *pg;
|
||||
|
||||
/**
|
||||
* Status code, set to #GNUNET_SYSERR on hard errors.
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue 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 PurseRefundSerialContext`
|
||||
* @param result the postgres result
|
||||
* @param num_results the number of results in @a result
|
||||
*/
|
||||
static void
|
||||
purse_refund_serial_helper_cb (void *cls,
|
||||
PGresult *result,
|
||||
unsigned int num_results)
|
||||
{
|
||||
struct PurseRefundSerialContext *dsc = cls;
|
||||
|
||||
for (unsigned int i = 0; i<num_results; i++)
|
||||
{
|
||||
struct TALER_PurseContractPublicKeyP purse_pub;
|
||||
uint64_t rowid;
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
|
||||
&purse_pub),
|
||||
GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
|
||||
&rowid),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result,
|
||||
rs,
|
||||
i))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
dsc->status = GNUNET_SYSERR;
|
||||
return;
|
||||
}
|
||||
ret = dsc->cb (dsc->cb_cls,
|
||||
rowid,
|
||||
&purse_pub);
|
||||
GNUNET_PQ_cleanup_result (rs);
|
||||
if (GNUNET_OK != ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Select purse refunds above @a serial_id in monotonically increasing
|
||||
* order.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param serial_id highest serial ID to exclude (select strictly larger)
|
||||
* @param cb function to call on each result
|
||||
* @param cb_cls closure for @a cb
|
||||
* @return transaction status code
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
postgres_select_purse_refunds_above_serial_id (
|
||||
void *cls,
|
||||
uint64_t serial_id,
|
||||
TALER_EXCHANGEDB_PurseRefundCallback cb,
|
||||
void *cb_cls)
|
||||
{
|
||||
struct PostgresClosure *pg = cls;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_uint64 (&serial_id),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
struct PurseRefundSerialContext dsc = {
|
||||
.cb = cb,
|
||||
.cb_cls = cb_cls,
|
||||
.pg = pg,
|
||||
.status = GNUNET_OK
|
||||
};
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
|
||||
"audit_get_purse_refunds_incr",
|
||||
params,
|
||||
&purse_refund_serial_helper_cb,
|
||||
&dsc);
|
||||
if (GNUNET_OK != dsc.status)
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #purse_refund_coin_helper_cb().
|
||||
*/
|
||||
struct PurseRefundCoinContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Callback to call.
|
||||
*/
|
||||
TALER_EXCHANGEDB_PurseRefundCoinCallback cb;
|
||||
|
||||
/**
|
||||
* Closure for @e cb.
|
||||
*/
|
||||
void *cb_cls;
|
||||
|
||||
/**
|
||||
* Plugin context.
|
||||
*/
|
||||
struct PostgresClosure *pg;
|
||||
|
||||
/**
|
||||
* Status code, set to #GNUNET_SYSERR on hard errors.
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue 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 PurseRefundCoinContext`
|
||||
* @param result the postgres result
|
||||
* @param num_results the number of results in @a result
|
||||
*/
|
||||
static void
|
||||
purse_refund_coin_helper_cb (void *cls,
|
||||
PGresult *result,
|
||||
unsigned int num_results)
|
||||
{
|
||||
struct PurseRefundCoinContext *dsc = cls;
|
||||
struct PostgresClosure *pg = dsc->pg;
|
||||
|
||||
for (unsigned int i = 0; i<num_results; i++)
|
||||
{
|
||||
struct TALER_Amount amount_with_fee;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
struct TALER_DenominationPublicKey denom_pub;
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
TALER_PQ_result_spec_denom_pub ("denom_pub",
|
||||
&denom_pub),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
|
||||
&amount_with_fee),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
|
||||
&coin_pub),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result,
|
||||
rs,
|
||||
i))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
dsc->status = GNUNET_SYSERR;
|
||||
return;
|
||||
}
|
||||
ret = dsc->cb (dsc->cb_cls,
|
||||
&amount_with_fee,
|
||||
&coin_pub,
|
||||
&denom_pub);
|
||||
GNUNET_PQ_cleanup_result (rs);
|
||||
if (GNUNET_OK != ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Select coin affected by purse refund.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param purse_pub purse that was refunded
|
||||
* @param cb function to call on each result
|
||||
* @param cb_cls closure for @a cb
|
||||
* @return transaction status code
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
postgres_select_purse_deposits_by_purse (
|
||||
void *cls,
|
||||
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||
TALER_EXCHANGEDB_PurseRefundCoinCallback cb,
|
||||
void *cb_cls)
|
||||
{
|
||||
struct PostgresClosure *pg = cls;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_auto_from_type (purse_pub),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
struct PurseRefundCoinContext dsc = {
|
||||
.cb = cb,
|
||||
.cb_cls = cb_cls,
|
||||
.pg = pg,
|
||||
.status = GNUNET_OK
|
||||
};
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
|
||||
"audit_get_purse_deposits_by_purse",
|
||||
params,
|
||||
&purse_refund_coin_helper_cb,
|
||||
&dsc);
|
||||
if (GNUNET_OK != dsc.status)
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #refreshs_serial_helper_cb().
|
||||
*/
|
||||
@ -10690,6 +10987,7 @@ refunds_serial_helper_cb (void *cls,
|
||||
struct TALER_EXCHANGEDB_Refund refund;
|
||||
struct TALER_DenominationPublicKey denom_pub;
|
||||
uint64_t rowid;
|
||||
bool full_refund;
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
|
||||
&refund.details.merchant_pub),
|
||||
@ -10720,6 +11018,42 @@ refunds_serial_helper_cb (void *cls,
|
||||
rsc->status = GNUNET_SYSERR;
|
||||
return;
|
||||
}
|
||||
{
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_uint64 (&rowid),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
struct TALER_Amount amount_with_fee;
|
||||
uint64_t s_f;
|
||||
uint64_t s_v;
|
||||
struct GNUNET_PQ_ResultSpec rs2[] = {
|
||||
GNUNET_PQ_result_spec_uint64 ("s_v",
|
||||
&s_v),
|
||||
GNUNET_PQ_result_spec_uint64 ("s_f",
|
||||
&s_f),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
|
||||
&amount_with_fee),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = GNUNET_PQ_eval_prepared_singleton_select (
|
||||
pg->conn,
|
||||
"test_refund_full",
|
||||
params,
|
||||
rs2);
|
||||
if (qs <= 0)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
rsc->status = GNUNET_SYSERR;
|
||||
return;
|
||||
}
|
||||
/* normalize */
|
||||
s_v += s_f / TALER_AMOUNT_FRAC_BASE;
|
||||
s_f %= TALER_AMOUNT_FRAC_BASE;
|
||||
full_refund = (s_v >= amount_with_fee.value) &&
|
||||
(s_f >= amount_with_fee.fraction);
|
||||
}
|
||||
ret = rsc->cb (rsc->cb_cls,
|
||||
rowid,
|
||||
&denom_pub,
|
||||
@ -10728,6 +11062,7 @@ refunds_serial_helper_cb (void *cls,
|
||||
&refund.details.merchant_sig,
|
||||
&refund.details.h_contract_terms,
|
||||
refund.details.rtransaction_id,
|
||||
full_refund,
|
||||
&refund.details.refund_amount);
|
||||
GNUNET_PQ_cleanup_result (rs);
|
||||
if (GNUNET_OK != ret)
|
||||
@ -13129,6 +13464,9 @@ postgres_lookup_serial_by_table (void *cls,
|
||||
case TALER_EXCHANGEDB_RT_PURSE_REQUESTS:
|
||||
statement = "select_serial_by_table_purse_requests";
|
||||
break;
|
||||
case TALER_EXCHANGEDB_RT_PURSE_REFUNDS:
|
||||
statement = "select_serial_by_table_purse_refunds";
|
||||
break;
|
||||
case TALER_EXCHANGEDB_RT_PURSE_MERGES:
|
||||
statement = "select_serial_by_table_purse_merges";
|
||||
break;
|
||||
@ -13337,6 +13675,10 @@ postgres_lookup_records_by_table (void *cls,
|
||||
statement = "select_above_serial_by_table_purse_requests";
|
||||
rh = &lrbt_cb_table_purse_requests;
|
||||
break;
|
||||
case TALER_EXCHANGEDB_RT_PURSE_REFUNDS:
|
||||
statement = "select_above_serial_by_table_purse_refunds";
|
||||
rh = &lrbt_cb_table_purse_refunds;
|
||||
break;
|
||||
case TALER_EXCHANGEDB_RT_PURSE_MERGES:
|
||||
statement = "select_above_serial_by_table_purse_merges";
|
||||
rh = &lrbt_cb_table_purse_merges;
|
||||
@ -13510,6 +13852,9 @@ postgres_insert_records_by_table (void *cls,
|
||||
case TALER_EXCHANGEDB_RT_PURSE_REQUESTS:
|
||||
rh = &irbt_cb_table_purse_requests;
|
||||
break;
|
||||
case TALER_EXCHANGEDB_RT_PURSE_REFUNDS:
|
||||
rh = &irbt_cb_table_purse_refunds;
|
||||
break;
|
||||
case TALER_EXCHANGEDB_RT_PURSE_MERGES:
|
||||
rh = &irbt_cb_table_purse_merges;
|
||||
break;
|
||||
@ -15203,6 +15548,10 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
|
||||
= &postgres_select_deposits_above_serial_id;
|
||||
plugin->select_purse_deposits_above_serial_id
|
||||
= &postgres_select_purse_deposits_above_serial_id;
|
||||
plugin->select_purse_refunds_above_serial_id
|
||||
= &postgres_select_purse_refunds_above_serial_id;
|
||||
plugin->select_purse_deposits_by_purse
|
||||
= &postgres_select_purse_deposits_by_purse;
|
||||
plugin->select_refreshes_above_serial_id
|
||||
= &postgres_select_refreshes_above_serial_id;
|
||||
plugin->select_refunds_above_serial_id
|
||||
|
@ -26,7 +26,7 @@ CREATE OR REPLACE FUNCTION setup_shard(
|
||||
RETURNS VOID
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
DECLARE
|
||||
shard_suffix VARCHAR;
|
||||
BEGIN
|
||||
|
||||
@ -51,26 +51,26 @@ BEGIN
|
||||
|
||||
PERFORM create_table_refresh_commitments(shard_suffix);
|
||||
PERFORM add_constraints_to_refresh_commitments_partition(shard_suffix);
|
||||
|
||||
|
||||
PERFORM create_table_refresh_revealed_coins(shard_suffix);
|
||||
PERFORM add_constraints_to_refresh_revealed_coins_partition(shard_suffix);
|
||||
|
||||
|
||||
PERFORM create_table_refresh_transfer_keys(shard_suffix);
|
||||
PERFORM add_constraints_to_refresh_transfer_keys_partition(shard_suffix);
|
||||
|
||||
|
||||
PERFORM create_table_deposits(shard_suffix);
|
||||
PERFORM add_constraints_to_deposits_partition(shard_suffix);
|
||||
|
||||
PERFORM create_table_deposits_by_ready(shard_suffix);
|
||||
|
||||
PERFORM create_table_deposits_for_matching(shard_suffix);
|
||||
|
||||
|
||||
PERFORM create_table_refunds(shard_suffix);
|
||||
PERFORM add_constraints_to_refunds_partition(shard_suffix);
|
||||
|
||||
|
||||
PERFORM create_table_wire_out(shard_suffix);
|
||||
PERFORM add_constraints_to_wire_out_partition(shard_suffix);
|
||||
|
||||
|
||||
PERFORM create_table_aggregation_transient(shard_suffix);
|
||||
|
||||
PERFORM create_table_aggregation_tracking(shard_suffix);
|
||||
@ -92,6 +92,9 @@ BEGIN
|
||||
PERFORM create_table_purse_requests(shard_suffix);
|
||||
PERFORM add_constraints_to_purse_requests_partition(shard_suffix);
|
||||
|
||||
PERFORM create_table_purse_refunds(shard_suffix);
|
||||
PERFORM add_constraints_to_purse_refunds_partition(shard_suffix);
|
||||
|
||||
PERFORM create_table_purse_merges(shard_suffix);
|
||||
PERFORM add_constraints_to_purse_merges_partition(shard_suffix);
|
||||
|
||||
@ -121,15 +124,15 @@ $$;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION drop_shard(
|
||||
shard_idx INTEGER
|
||||
shard_idx INTEGER
|
||||
)
|
||||
RETURNS VOID
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
DECLARE
|
||||
shard_suffix VARCHAR;
|
||||
BEGIN
|
||||
|
||||
|
||||
shard_suffix = shard_idx::varchar;
|
||||
|
||||
EXECUTE FORMAT(
|
||||
@ -224,6 +227,10 @@ BEGIN
|
||||
'DROP TABLE IF EXISTS %I CASCADE'
|
||||
,'purse_requests_' || shard_suffix
|
||||
);
|
||||
EXECUTE FORMAT(
|
||||
'DROP TABLE IF EXISTS %I CASCADE'
|
||||
,'purse_refunds_' || shard_suffix
|
||||
);
|
||||
EXECUTE FORMAT(
|
||||
'DROP TABLE IF EXISTS %I CASCADE'
|
||||
,'purse_merges_' || shard_suffix
|
||||
|
@ -646,6 +646,7 @@ audit_deposit_cb (void *cls,
|
||||
* @param h_contract_terms hash of the proposal data in
|
||||
* the contract between merchant and customer
|
||||
* @param rtransaction_id refund transaction ID chosen by the merchant
|
||||
* @param full_refund the deposit
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
@ -658,6 +659,7 @@ audit_refund_cb (void *cls,
|
||||
const struct TALER_MerchantSignatureP *merchant_sig,
|
||||
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||
uint64_t rtransaction_id,
|
||||
bool full_refund,
|
||||
const struct TALER_Amount *amount_with_fee)
|
||||
{
|
||||
(void) cls;
|
||||
@ -669,6 +671,7 @@ audit_refund_cb (void *cls,
|
||||
(void) h_contract_terms;
|
||||
(void) rtransaction_id;
|
||||
(void) amount_with_fee;
|
||||
(void) full_refund;
|
||||
auditor_row_cnt++;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
1
src/include/.gitignore
vendored
Normal file
1
src/include/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
taler_signatures.h
|
@ -253,6 +253,11 @@ struct TALER_AUDITORDB_ProgressPointCoin
|
||||
*/
|
||||
uint64_t last_purse_deposits_serial_id;
|
||||
|
||||
/**
|
||||
* Serial ID of the last purse_refunds operation the auditor processed.
|
||||
*/
|
||||
uint64_t last_purse_refunds_serial_id;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -218,6 +218,7 @@ enum TALER_EXCHANGEDB_ReplicatedTable
|
||||
TALER_EXCHANGEDB_RT_EXTENSIONS,
|
||||
TALER_EXCHANGEDB_RT_EXTENSION_DETAILS,
|
||||
TALER_EXCHANGEDB_RT_PURSE_REQUESTS,
|
||||
TALER_EXCHANGEDB_RT_PURSE_REFUNDS,
|
||||
TALER_EXCHANGEDB_RT_PURSE_MERGES,
|
||||
TALER_EXCHANGEDB_RT_PURSE_DEPOSITS,
|
||||
TALER_EXCHANGEDB_RT_ACCOUNT_MERGES,
|
||||
@ -495,6 +496,11 @@ struct TALER_EXCHANGEDB_TableData
|
||||
struct TALER_PurseContractSignatureP purse_sig;
|
||||
} purse_requests;
|
||||
|
||||
struct
|
||||
{
|
||||
struct TALER_PurseContractPublicKeyP purse_pub;
|
||||
} purse_refunds;
|
||||
|
||||
struct
|
||||
{
|
||||
uint64_t partner_serial_id;
|
||||
@ -1995,6 +2001,40 @@ typedef enum GNUNET_GenericReturnValue
|
||||
const struct TALER_DenominationPublicKey *denom_pub);
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about purse refunds that have been made, with
|
||||
* the goal of auditing the purse refund's execution.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid unique serial ID for the deposit in our DB
|
||||
* @param purse_pub public key of the refunded purse
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
typedef enum GNUNET_GenericReturnValue
|
||||
(*TALER_EXCHANGEDB_PurseRefundCallback)(
|
||||
void *cls,
|
||||
uint64_t rowid,
|
||||
const struct TALER_PurseContractPublicKeyP *purse_pub);
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about purse refunds that have been made, with
|
||||
* the goal of auditing the purse refund's execution.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param amount_with_fee amount of the deposit into the purse
|
||||
* @param coin_pub coin that is to be refunded the @a given amount_with_fee
|
||||
* @param denom_pub denomination of @a coin_pub
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
typedef enum GNUNET_GenericReturnValue
|
||||
(*TALER_EXCHANGEDB_PurseRefundCoinCallback)(
|
||||
void *cls,
|
||||
const struct TALER_Amount *amount_with_fee,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_DenominationPublicKey *denom_pub);
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about coins that were melted,
|
||||
* with the goal of auditing the refresh's execution.
|
||||
@ -2198,6 +2238,7 @@ typedef void
|
||||
* @param merchant_sig signature of the merchant
|
||||
* @param h_contract_terms hash of the proposal data known to merchant and customer
|
||||
* @param rtransaction_id refund transaction ID chosen by the merchant
|
||||
* @param full_refund true if the refunds total up to the entire value of the deposit
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
@ -2211,6 +2252,7 @@ typedef enum GNUNET_GenericReturnValue
|
||||
const struct TALER_MerchantSignatureP *merchant_sig,
|
||||
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||
uint64_t rtransaction_id,
|
||||
bool full_refund,
|
||||
const struct TALER_Amount *amount_with_fee);
|
||||
|
||||
|
||||
@ -4058,6 +4100,41 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
void *cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Select purse refunds above @a serial_id in monotonically increasing
|
||||
* order.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param serial_id highest serial ID to exclude (select strictly larger)
|
||||
* @param cb function to call on each result
|
||||
* @param cb_cls closure for @a cb
|
||||
* @return transaction status code
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*select_purse_refunds_above_serial_id)(
|
||||
void *cls,
|
||||
uint64_t serial_id,
|
||||
TALER_EXCHANGEDB_PurseRefundCallback cb,
|
||||
void *cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Select coins deposited into a purse.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param purse_pub public key of the purse
|
||||
* @param cb function to call on each result
|
||||
* @param cb_cls closure for @a cb
|
||||
* @return transaction status code
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*select_purse_deposits_by_purse)(
|
||||
void *cls,
|
||||
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||
TALER_EXCHANGEDB_PurseRefundCoinCallback cb,
|
||||
void *cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Select refresh sessions above @a serial_id in monotonically increasing
|
||||
* order.
|
||||
|
Loading…
Reference in New Issue
Block a user