fix auditor refund fee calculations
This commit is contained in:
parent
36a8ecd4c4
commit
0ad84355d5
@ -176,7 +176,7 @@ taler-exchange-offline -c $CONF \
|
|||||||
download sign \
|
download sign \
|
||||||
enable-account payto://x-taler-bank/localhost/Exchange \
|
enable-account payto://x-taler-bank/localhost/Exchange \
|
||||||
enable-auditor $AUDITOR_PUB $AUDITOR_URL "TESTKUDOS Auditor" \
|
enable-auditor $AUDITOR_PUB $AUDITOR_URL "TESTKUDOS Auditor" \
|
||||||
wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 \
|
wire-fee now x-taler-bank TESTKUDOS:0.07 TESTKUDOS:0.01 TESTKUDOS:0.01 \
|
||||||
global-fee now TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 1h 1h 1year 5 \
|
global-fee now TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 1h 1h 1year 5 \
|
||||||
upload &> taler-exchange-offline.log
|
upload &> taler-exchange-offline.log
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ static struct TALER_Amount total_arithmetic_delta_plus;
|
|||||||
static struct TALER_Amount total_arithmetic_delta_minus;
|
static struct TALER_Amount total_arithmetic_delta_minus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Total aggregation fees earned.
|
* Total aggregation fees (wire fees) earned.
|
||||||
*/
|
*/
|
||||||
static struct TALER_Amount total_aggregation_fee_income;
|
static struct TALER_Amount total_aggregation_fee_income;
|
||||||
|
|
||||||
@ -398,9 +398,9 @@ check_transaction_history_for_deposit (
|
|||||||
struct TALER_Amount expenditures;
|
struct TALER_Amount expenditures;
|
||||||
struct TALER_Amount refunds;
|
struct TALER_Amount refunds;
|
||||||
struct TALER_Amount spent;
|
struct TALER_Amount spent;
|
||||||
|
struct TALER_Amount *deposited = NULL;
|
||||||
struct TALER_Amount merchant_loss;
|
struct TALER_Amount merchant_loss;
|
||||||
const struct TALER_Amount *deposit_fee;
|
const struct TALER_Amount *deposit_fee;
|
||||||
bool refund_deposit_fee;
|
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"Checking transaction history of coin %s\n",
|
"Checking transaction history of coin %s\n",
|
||||||
@ -422,24 +422,33 @@ check_transaction_history_for_deposit (
|
|||||||
compute positive (deposit, melt) and negative (refund) values separately
|
compute positive (deposit, melt) and negative (refund) values separately
|
||||||
here, and then subtract the negative from the positive at the end (after
|
here, and then subtract the negative from the positive at the end (after
|
||||||
the loops). */
|
the loops). */
|
||||||
refund_deposit_fee = false;
|
|
||||||
deposit_fee = NULL;
|
deposit_fee = NULL;
|
||||||
for (const struct TALER_EXCHANGEDB_TransactionList *tl = tl_head;
|
for (const struct TALER_EXCHANGEDB_TransactionList *tl = tl_head;
|
||||||
NULL != tl;
|
NULL != tl;
|
||||||
tl = tl->next)
|
tl = tl->next)
|
||||||
{
|
{
|
||||||
const struct TALER_Amount *amount_with_fee;
|
|
||||||
const struct TALER_Amount *fee_claimed;
|
const struct TALER_Amount *fee_claimed;
|
||||||
|
|
||||||
switch (tl->type)
|
switch (tl->type)
|
||||||
{
|
{
|
||||||
case TALER_EXCHANGEDB_TT_DEPOSIT:
|
case TALER_EXCHANGEDB_TT_DEPOSIT:
|
||||||
/* check wire and h_wire are consistent */
|
/* check wire and h_wire are consistent */
|
||||||
amount_with_fee = &tl->details.deposit->amount_with_fee; /* according to exchange*/
|
if (NULL != deposited)
|
||||||
|
{
|
||||||
|
TALER_ARL_report (report_row_inconsistencies,
|
||||||
|
GNUNET_JSON_PACK (
|
||||||
|
GNUNET_JSON_pack_string ("table",
|
||||||
|
"deposits"),
|
||||||
|
GNUNET_JSON_pack_uint64 ("row",
|
||||||
|
tl->serial_id),
|
||||||
|
GNUNET_JSON_pack_string ("diagnostic",
|
||||||
|
"multiple deposits of the same coin into the same contract detected")));
|
||||||
|
}
|
||||||
|
deposited = &tl->details.deposit->amount_with_fee; /* according to exchange*/
|
||||||
fee_claimed = &tl->details.deposit->deposit_fee; /* Fee according to exchange DB */
|
fee_claimed = &tl->details.deposit->deposit_fee; /* Fee according to exchange DB */
|
||||||
TALER_ARL_amount_add (&expenditures,
|
TALER_ARL_amount_add (&expenditures,
|
||||||
&expenditures,
|
&expenditures,
|
||||||
amount_with_fee);
|
deposited);
|
||||||
/* Check if this deposit is within the remit of the aggregation
|
/* Check if this deposit is within the remit of the aggregation
|
||||||
we are investigating, if so, include it in the totals. */
|
we are investigating, if so, include it in the totals. */
|
||||||
if ( (0 == GNUNET_memcmp (merchant_pub,
|
if ( (0 == GNUNET_memcmp (merchant_pub,
|
||||||
@ -450,7 +459,7 @@ check_transaction_history_for_deposit (
|
|||||||
struct TALER_Amount amount_without_fee;
|
struct TALER_Amount amount_without_fee;
|
||||||
|
|
||||||
TALER_ARL_amount_subtract (&amount_without_fee,
|
TALER_ARL_amount_subtract (&amount_without_fee,
|
||||||
amount_with_fee,
|
deposited,
|
||||||
fee_claimed);
|
fee_claimed);
|
||||||
TALER_ARL_amount_add (merchant_gain,
|
TALER_ARL_amount_add (merchant_gain,
|
||||||
merchant_gain,
|
merchant_gain,
|
||||||
@ -474,96 +483,116 @@ check_transaction_history_for_deposit (
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TALER_EXCHANGEDB_TT_MELT:
|
case TALER_EXCHANGEDB_TT_MELT:
|
||||||
amount_with_fee = &tl->details.melt->amount_with_fee;
|
|
||||||
fee_claimed = &tl->details.melt->melt_fee;
|
|
||||||
TALER_ARL_amount_add (&expenditures,
|
|
||||||
&expenditures,
|
|
||||||
amount_with_fee);
|
|
||||||
/* Check that the fees given in the transaction list and in dki match */
|
|
||||||
if (0 !=
|
|
||||||
TALER_amount_cmp (&issue->fees.refresh,
|
|
||||||
fee_claimed))
|
|
||||||
{
|
{
|
||||||
/* Disagreement in fee structure between exchange and auditor */
|
const struct TALER_Amount *amount_with_fee;
|
||||||
report_amount_arithmetic_inconsistency ("melt fee",
|
|
||||||
0,
|
amount_with_fee = &tl->details.melt->amount_with_fee;
|
||||||
fee_claimed,
|
fee_claimed = &tl->details.melt->melt_fee;
|
||||||
&issue->fees.refresh,
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TALER_EXCHANGEDB_TT_REFUND:
|
|
||||||
amount_with_fee = &tl->details.refund->refund_amount;
|
|
||||||
fee_claimed = &tl->details.refund->refund_fee;
|
|
||||||
TALER_ARL_amount_add (&refunds,
|
|
||||||
&refunds,
|
|
||||||
amount_with_fee);
|
|
||||||
TALER_ARL_amount_add (&expenditures,
|
|
||||||
&expenditures,
|
|
||||||
fee_claimed);
|
|
||||||
/* Check if this refund is within the remit of the aggregation
|
|
||||||
we are investigating, if so, include it in the totals. */
|
|
||||||
if ( (0 == GNUNET_memcmp (merchant_pub,
|
|
||||||
&tl->details.refund->merchant_pub)) &&
|
|
||||||
(0 == GNUNET_memcmp (h_contract_terms,
|
|
||||||
&tl->details.refund->h_contract_terms)) )
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Detected applicable refund of %s\n",
|
|
||||||
TALER_amount2s (amount_with_fee));
|
|
||||||
TALER_ARL_amount_add (&merchant_loss,
|
|
||||||
&merchant_loss,
|
|
||||||
amount_with_fee);
|
|
||||||
/* If there is a refund, we give back the deposit fee */
|
|
||||||
/* FIXME: wrong: only if this is a FULL
|
|
||||||
refund we refund the deposit fee! */
|
|
||||||
refund_deposit_fee = true;
|
|
||||||
}
|
|
||||||
/* Check that the fees given in the transaction list and in dki match */
|
|
||||||
if (0 !=
|
|
||||||
TALER_amount_cmp (&issue->fees.refund,
|
|
||||||
fee_claimed))
|
|
||||||
{
|
|
||||||
/* Disagreement in fee structure between exchange and auditor! */
|
|
||||||
report_amount_arithmetic_inconsistency ("refund fee",
|
|
||||||
0,
|
|
||||||
fee_claimed,
|
|
||||||
&issue->fees.refund,
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TALER_EXCHANGEDB_TT_OLD_COIN_RECOUP:
|
|
||||||
amount_with_fee = &tl->details.old_coin_recoup->value;
|
|
||||||
/* We count recoups of refreshed coins like refunds for the dirty old
|
|
||||||
coin, as they equivalently _increase_ the remaining value on the
|
|
||||||
_old_ coin */
|
|
||||||
TALER_ARL_amount_add (&refunds,
|
|
||||||
&refunds,
|
|
||||||
amount_with_fee);
|
|
||||||
break;
|
|
||||||
case TALER_EXCHANGEDB_TT_RECOUP:
|
|
||||||
/* We count recoups of the coin as expenditures, as it
|
|
||||||
equivalently decreases the remaining value of the recouped coin. */
|
|
||||||
amount_with_fee = &tl->details.recoup->value;
|
|
||||||
TALER_ARL_amount_add (&expenditures,
|
|
||||||
&expenditures,
|
|
||||||
amount_with_fee);
|
|
||||||
break;
|
|
||||||
case TALER_EXCHANGEDB_TT_RECOUP_REFRESH:
|
|
||||||
/* We count recoups of the coin as expenditures, as it
|
|
||||||
equivalently decreases the remaining value of the recouped coin. */
|
|
||||||
amount_with_fee = &tl->details.recoup_refresh->value;
|
|
||||||
TALER_ARL_amount_add (&expenditures,
|
|
||||||
&expenditures,
|
|
||||||
amount_with_fee);
|
|
||||||
break;
|
|
||||||
case TALER_EXCHANGEDB_TT_PURSE_DEPOSIT:
|
|
||||||
amount_with_fee = &tl->details.purse_deposit->amount;
|
|
||||||
if (! tl->details.purse_deposit->refunded)
|
|
||||||
TALER_ARL_amount_add (&expenditures,
|
TALER_ARL_amount_add (&expenditures,
|
||||||
&expenditures,
|
&expenditures,
|
||||||
amount_with_fee);
|
amount_with_fee);
|
||||||
break;
|
/* Check that the fees given in the transaction list and in dki match */
|
||||||
|
if (0 !=
|
||||||
|
TALER_amount_cmp (&issue->fees.refresh,
|
||||||
|
fee_claimed))
|
||||||
|
{
|
||||||
|
/* Disagreement in fee structure between exchange and auditor */
|
||||||
|
report_amount_arithmetic_inconsistency ("melt fee",
|
||||||
|
0,
|
||||||
|
fee_claimed,
|
||||||
|
&issue->fees.refresh,
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TALER_EXCHANGEDB_TT_REFUND:
|
||||||
|
{
|
||||||
|
const struct TALER_Amount *amount_with_fee;
|
||||||
|
|
||||||
|
amount_with_fee = &tl->details.refund->refund_amount;
|
||||||
|
fee_claimed = &tl->details.refund->refund_fee;
|
||||||
|
TALER_ARL_amount_add (&refunds,
|
||||||
|
&refunds,
|
||||||
|
amount_with_fee);
|
||||||
|
TALER_ARL_amount_add (&expenditures,
|
||||||
|
&expenditures,
|
||||||
|
fee_claimed);
|
||||||
|
/* Check if this refund is within the remit of the aggregation
|
||||||
|
we are investigating, if so, include it in the totals. */
|
||||||
|
if ( (0 == GNUNET_memcmp (merchant_pub,
|
||||||
|
&tl->details.refund->merchant_pub)) &&
|
||||||
|
(0 == GNUNET_memcmp (h_contract_terms,
|
||||||
|
&tl->details.refund->h_contract_terms)) )
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Detected applicable refund of %s\n",
|
||||||
|
TALER_amount2s (amount_with_fee));
|
||||||
|
TALER_ARL_amount_add (&merchant_loss,
|
||||||
|
&merchant_loss,
|
||||||
|
amount_with_fee);
|
||||||
|
}
|
||||||
|
/* Check that the fees given in the transaction list and in dki match */
|
||||||
|
if (0 !=
|
||||||
|
TALER_amount_cmp (&issue->fees.refund,
|
||||||
|
fee_claimed))
|
||||||
|
{
|
||||||
|
/* Disagreement in fee structure between exchange and auditor! */
|
||||||
|
report_amount_arithmetic_inconsistency ("refund fee",
|
||||||
|
0,
|
||||||
|
fee_claimed,
|
||||||
|
&issue->fees.refund,
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TALER_EXCHANGEDB_TT_OLD_COIN_RECOUP:
|
||||||
|
{
|
||||||
|
const struct TALER_Amount *amount_with_fee;
|
||||||
|
|
||||||
|
amount_with_fee = &tl->details.old_coin_recoup->value;
|
||||||
|
/* We count recoups of refreshed coins like refunds for the dirty old
|
||||||
|
coin, as they equivalently _increase_ the remaining value on the
|
||||||
|
_old_ coin */
|
||||||
|
TALER_ARL_amount_add (&refunds,
|
||||||
|
&refunds,
|
||||||
|
amount_with_fee);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TALER_EXCHANGEDB_TT_RECOUP:
|
||||||
|
{
|
||||||
|
const struct TALER_Amount *amount_with_fee;
|
||||||
|
|
||||||
|
/* We count recoups of the coin as expenditures, as it
|
||||||
|
equivalently decreases the remaining value of the recouped coin. */
|
||||||
|
amount_with_fee = &tl->details.recoup->value;
|
||||||
|
TALER_ARL_amount_add (&expenditures,
|
||||||
|
&expenditures,
|
||||||
|
amount_with_fee);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TALER_EXCHANGEDB_TT_RECOUP_REFRESH:
|
||||||
|
{
|
||||||
|
const struct TALER_Amount *amount_with_fee;
|
||||||
|
|
||||||
|
/* We count recoups of the coin as expenditures, as it
|
||||||
|
equivalently decreases the remaining value of the recouped coin. */
|
||||||
|
amount_with_fee = &tl->details.recoup_refresh->value;
|
||||||
|
TALER_ARL_amount_add (&expenditures,
|
||||||
|
&expenditures,
|
||||||
|
amount_with_fee);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TALER_EXCHANGEDB_TT_PURSE_DEPOSIT:
|
||||||
|
{
|
||||||
|
const struct TALER_Amount *amount_with_fee;
|
||||||
|
|
||||||
|
amount_with_fee = &tl->details.purse_deposit->amount;
|
||||||
|
if (! tl->details.purse_deposit->refunded)
|
||||||
|
TALER_ARL_amount_add (&expenditures,
|
||||||
|
&expenditures,
|
||||||
|
amount_with_fee);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} /* for 'tl' */
|
} /* for 'tl' */
|
||||||
|
|
||||||
@ -574,14 +603,15 @@ check_transaction_history_for_deposit (
|
|||||||
"Aggregation loss due to refunds is %s\n",
|
"Aggregation loss due to refunds is %s\n",
|
||||||
TALER_amount2s (&merchant_loss));
|
TALER_amount2s (&merchant_loss));
|
||||||
*deposit_gain = *merchant_gain;
|
*deposit_gain = *merchant_gain;
|
||||||
if ( (refund_deposit_fee) &&
|
if ( (NULL != deposited) &&
|
||||||
(NULL != deposit_fee) )
|
(NULL != deposit_fee) &&
|
||||||
|
(0 == TALER_amount_cmp (&refunds,
|
||||||
|
deposited)) )
|
||||||
{
|
{
|
||||||
/* We had a /deposit operation AND a /refund operation,
|
/* We had a /deposit operation AND /refund operations adding up to the
|
||||||
and should thus not charge the merchant the /deposit fee */
|
total deposited value including deposit fee. Thus, we should not
|
||||||
/* FIXME: this is wrong, the merchant never pays either
|
subtract the /deposit fee from the merchant gain (as it was also
|
||||||
fee, the deposit fee is simply not charged to the coin
|
refunded). */
|
||||||
IF there is a full refund. */
|
|
||||||
TALER_ARL_amount_add (merchant_gain,
|
TALER_ARL_amount_add (merchant_gain,
|
||||||
merchant_gain,
|
merchant_gain,
|
||||||
deposit_fee);
|
deposit_fee);
|
||||||
@ -700,6 +730,10 @@ wire_transfer_information_cb (
|
|||||||
enum GNUNET_DB_QueryStatus qs;
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
struct TALER_PaytoHashP hpt;
|
struct TALER_PaytoHashP hpt;
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"DEPFEE: %s\n",
|
||||||
|
TALER_amount2s (deposit_fee));
|
||||||
|
|
||||||
TALER_payto_hash (account_pay_uri,
|
TALER_payto_hash (account_pay_uri,
|
||||||
&hpt);
|
&hpt);
|
||||||
if (0 !=
|
if (0 !=
|
||||||
|
@ -1778,18 +1778,12 @@ prepare_statements (struct PostgresClosure *pg)
|
|||||||
" FROM refunds"
|
" FROM refunds"
|
||||||
" WHERE coin_pub IN (SELECT coin_pub FROM dep)"
|
" WHERE coin_pub IN (SELECT coin_pub FROM dep)"
|
||||||
" AND deposit_serial_id IN (SELECT deposit_serial_id FROM dep))"
|
" AND deposit_serial_id IN (SELECT deposit_serial_id FROM dep))"
|
||||||
" ,coins_with_fees AS (" /* find coins for which deposit fees apply */
|
|
||||||
" SELECT"
|
|
||||||
" coin_pub"
|
|
||||||
" ,deposit_serial_id" /* ensures that if the same coin is deposited twice, it is in the list twice */
|
|
||||||
" FROM dep"
|
|
||||||
" WHERE deposit_serial_id NOT IN (SELECT deposit_serial_id FROM ref))"
|
|
||||||
" ,fees AS (" /* find deposit fees for non-refunded deposits */
|
" ,fees AS (" /* find deposit fees for non-refunded deposits */
|
||||||
" SELECT"
|
" SELECT"
|
||||||
" denom.fee_deposit_val AS fee_val"
|
" denom.fee_deposit_val AS fee_val"
|
||||||
" ,denom.fee_deposit_frac AS fee_frac"
|
" ,denom.fee_deposit_frac AS fee_frac"
|
||||||
" ,cs.deposit_serial_id" /* ensures we get the fee for each coin, not once per denomination */
|
" ,cs.deposit_serial_id" /* ensures we get the fee for each coin, not once per denomination */
|
||||||
" FROM coins_with_fees cs"
|
" FROM dep cs"
|
||||||
" JOIN known_coins kc" /* NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */
|
" JOIN known_coins kc" /* NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */
|
||||||
" USING (coin_pub)"
|
" USING (coin_pub)"
|
||||||
" JOIN denominations denom"
|
" JOIN denominations denom"
|
||||||
|
@ -1397,6 +1397,7 @@ run (void *cls)
|
|||||||
|
|
||||||
{
|
{
|
||||||
bool found;
|
bool found;
|
||||||
|
bool nonce_ok;
|
||||||
bool balance_ok;
|
bool balance_ok;
|
||||||
struct TALER_EXCHANGEDB_KycStatus kyc;
|
struct TALER_EXCHANGEDB_KycStatus kyc;
|
||||||
uint64_t ruuid;
|
uint64_t ruuid;
|
||||||
@ -1408,9 +1409,11 @@ run (void *cls)
|
|||||||
now,
|
now,
|
||||||
&found,
|
&found,
|
||||||
&balance_ok,
|
&balance_ok,
|
||||||
|
&nonce_ok,
|
||||||
&kyc,
|
&kyc,
|
||||||
&ruuid));
|
&ruuid));
|
||||||
GNUNET_assert (found);
|
GNUNET_assert (found);
|
||||||
|
GNUNET_assert (nonce_ok);
|
||||||
GNUNET_assert (balance_ok);
|
GNUNET_assert (balance_ok);
|
||||||
GNUNET_assert (! kyc.ok);
|
GNUNET_assert (! kyc.ok);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user