merge changelog
This commit is contained in:
commit
9fffeee4ef
@ -1,3 +1,10 @@
|
|||||||
|
Thu Jan 4 11:55:41 CET 2018
|
||||||
|
Fix issue #5234 (aggregator ignoring refunds).
|
||||||
|
Misc. minor fixes to the auditor. -CG
|
||||||
|
|
||||||
|
Mon Jan 1 23:15:37 CET 2018
|
||||||
|
Add TALER_EXCHANGE_refund2() API call to libtalerexchange. -CG
|
||||||
|
|
||||||
Thu Dec 14 15:32:50 CET 2017
|
Thu Dec 14 15:32:50 CET 2017
|
||||||
Replaced taler-exchange-reservemod tool with new taler-bank-transfer
|
Replaced taler-exchange-reservemod tool with new taler-bank-transfer
|
||||||
tool (#5195). Removed /admin/add/incoming API, replaced by new
|
tool (#5195). Removed /admin/add/incoming API, replaced by new
|
||||||
|
@ -102,8 +102,7 @@ making wire transfers that have been due.
|
|||||||
|
|
||||||
The total amount the exchange currently lags behind is
|
The total amount the exchange currently lags behind is
|
||||||
{\bf {{ wire.total_amount_lag.value }}.{{ wire.total_amount_lag.fraction }}
|
{\bf {{ wire.total_amount_lag.value }}.{{ wire.total_amount_lag.fraction }}
|
||||||
{{ wire.total_amount_lag.currency }}
|
{{ wire.total_amount_lag.currency }}}.
|
||||||
}.
|
|
||||||
|
|
||||||
Note that some lag is perfectly normal, as tiny amounts that are too small to be wired
|
Note that some lag is perfectly normal, as tiny amounts that are too small to be wired
|
||||||
are deferred beyond the due date, hoping that additional transfers will push them above
|
are deferred beyond the due date, hoping that additional transfers will push them above
|
||||||
@ -210,7 +209,7 @@ the financial damage done to the customer).
|
|||||||
{% if data.amount_arithmetic_inconsistencies|length() == 0 %}
|
{% if data.amount_arithmetic_inconsistencies|length() == 0 %}
|
||||||
{\bf No arithmetic problems detected.}
|
{\bf No arithmetic problems detected.}
|
||||||
{% else %}
|
{% else %}
|
||||||
\begin{longtable}{p{4.5cm}|l|rl|rl}
|
\begin{longtable}{p{3.5cm}|l|rl|rl}
|
||||||
{\bf Operation} & {\bf Table row} & \multicolumn{2}{|c|}{ {\bf Exchange}} & \multicolumn{2}{|c}{ {\bf Auditor}} \\
|
{\bf Operation} & {\bf Table row} & \multicolumn{2}{|c|}{ {\bf Exchange}} & \multicolumn{2}{|c}{ {\bf Auditor}} \\
|
||||||
\hline \hline
|
\hline \hline
|
||||||
\endfirsthead
|
\endfirsthead
|
||||||
@ -219,11 +218,11 @@ the financial damage done to the customer).
|
|||||||
\hline \hline
|
\hline \hline
|
||||||
{\bf Operation} & {\bf Table row} & \multicolumn{2}{|c|}{ {\bf Exchange}} & \multicolumn{2}{|c}{ {\bf Auditor}} \\
|
{\bf Operation} & {\bf Table row} & \multicolumn{2}{|c|}{ {\bf Exchange}} & \multicolumn{2}{|c}{ {\bf Auditor}} \\
|
||||||
\endfoot
|
\endfoot
|
||||||
\hline
|
\hline \hline
|
||||||
{\bf Total} & &
|
\multicolumn{2}{l|}{ {\bf $\sum$ Deltas (Auditor-Exchange)} } &
|
||||||
{{ data.total_arithmetic_delta_plus.value }}.{{ data.total_arithmetic_delta_plus.fraction }} &
|
+ {{ data.total_arithmetic_delta_plus.value }}.{{ data.total_arithmetic_delta_plus.fraction }} &
|
||||||
{{ data.total_arithmetic_delta_plus.currency }} &
|
{{ data.total_arithmetic_delta_plus.currency }} &
|
||||||
{{ data.total_arithmetic_delta_minus.value }}.{{ data.total_arithmetic_delta_minus.fraction }} &
|
- {{ data.total_arithmetic_delta_minus.value }}.{{ data.total_arithmetic_delta_minus.fraction }} &
|
||||||
{{ data.total_arithmetic_delta_minus.currency }} \\
|
{{ data.total_arithmetic_delta_minus.currency }} \\
|
||||||
\caption{Arithmetic inconsistencies.}
|
\caption{Arithmetic inconsistencies.}
|
||||||
\label{table:amount:arithmetic:inconsistencies}
|
\label{table:amount:arithmetic:inconsistencies}
|
||||||
@ -328,17 +327,17 @@ any effects on its own balance, those entries are excluded from the total.
|
|||||||
{% if data.coin_inconsistencies|length() == 0 %}
|
{% if data.coin_inconsistencies|length() == 0 %}
|
||||||
{\bf All coin histories were unproblematic.}
|
{\bf All coin histories were unproblematic.}
|
||||||
{% else %}
|
{% else %}
|
||||||
\begin{longtable}{l|p{5.5cm}|rl|rl}
|
\begin{longtable}{p{1.8cm}|p{3cm}|rl|rl}
|
||||||
{\bf Operation} & {\bf Coin public key} & \multicolumn{2}{|c|}{ {\bf Exchange}} & \multicolumn{2}{|c|}{ {\bf Auditor}} \\
|
{\bf Operation} & {\bf Coin public key} & \multicolumn{2}{|c|}{ {\bf Exchange}} & \multicolumn{2}{|c}{ {\bf Auditor}} \\
|
||||||
\hline \hline
|
\hline \hline
|
||||||
\endfirsthead
|
\endfirsthead
|
||||||
{\bf Operation} & {\bf Coin public key} & \multicolumn{2}{|c|}{ {\bf Exchange}} & \multicolumn{2}{|c|}{ {\bf Auditor}} \\ \hline \hline
|
{\bf Operation} & {\bf Coin public key} & \multicolumn{2}{|c|}{ {\bf Exchange}} & \multicolumn{2}{|c}{ {\bf Auditor}} \\ \hline \hline
|
||||||
\endhead
|
\endhead
|
||||||
\hline \hline
|
\hline \hline
|
||||||
{\bf Operation} & {\bf Coin public key} & \multicolumn{2}{|c|}{ {\bf Exchange}} & \multicolumn{2}{|c|}{ {\bf Auditor}} \\
|
{\bf Operation} & {\bf Coin public key} & \multicolumn{2}{|c|}{ {\bf Exchange}} & \multicolumn{2}{|c}{ {\bf Auditor}} \\
|
||||||
\endfoot
|
\endfoot
|
||||||
\hline
|
\hline
|
||||||
{\bf Total} & &
|
\multicolumn{2}{l|}{ $\sum$ {\bf Delta (Auditor-Exchange)} } &
|
||||||
{{ data.total_coin_delta_plus.value }}.{{ data.total_coin_delta_plus.fraction }} &
|
{{ data.total_coin_delta_plus.value }}.{{ data.total_coin_delta_plus.fraction }} &
|
||||||
{{ data.total_coin_delta_plus.currency }} &
|
{{ data.total_coin_delta_plus.currency }} &
|
||||||
- {{ data.total_coin_delta_minus.value }}.{{ data.total_coin_delta_minus.fraction }} &
|
- {{ data.total_coin_delta_minus.value }}.{{ data.total_coin_delta_minus.fraction }} &
|
||||||
@ -593,7 +592,7 @@ have a clear financial impact.
|
|||||||
\hline
|
\hline
|
||||||
{\bf Table} & {\bf Row} & {\bf Diagnostic} \\
|
{\bf Table} & {\bf Row} & {\bf Diagnostic} \\
|
||||||
\caption{Other wire table issues found (by table and row).}
|
\caption{Other wire table issues found (by table and row).}
|
||||||
\label{table:misc}
|
\label{table:wire:misc}
|
||||||
\endlastfoot
|
\endlastfoot
|
||||||
{% for item in wire.row_inconsistencies %}
|
{% for item in wire.row_inconsistencies %}
|
||||||
\verb! {{ item.table }} ! &
|
\verb! {{ item.table }} ! &
|
||||||
@ -687,7 +686,7 @@ impact.
|
|||||||
{% if data.row_inconsistencies|length() == 0 %}
|
{% if data.row_inconsistencies|length() == 0 %}
|
||||||
{\bf No row inconsistencies found.}
|
{\bf No row inconsistencies found.}
|
||||||
{% else %}
|
{% else %}
|
||||||
\begin{longtable}{p{1.5cm}|l|p{5.5}}
|
\begin{longtable}{p{1.5cm}|l|p{5.5cm}}
|
||||||
{\bf Table} & {\bf Row} & {\bf Diagnostic} \\
|
{\bf Table} & {\bf Row} & {\bf Diagnostic} \\
|
||||||
\hline \hline
|
\hline \hline
|
||||||
\endfirsthead
|
\endfirsthead
|
||||||
@ -697,13 +696,13 @@ impact.
|
|||||||
\hline \hline
|
\hline \hline
|
||||||
{\bf Table} & {\bf Row} & {\bf Diagnostic} \\
|
{\bf Table} & {\bf Row} & {\bf Diagnostic} \\
|
||||||
\endfoot
|
\endfoot
|
||||||
\hline
|
\hline \hline
|
||||||
{\bf Table} & {\bf Row} & {\bf Diagnostic} \\
|
{\bf Table} & {\bf Row} & {\bf Diagnostic} \\
|
||||||
\caption{Other issues found (by table and row).}
|
\caption{Other issues found (by table and row).}
|
||||||
\label{table:misc}
|
\label{table:misc}
|
||||||
\endlastfoot
|
\endlastfoot
|
||||||
{% for item in data.row_inconsistencies %}
|
{% for item in data.row_inconsistencies %}
|
||||||
{{ item.table }} &
|
\verb! {{ item.table }} ! &
|
||||||
{{ item.row }} &
|
{{ item.row }} &
|
||||||
{{ item.diagnostic }} \\ \hline
|
{{ item.diagnostic }} \\ \hline
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -728,12 +727,12 @@ reserve expired.
|
|||||||
{\bf All expired reserves were closed.}
|
{\bf All expired reserves were closed.}
|
||||||
{% else %}
|
{% else %}
|
||||||
\begin{longtable}{p{1.5cm}|c|rl}
|
\begin{longtable}{p{1.5cm}|c|rl}
|
||||||
{\bf Reserve} & {\bf Expired} & \multicolumn{2}{|c|}{ {\bf Balance}} \\ \hline \hline
|
{\bf Reserve} & {\bf Expired} & \multicolumn{2}{|c}{ {\bf Balance}} \\ \hline \hline
|
||||||
\endfirsthead
|
\endfirsthead
|
||||||
{\bf Reserve} & {\bf Expired} & \multicolumn{2}{|c|}{ {\bf Balance}} \\ \hline \hline
|
{\bf Reserve} & {\bf Expired} & \multicolumn{2}{|c}{ {\bf Balance}} \\ \hline \hline
|
||||||
\endhead
|
\endhead
|
||||||
\hline \hline
|
\hline \hline
|
||||||
{\bf Reserve} & {\bf Expired} & \multicolumn{2}{|c|}{ {\bf Balance}}
|
{\bf Reserve} & {\bf Expired} & \multicolumn{2}{|c}{ {\bf Balance}}
|
||||||
\endfoot
|
\endfoot
|
||||||
\hline
|
\hline
|
||||||
{\bf Sum} & &
|
{\bf Sum} & &
|
||||||
@ -854,7 +853,7 @@ This section lists issues with wire transfers related to timestamps.
|
|||||||
\label{table:wire:bad_time}
|
\label{table:wire:bad_time}
|
||||||
\endlastfoot
|
\endlastfoot
|
||||||
{% for item in wire.row_minor_inconsistencies %}
|
{% for item in wire.row_minor_inconsistencies %}
|
||||||
{\tt {{ item.table }} } & {{ item.row }} & {{ item.diagnostic }} \\ \hline
|
\verb! {{ item.table }} ! & {{ item.row }} & {{ item.diagnostic }} \\ \hline
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
\end{longtable}
|
\end{longtable}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -391,7 +391,7 @@ report_amount_arithmetic_inconsistency (const char *operation,
|
|||||||
"profitable", (json_int_t) profitable));
|
"profitable", (json_int_t) profitable));
|
||||||
if (0 != profitable)
|
if (0 != profitable)
|
||||||
{
|
{
|
||||||
target = profitable
|
target = (1 == profitable)
|
||||||
? &total_arithmetic_delta_plus
|
? &total_arithmetic_delta_plus
|
||||||
: &total_arithmetic_delta_minus;
|
: &total_arithmetic_delta_minus;
|
||||||
GNUNET_break (GNUNET_OK ==
|
GNUNET_break (GNUNET_OK ==
|
||||||
@ -452,7 +452,7 @@ report_coin_arithmetic_inconsistency (const char *operation,
|
|||||||
"profitable", (json_int_t) profitable));
|
"profitable", (json_int_t) profitable));
|
||||||
if (0 != profitable)
|
if (0 != profitable)
|
||||||
{
|
{
|
||||||
target = profitable
|
target = (1 == profitable)
|
||||||
? &total_coin_delta_plus
|
? &total_coin_delta_plus
|
||||||
: &total_coin_delta_minus;
|
: &total_coin_delta_minus;
|
||||||
GNUNET_break (GNUNET_OK ==
|
GNUNET_break (GNUNET_OK ==
|
||||||
@ -1664,10 +1664,15 @@ struct WireFeeInfo
|
|||||||
struct GNUNET_TIME_Absolute end_date;
|
struct GNUNET_TIME_Absolute end_date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How high is the fee.
|
* How high is the wire fee.
|
||||||
*/
|
*/
|
||||||
struct TALER_Amount wire_fee;
|
struct TALER_Amount wire_fee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How high is the closing fee.
|
||||||
|
*/
|
||||||
|
struct TALER_Amount closing_fee;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1697,11 +1702,6 @@ struct AggregationContext
|
|||||||
*/
|
*/
|
||||||
struct WireFeeInfo *fee_tail;
|
struct WireFeeInfo *fee_tail;
|
||||||
|
|
||||||
/**
|
|
||||||
* How much did we make in aggregation fees.
|
|
||||||
*/
|
|
||||||
struct TALER_Amount total_aggregation_feesX;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Final result status.
|
* Final result status.
|
||||||
*/
|
*/
|
||||||
@ -1798,7 +1798,6 @@ struct WireCheckContext
|
|||||||
* @param dki denomination information about the coin
|
* @param dki denomination information about the coin
|
||||||
* @param tl_head head of transaction history to verify
|
* @param tl_head head of transaction history to verify
|
||||||
* @param[out] merchant_gain amount the coin contributes to the wire transfer to the merchant
|
* @param[out] merchant_gain amount the coin contributes to the wire transfer to the merchant
|
||||||
* @param[out] merchant_fees fees the exchange charged the merchant for the transaction(s)
|
|
||||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -1807,14 +1806,16 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|||||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
const struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki,
|
const struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki,
|
||||||
const struct TALER_EXCHANGEDB_TransactionList *tl_head,
|
const struct TALER_EXCHANGEDB_TransactionList *tl_head,
|
||||||
struct TALER_Amount *merchant_gain,
|
struct TALER_Amount *merchant_gain)
|
||||||
struct TALER_Amount *merchant_fees)
|
|
||||||
{
|
{
|
||||||
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 value;
|
struct TALER_Amount value;
|
||||||
struct TALER_Amount merchant_loss;
|
struct TALER_Amount merchant_loss;
|
||||||
|
struct TALER_Amount merchant_delta;
|
||||||
|
const struct TALER_Amount *deposit_fee;
|
||||||
|
int 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",
|
||||||
@ -1830,9 +1831,6 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_amount_get_zero (currency,
|
TALER_amount_get_zero (currency,
|
||||||
merchant_gain));
|
merchant_gain));
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_get_zero (currency,
|
|
||||||
merchant_fees));
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_amount_get_zero (currency,
|
TALER_amount_get_zero (currency,
|
||||||
&merchant_loss));
|
&merchant_loss));
|
||||||
@ -1840,6 +1838,8 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|||||||
know the order, so instead of subtracting we compute positive
|
know the order, so instead of subtracting we compute positive
|
||||||
(deposit, melt) and negative (refund) values separately here,
|
(deposit, melt) and negative (refund) values separately here,
|
||||||
and then subtract the negative from the positive after the loop. */
|
and then subtract the negative from the positive after the loop. */
|
||||||
|
refund_deposit_fee = GNUNET_NO;
|
||||||
|
deposit_fee = NULL;
|
||||||
for (const struct TALER_EXCHANGEDB_TransactionList *tl = tl_head;NULL != tl;tl = tl->next)
|
for (const struct TALER_EXCHANGEDB_TransactionList *tl = tl_head;NULL != tl;tl = tl->next)
|
||||||
{
|
{
|
||||||
const struct TALER_Amount *amount_with_fee;
|
const struct TALER_Amount *amount_with_fee;
|
||||||
@ -1871,7 +1871,7 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|||||||
{
|
{
|
||||||
struct TALER_Amount amount_without_fee;
|
struct TALER_Amount amount_without_fee;
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
TALER_amount_subtract (&amount_without_fee,
|
TALER_amount_subtract (&amount_without_fee,
|
||||||
amount_with_fee,
|
amount_with_fee,
|
||||||
fee))
|
fee))
|
||||||
@ -1890,14 +1890,7 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"Detected applicable deposit of %s\n",
|
"Detected applicable deposit of %s\n",
|
||||||
TALER_amount2s (&amount_without_fee));
|
TALER_amount2s (&amount_without_fee));
|
||||||
if (GNUNET_OK !=
|
deposit_fee = fee;
|
||||||
TALER_amount_add (merchant_fees,
|
|
||||||
merchant_fees,
|
|
||||||
fee))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Check that the fees given in the transaction list and in dki match */
|
/* Check that the fees given in the transaction list and in dki match */
|
||||||
TALER_amount_ntoh (&tmp,
|
TALER_amount_ntoh (&tmp,
|
||||||
@ -1975,14 +1968,7 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"Detected applicable refund of %s\n",
|
"Detected applicable refund of %s\n",
|
||||||
TALER_amount2s (amount_with_fee));
|
TALER_amount2s (amount_with_fee));
|
||||||
if (GNUNET_OK !=
|
refund_deposit_fee = GNUNET_YES;
|
||||||
TALER_amount_add (merchant_fees,
|
|
||||||
merchant_fees,
|
|
||||||
fee))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Check that the fees given in the transaction list and in dki match */
|
/* Check that the fees given in the transaction list and in dki match */
|
||||||
TALER_amount_ntoh (&tmp,
|
TALER_amount_ntoh (&tmp,
|
||||||
@ -2008,9 +1994,19 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* for 'tl' */
|
} /* for 'tl' */
|
||||||
|
|
||||||
|
if ( (GNUNET_YES == refund_deposit_fee) &&
|
||||||
|
(NULL != deposit_fee) )
|
||||||
|
{
|
||||||
|
/* We had a /deposit operation AND a /refund operation,
|
||||||
|
and should thus not charge the merchant the /deposit fee */
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (merchant_gain,
|
||||||
|
merchant_gain,
|
||||||
|
deposit_fee));
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate total balance change, i.e. expenditures minus refunds */
|
/* Calculate total balance change, i.e. expenditures minus refunds */
|
||||||
if (GNUNET_SYSERR ==
|
if (GNUNET_SYSERR ==
|
||||||
TALER_amount_subtract (&spent,
|
TALER_amount_subtract (&spent,
|
||||||
@ -2022,7 +2018,7 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|||||||
coin_pub,
|
coin_pub,
|
||||||
&expenditures,
|
&expenditures,
|
||||||
&refunds,
|
&refunds,
|
||||||
0);
|
1);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2041,9 +2037,10 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally, update @a merchant_gain by subtracting what he "lost" from refunds */
|
/* Finally, update @a merchant_gain by subtracting what he "lost"
|
||||||
|
from refunds */
|
||||||
if (GNUNET_SYSERR ==
|
if (GNUNET_SYSERR ==
|
||||||
TALER_amount_subtract (merchant_gain,
|
TALER_amount_subtract (&merchant_delta,
|
||||||
merchant_gain,
|
merchant_gain,
|
||||||
&merchant_loss))
|
&merchant_loss))
|
||||||
{
|
{
|
||||||
@ -2052,9 +2049,10 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|||||||
coin_pub,
|
coin_pub,
|
||||||
merchant_gain,
|
merchant_gain,
|
||||||
&merchant_loss,
|
&merchant_loss,
|
||||||
0);
|
1);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
*merchant_gain = merchant_delta;
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"Coin %s contributes %s to contract %s\n",
|
"Coin %s contributes %s to contract %s\n",
|
||||||
TALER_B2S (coin_pub),
|
TALER_B2S (coin_pub),
|
||||||
@ -2077,7 +2075,8 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|||||||
* @param h_contract_terms which proposal was this payment about
|
* @param h_contract_terms which proposal was this payment about
|
||||||
* @param coin_pub which public key was this payment about
|
* @param coin_pub which public key was this payment about
|
||||||
* @param coin_value amount contributed by this coin in total (with fee)
|
* @param coin_value amount contributed by this coin in total (with fee)
|
||||||
* @param coin_fee applicable fee for this coin
|
* @param deposit_fee applicable deposit fee for this coin, actual
|
||||||
|
* fees charged may differ if coin was refunded
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
wire_transfer_information_cb (void *cls,
|
wire_transfer_information_cb (void *cls,
|
||||||
@ -2089,12 +2088,11 @@ wire_transfer_information_cb (void *cls,
|
|||||||
const struct GNUNET_HashCode *h_contract_terms,
|
const struct GNUNET_HashCode *h_contract_terms,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
const struct TALER_Amount *coin_value,
|
const struct TALER_Amount *coin_value,
|
||||||
const struct TALER_Amount *coin_fee)
|
const struct TALER_Amount *deposit_fee)
|
||||||
{
|
{
|
||||||
struct WireCheckContext *wcc = cls;
|
struct WireCheckContext *wcc = cls;
|
||||||
const struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
|
const struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
|
||||||
struct TALER_Amount computed_value;
|
struct TALER_Amount computed_value;
|
||||||
struct TALER_Amount computed_fees;
|
|
||||||
struct TALER_Amount coin_value_without_fee;
|
struct TALER_Amount coin_value_without_fee;
|
||||||
struct TALER_EXCHANGEDB_TransactionList *tl;
|
struct TALER_EXCHANGEDB_TransactionList *tl;
|
||||||
const struct TALER_CoinPublicInfo *coin;
|
const struct TALER_CoinPublicInfo *coin;
|
||||||
@ -2156,18 +2154,17 @@ wire_transfer_information_cb (void *cls,
|
|||||||
merchant_pub,
|
merchant_pub,
|
||||||
dki,
|
dki,
|
||||||
tl,
|
tl,
|
||||||
&computed_value,
|
&computed_value);
|
||||||
&computed_fees);
|
|
||||||
if (GNUNET_SYSERR ==
|
if (GNUNET_SYSERR ==
|
||||||
TALER_amount_subtract (&coin_value_without_fee,
|
TALER_amount_subtract (&coin_value_without_fee,
|
||||||
coin_value,
|
coin_value,
|
||||||
coin_fee))
|
deposit_fee))
|
||||||
{
|
{
|
||||||
wcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
|
wcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
report_amount_arithmetic_inconsistency ("aggregation (fee structure)",
|
report_amount_arithmetic_inconsistency ("aggregation (fee structure)",
|
||||||
rowid,
|
rowid,
|
||||||
coin_value,
|
coin_value,
|
||||||
coin_fee,
|
deposit_fee,
|
||||||
-1);
|
-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2182,17 +2179,6 @@ wire_transfer_information_cb (void *cls,
|
|||||||
&computed_value,
|
&computed_value,
|
||||||
-1);
|
-1);
|
||||||
}
|
}
|
||||||
if (0 !=
|
|
||||||
TALER_amount_cmp (&computed_fees,
|
|
||||||
coin_fee))
|
|
||||||
{
|
|
||||||
wcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
report_amount_arithmetic_inconsistency ("aggregation (fee)",
|
|
||||||
rowid,
|
|
||||||
coin_fee,
|
|
||||||
&computed_fees,
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
edb->free_coin_transaction_list (edb->cls,
|
edb->free_coin_transaction_list (edb->cls,
|
||||||
tl);
|
tl);
|
||||||
|
|
||||||
@ -2276,6 +2262,7 @@ get_wire_fee (struct AggregationContext *ac,
|
|||||||
&wfi->start_date,
|
&wfi->start_date,
|
||||||
&wfi->end_date,
|
&wfi->end_date,
|
||||||
&wfi->wire_fee,
|
&wfi->wire_fee,
|
||||||
|
&wfi->closing_fee,
|
||||||
&master_sig))
|
&master_sig))
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
@ -2299,6 +2286,8 @@ get_wire_fee (struct AggregationContext *ac,
|
|||||||
wp.end_date = GNUNET_TIME_absolute_hton (wfi->end_date);
|
wp.end_date = GNUNET_TIME_absolute_hton (wfi->end_date);
|
||||||
TALER_amount_hton (&wp.wire_fee,
|
TALER_amount_hton (&wp.wire_fee,
|
||||||
&wfi->wire_fee);
|
&wfi->wire_fee);
|
||||||
|
TALER_amount_hton (&wp.closing_fee,
|
||||||
|
&wfi->closing_fee);
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_FEES,
|
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_FEES,
|
||||||
&wp.purpose,
|
&wp.purpose,
|
||||||
|
@ -613,7 +613,7 @@ handle_reject (struct TALER_FAKEBANK_Handle *h,
|
|||||||
if (GNUNET_OK != found)
|
if (GNUNET_OK != found)
|
||||||
return create_bank_error (connection,
|
return create_bank_error (connection,
|
||||||
MHD_HTTP_NOT_FOUND,
|
MHD_HTTP_NOT_FOUND,
|
||||||
TALER_EC_BANK_REJECT_NOT_FOUND,
|
TALER_EC_BANK_REJECT_TRANSACTION_NOT_FOUND,
|
||||||
"transaction unknown");
|
"transaction unknown");
|
||||||
/* finally build regular response */
|
/* finally build regular response */
|
||||||
resp = MHD_create_response_from_buffer (0,
|
resp = MHD_create_response_from_buffer (0,
|
||||||
|
@ -454,7 +454,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange,
|
|||||||
" s:o," /* merchant_pub */
|
" s:o," /* merchant_pub */
|
||||||
" s:o, s:o," /* refund_deadline, wire_deadline */
|
" s:o, s:o," /* refund_deadline, wire_deadline */
|
||||||
" s:o}", /* coin_sig */
|
" s:o}", /* coin_sig */
|
||||||
"f", TALER_JSON_from_amount (amount),
|
"contribution", TALER_JSON_from_amount (amount),
|
||||||
"wire", wire_details,
|
"wire", wire_details,
|
||||||
"H_wire", GNUNET_JSON_from_data_auto (&h_wire),
|
"H_wire", GNUNET_JSON_from_data_auto (&h_wire),
|
||||||
"h_contract_terms", GNUNET_JSON_from_data_auto (h_contract_terms),
|
"h_contract_terms", GNUNET_JSON_from_data_auto (h_contract_terms),
|
||||||
|
@ -243,12 +243,8 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange,
|
|||||||
TALER_EXCHANGE_RefundResultCallback cb,
|
TALER_EXCHANGE_RefundResultCallback cb,
|
||||||
void *cb_cls)
|
void *cb_cls)
|
||||||
{
|
{
|
||||||
struct TALER_EXCHANGE_RefundHandle *rh;
|
|
||||||
struct GNUNET_CURL_Context *ctx;
|
|
||||||
struct TALER_RefundRequestPS rr;
|
struct TALER_RefundRequestPS rr;
|
||||||
struct TALER_MerchantSignatureP merchant_sig;
|
struct TALER_MerchantSignatureP merchant_sig;
|
||||||
json_t *refund_obj;
|
|
||||||
CURL *eh;
|
|
||||||
|
|
||||||
GNUNET_assert (GNUNET_YES ==
|
GNUNET_assert (GNUNET_YES ==
|
||||||
MAH_handle_is_ready (exchange));
|
MAH_handle_is_ready (exchange));
|
||||||
@ -267,7 +263,68 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange,
|
|||||||
GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv,
|
GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv,
|
||||||
&rr.purpose,
|
&rr.purpose,
|
||||||
&merchant_sig.eddsa_sig));
|
&merchant_sig.eddsa_sig));
|
||||||
refund_obj = json_pack ("{s:o, s:o," /* amount/fee */
|
return TALER_EXCHANGE_refund2 (exchange,
|
||||||
|
amount,
|
||||||
|
refund_fee,
|
||||||
|
h_contract_terms,
|
||||||
|
coin_pub,
|
||||||
|
rtransaction_id,
|
||||||
|
&rr.merchant,
|
||||||
|
&merchant_sig,
|
||||||
|
cb,
|
||||||
|
cb_cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit a refund request to the exchange and get the exchange's
|
||||||
|
* response. This API is used by a merchant. Note that
|
||||||
|
* while we return the response verbatim to the caller for further
|
||||||
|
* processing, we do already verify that the response is well-formed
|
||||||
|
* (i.e. that signatures included in the response are all valid). If
|
||||||
|
* the exchange's reply is not well-formed, we return an HTTP status code
|
||||||
|
* of zero to @a cb.
|
||||||
|
*
|
||||||
|
* The @a exchange must be ready to operate (i.e. have
|
||||||
|
* finished processing the /keys reply). If this check fails, we do
|
||||||
|
* NOT initiate the transaction with the exchange and instead return NULL.
|
||||||
|
*
|
||||||
|
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||||
|
* @param amount the amount to be refunded; must be larger than the refund fee
|
||||||
|
* (as that fee is still being subtracted), and smaller than the amount
|
||||||
|
* (with deposit fee) of the original deposit contribution of this coin
|
||||||
|
* @param refund_fee fee applicable to this coin for the refund
|
||||||
|
* @param h_contract_terms hash of the contact of the merchant with the customer that is being refunded
|
||||||
|
* @param coin_pub coin’s public key of the coin from the original deposit operation
|
||||||
|
* @param rtransaction_id transaction id for the transaction between merchant and customer (of refunding operation);
|
||||||
|
* this is needed as we may first do a partial refund and later a full refund. If both
|
||||||
|
* refunds are also over the same amount, we need the @a rtransaction_id to make the disjoint
|
||||||
|
* refund requests different (as requests are idempotent and otherwise the 2nd refund might not work).
|
||||||
|
* @param merchant_pub public key of the merchant
|
||||||
|
* @param merchant_sig signature affirming the refund from the merchant
|
||||||
|
* @param cb the callback to call when a reply for this request is available
|
||||||
|
* @param cb_cls closure for the above callback
|
||||||
|
* @return a handle for this request; NULL if the inputs are invalid (i.e.
|
||||||
|
* signatures fail to verify). In this case, the callback is not called.
|
||||||
|
*/
|
||||||
|
struct TALER_EXCHANGE_RefundHandle *
|
||||||
|
TALER_EXCHANGE_refund2 (struct TALER_EXCHANGE_Handle *exchange,
|
||||||
|
const struct TALER_Amount *amount,
|
||||||
|
const struct TALER_Amount *refund_fee,
|
||||||
|
const struct GNUNET_HashCode *h_contract_terms,
|
||||||
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
|
uint64_t rtransaction_id,
|
||||||
|
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
|
const struct TALER_MerchantSignatureP *merchant_sig,
|
||||||
|
TALER_EXCHANGE_RefundResultCallback cb,
|
||||||
|
void *cb_cls)
|
||||||
|
{
|
||||||
|
struct TALER_EXCHANGE_RefundHandle *rh;
|
||||||
|
struct GNUNET_CURL_Context *ctx;
|
||||||
|
json_t *refund_obj;
|
||||||
|
CURL *eh;
|
||||||
|
|
||||||
|
refund_obj = json_pack ("{s:o, s:o," /* amount/fee */
|
||||||
" s:o, s:o," /* h_contract_terms, coin_pub */
|
" s:o, s:o," /* h_contract_terms, coin_pub */
|
||||||
" s:I," /* rtransaction id */
|
" s:I," /* rtransaction id */
|
||||||
" s:o, s:o}", /* merchant_pub, merchant_sig */
|
" s:o, s:o}", /* merchant_pub, merchant_sig */
|
||||||
@ -276,8 +333,8 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange,
|
|||||||
"h_contract_terms", GNUNET_JSON_from_data_auto (h_contract_terms),
|
"h_contract_terms", GNUNET_JSON_from_data_auto (h_contract_terms),
|
||||||
"coin_pub", GNUNET_JSON_from_data_auto (coin_pub),
|
"coin_pub", GNUNET_JSON_from_data_auto (coin_pub),
|
||||||
"rtransaction_id", (json_int_t) rtransaction_id,
|
"rtransaction_id", (json_int_t) rtransaction_id,
|
||||||
"merchant_pub", GNUNET_JSON_from_data_auto (&rr.merchant),
|
"merchant_pub", GNUNET_JSON_from_data_auto (merchant_pub),
|
||||||
"merchant_sig", GNUNET_JSON_from_data_auto (&merchant_sig)
|
"merchant_sig", GNUNET_JSON_from_data_auto (merchant_sig)
|
||||||
);
|
);
|
||||||
if (NULL == refund_obj)
|
if (NULL == refund_obj)
|
||||||
{
|
{
|
||||||
@ -294,7 +351,7 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange,
|
|||||||
rh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND);
|
rh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND);
|
||||||
rh->depconf.h_contract_terms = *h_contract_terms;
|
rh->depconf.h_contract_terms = *h_contract_terms;
|
||||||
rh->depconf.coin_pub = *coin_pub;
|
rh->depconf.coin_pub = *coin_pub;
|
||||||
rh->depconf.merchant = rr.merchant;
|
rh->depconf.merchant = *merchant_pub;
|
||||||
rh->depconf.rtransaction_id = GNUNET_htonll (rtransaction_id);
|
rh->depconf.rtransaction_id = GNUNET_htonll (rtransaction_id);
|
||||||
TALER_amount_hton (&rh->depconf.refund_amount,
|
TALER_amount_hton (&rh->depconf.refund_amount,
|
||||||
amount);
|
amount);
|
||||||
|
@ -3562,6 +3562,65 @@ run (void *cls)
|
|||||||
.details.refund.fee = "EUR:0.01",
|
.details.refund.fee = "EUR:0.01",
|
||||||
.details.refund.deposit_ref = "deposit-refund-2",
|
.details.refund.deposit_ref = "deposit-refund-2",
|
||||||
},
|
},
|
||||||
|
{ .oc = OC_CHECK_BANK_TRANSFERS_EMPTY,
|
||||||
|
.label = "check-empty-after-refund" },
|
||||||
|
|
||||||
|
|
||||||
|
/* Test refunded coins are never executed, even past
|
||||||
|
refund deadline */
|
||||||
|
{ .oc = OC_ADMIN_ADD_INCOMING,
|
||||||
|
.label = "create-reserve-rb",
|
||||||
|
.expected_response_code = MHD_HTTP_OK,
|
||||||
|
.details.admin_add_incoming.debit_account_no = 42,
|
||||||
|
.details.admin_add_incoming.credit_account_no = EXCHANGE_ACCOUNT_NO,
|
||||||
|
.details.admin_add_incoming.auth_username = "user42",
|
||||||
|
.details.admin_add_incoming.auth_password = "pass42",
|
||||||
|
.details.admin_add_incoming.amount = "EUR:5.01" },
|
||||||
|
/* Run wirewatch to observe /admin/add/incoming */
|
||||||
|
{ .oc = OC_RUN_WIREWATCH,
|
||||||
|
.label = "wirewatch-3b" },
|
||||||
|
/* Withdraw a 5 EUR coin, at fee of 1 ct */
|
||||||
|
{ .oc = OC_WITHDRAW_SIGN,
|
||||||
|
.label = "withdraw-coin-rb",
|
||||||
|
.expected_response_code = MHD_HTTP_OK,
|
||||||
|
.details.reserve_withdraw.reserve_reference = "create-reserve-rb",
|
||||||
|
.details.reserve_withdraw.amount = "EUR:5" },
|
||||||
|
/* Spend 5 EUR of the 5 EUR coin (in full)
|
||||||
|
(merchant would receive EUR:4.99 due to 1 ct deposit fee) */
|
||||||
|
{ .oc = OC_DEPOSIT,
|
||||||
|
.label = "deposit-refund-1b",
|
||||||
|
.expected_response_code = MHD_HTTP_OK,
|
||||||
|
.details.deposit.amount = "EUR:5",
|
||||||
|
.details.deposit.coin_ref = "withdraw-coin-rb",
|
||||||
|
.details.deposit.wire_details = "{ \"type\":\"test\", \"bank_uri\":\"http://localhost:8082/\", \"account_number\":42 }",
|
||||||
|
.details.deposit.contract_terms = "{ \"items\" : [ { \"name\":\"ice cream\", \"value\":\"EUR:5\" } ] }",
|
||||||
|
.details.deposit.refund_deadline = { 0 },
|
||||||
|
},
|
||||||
|
{ .oc = OC_CHECK_BANK_TRANSFER,
|
||||||
|
.label = "check_bank_transfer-aai-3b",
|
||||||
|
.details.check_bank_transfer.exchange_base_url = "https://exchange.com/",
|
||||||
|
.details.check_bank_transfer.amount = "EUR:5.01",
|
||||||
|
.details.check_bank_transfer.account_debit = 42,
|
||||||
|
.details.check_bank_transfer.account_credit = 2
|
||||||
|
},
|
||||||
|
/* Trigger refund (before aggregator had a chance to execute
|
||||||
|
deposit, even though refund deadline was zero) */
|
||||||
|
{ .oc = OC_REFUND,
|
||||||
|
.label = "refund-ok-fast",
|
||||||
|
.expected_response_code = MHD_HTTP_OK,
|
||||||
|
.details.refund.amount = "EUR:5",
|
||||||
|
.details.refund.fee = "EUR:0.01",
|
||||||
|
.details.refund.deposit_ref = "deposit-refund-1b",
|
||||||
|
},
|
||||||
|
/* Run transfers. This will do the transfer as refund deadline
|
||||||
|
was 0, except of course because the refund succeeded, the
|
||||||
|
transfer should no longer be done. */
|
||||||
|
{ .oc = OC_RUN_AGGREGATOR,
|
||||||
|
.label = "run-aggregator-3b" },
|
||||||
|
/* check that aggregator didn't do anything, as expected */
|
||||||
|
{ .oc = OC_CHECK_BANK_TRANSFERS_EMPTY,
|
||||||
|
.label = "check-refund-fast-not-run" },
|
||||||
|
|
||||||
|
|
||||||
/* ************** End of refund API testing************* */
|
/* ************** End of refund API testing************* */
|
||||||
|
|
||||||
|
@ -123,6 +123,11 @@ struct AggregationUnit
|
|||||||
*/
|
*/
|
||||||
struct GNUNET_HashCode h_wire;
|
struct GNUNET_HashCode h_wire;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash code of contract we are currently looking into.
|
||||||
|
*/
|
||||||
|
const struct GNUNET_HashCode *h_contract;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wire transfer identifier we use.
|
* Wire transfer identifier we use.
|
||||||
*/
|
*/
|
||||||
@ -374,6 +379,7 @@ update_fees (struct WirePlugin *wp,
|
|||||||
p->start_date,
|
p->start_date,
|
||||||
p->end_date,
|
p->end_date,
|
||||||
&p->wire_fee,
|
&p->wire_fee,
|
||||||
|
&p->closing_fee,
|
||||||
&p->master_sig);
|
&p->master_sig);
|
||||||
if (qs < 0)
|
if (qs < 0)
|
||||||
{
|
{
|
||||||
@ -567,6 +573,53 @@ exchange_serve_process_config ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback invoked with information about refunds applicable
|
||||||
|
* to a particular coin. Subtract refunded amount(s) from
|
||||||
|
* the aggregation unit's total amount.
|
||||||
|
*
|
||||||
|
* @param cls closure with a `struct AggregationUnit *`
|
||||||
|
* @param merchant_pub public key of merchant who authorized refund
|
||||||
|
* @param merchant_sig signature of merchant authorizing refund
|
||||||
|
* @param h_contract hash of contract being refunded
|
||||||
|
* @param rtransaction_id refund transaction ID
|
||||||
|
* @param amount_with_fee amount being refunded
|
||||||
|
* @param refund_fee fee the exchange keeps for the refund processing
|
||||||
|
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
refund_by_coin_cb (void *cls,
|
||||||
|
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
|
const struct TALER_MerchantSignatureP *merchant_sig,
|
||||||
|
const struct GNUNET_HashCode *h_contract,
|
||||||
|
uint64_t rtransaction_id,
|
||||||
|
const struct TALER_Amount *amount_with_fee,
|
||||||
|
const struct TALER_Amount *refund_fee)
|
||||||
|
{
|
||||||
|
struct AggregationUnit *au = cls;
|
||||||
|
|
||||||
|
/* TODO: potential optimization: include these conditions
|
||||||
|
in the SELECT! */
|
||||||
|
if (0 != memcmp (merchant_pub,
|
||||||
|
&au->merchant_pub,
|
||||||
|
sizeof (struct TALER_MerchantPublicKeyP)))
|
||||||
|
return GNUNET_OK; /* different merchant */
|
||||||
|
if (0 != memcmp (h_contract,
|
||||||
|
au->h_contract,
|
||||||
|
sizeof (struct GNUNET_HashCode)))
|
||||||
|
return GNUNET_OK; /* different contract */
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
TALER_amount_subtract (&au->total_amount,
|
||||||
|
&au->total_amount,
|
||||||
|
amount_with_fee))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called with details about deposits that have been made,
|
* Function called with details about deposits that have been made,
|
||||||
* with the goal of executing the corresponding wire transaction.
|
* with the goal of executing the corresponding wire transaction.
|
||||||
@ -609,6 +662,20 @@ deposit_cb (void *cls,
|
|||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
}
|
}
|
||||||
au->row_id = row_id;
|
au->row_id = row_id;
|
||||||
|
|
||||||
|
au->h_contract = h_contract_terms;
|
||||||
|
qs = db_plugin->select_refunds_by_coin (db_plugin->cls,
|
||||||
|
au->session,
|
||||||
|
coin_pub,
|
||||||
|
&refund_by_coin_cb,
|
||||||
|
au);
|
||||||
|
au->h_contract = NULL;
|
||||||
|
if (0 > qs)
|
||||||
|
{
|
||||||
|
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
|
||||||
GNUNET_assert (NULL == au->wire);
|
GNUNET_assert (NULL == au->wire);
|
||||||
au->wire = json_incref ((json_t *) wire);
|
au->wire = json_incref ((json_t *) wire);
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
@ -730,6 +797,20 @@ aggregate_cb (void *cls,
|
|||||||
/* Skip this one, but keep going! */
|
/* Skip this one, but keep going! */
|
||||||
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
au->h_contract = h_contract_terms;
|
||||||
|
qs = db_plugin->select_refunds_by_coin (db_plugin->cls,
|
||||||
|
au->session,
|
||||||
|
coin_pub,
|
||||||
|
&refund_by_coin_cb,
|
||||||
|
au);
|
||||||
|
au->h_contract = NULL;
|
||||||
|
if (0 > qs)
|
||||||
|
{
|
||||||
|
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
|
||||||
if (au->rows_offset >= aggregation_limit)
|
if (au->rows_offset >= aggregation_limit)
|
||||||
{
|
{
|
||||||
/* Bug: we asked for at most #aggregation_limit results! */
|
/* Bug: we asked for at most #aggregation_limit results! */
|
||||||
|
@ -149,6 +149,8 @@ deposit_transaction (void *cls,
|
|||||||
{
|
{
|
||||||
struct TALER_Amount amount_without_fee;
|
struct TALER_Amount amount_without_fee;
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"/deposit replay, accepting again!\n");
|
||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_amount_subtract (&amount_without_fee,
|
TALER_amount_subtract (&amount_without_fee,
|
||||||
&deposit->amount_with_fee,
|
&deposit->amount_with_fee,
|
||||||
@ -191,6 +193,8 @@ deposit_transaction (void *cls,
|
|||||||
if (0 < TALER_amount_cmp (&spent,
|
if (0 < TALER_amount_cmp (&spent,
|
||||||
&dc->value))
|
&dc->value))
|
||||||
{
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"Deposited coin has insufficient funds left!\n");
|
||||||
*mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection,
|
*mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection,
|
||||||
TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS,
|
TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS,
|
||||||
tl);
|
tl);
|
||||||
@ -376,7 +380,7 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
|
|||||||
struct GNUNET_HashCode my_h_wire;
|
struct GNUNET_HashCode my_h_wire;
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
GNUNET_JSON_spec_json ("wire", &wire),
|
GNUNET_JSON_spec_json ("wire", &wire),
|
||||||
TALER_JSON_spec_amount ("f", &deposit.amount_with_fee),
|
TALER_JSON_spec_amount ("contribution", &deposit.amount_with_fee),
|
||||||
TALER_JSON_spec_denomination_public_key ("denom_pub", &deposit.coin.denom_pub),
|
TALER_JSON_spec_denomination_public_key ("denom_pub", &deposit.coin.denom_pub),
|
||||||
TALER_JSON_spec_denomination_signature ("ub_sig", &deposit.coin.denom_sig),
|
TALER_JSON_spec_denomination_signature ("ub_sig", &deposit.coin.denom_sig),
|
||||||
GNUNET_JSON_spec_fixed_auto ("coin_pub", &deposit.coin.coin_pub),
|
GNUNET_JSON_spec_fixed_auto ("coin_pub", &deposit.coin.coin_pub),
|
||||||
|
@ -285,7 +285,6 @@ refund_transaction (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check if we already send the money for the /deposit */
|
/* check if we already send the money for the /deposit */
|
||||||
// FIXME: DB API...
|
|
||||||
qs = TEH_plugin->test_deposit_done (TEH_plugin->cls,
|
qs = TEH_plugin->test_deposit_done (TEH_plugin->cls,
|
||||||
session,
|
session,
|
||||||
dep);
|
dep);
|
||||||
|
@ -352,6 +352,7 @@ track_transfer_transaction (void *cls,
|
|||||||
struct GNUNET_TIME_Absolute wire_fee_start_date;
|
struct GNUNET_TIME_Absolute wire_fee_start_date;
|
||||||
struct GNUNET_TIME_Absolute wire_fee_end_date;
|
struct GNUNET_TIME_Absolute wire_fee_end_date;
|
||||||
struct TALER_MasterSignatureP wire_fee_master_sig;
|
struct TALER_MasterSignatureP wire_fee_master_sig;
|
||||||
|
struct TALER_Amount closing_fee;
|
||||||
|
|
||||||
ctx->is_valid = GNUNET_NO;
|
ctx->is_valid = GNUNET_NO;
|
||||||
ctx->wdd_head = NULL;
|
ctx->wdd_head = NULL;
|
||||||
@ -393,6 +394,7 @@ track_transfer_transaction (void *cls,
|
|||||||
&wire_fee_start_date,
|
&wire_fee_start_date,
|
||||||
&wire_fee_end_date,
|
&wire_fee_end_date,
|
||||||
&ctx->wire_fee,
|
&ctx->wire_fee,
|
||||||
|
&closing_fee,
|
||||||
&wire_fee_master_sig);
|
&wire_fee_master_sig);
|
||||||
if (0 >= qs)
|
if (0 >= qs)
|
||||||
{
|
{
|
||||||
|
@ -383,6 +383,9 @@ postgres_create_tables (void *cls)
|
|||||||
",wire_fee_val INT8 NOT NULL"
|
",wire_fee_val INT8 NOT NULL"
|
||||||
",wire_fee_frac INT4 NOT NULL"
|
",wire_fee_frac INT4 NOT NULL"
|
||||||
",wire_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
|
",wire_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
|
||||||
|
",closing_fee_val INT8 NOT NULL"
|
||||||
|
",closing_fee_frac INT4 NOT NULL"
|
||||||
|
",closing_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
|
||||||
",master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)"
|
",master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)"
|
||||||
",PRIMARY KEY (wire_method, start_date)" /* this combo must be unique */
|
",PRIMARY KEY (wire_method, start_date)" /* this combo must be unique */
|
||||||
");"),
|
");"),
|
||||||
@ -1170,6 +1173,9 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
",wire_fee_val"
|
",wire_fee_val"
|
||||||
",wire_fee_frac"
|
",wire_fee_frac"
|
||||||
",wire_fee_curr"
|
",wire_fee_curr"
|
||||||
|
",closing_fee_val"
|
||||||
|
",closing_fee_frac"
|
||||||
|
",closing_fee_curr"
|
||||||
",master_sig"
|
",master_sig"
|
||||||
" FROM wire_fee"
|
" FROM wire_fee"
|
||||||
" WHERE wire_method=$1"
|
" WHERE wire_method=$1"
|
||||||
@ -1185,10 +1191,13 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
",wire_fee_val"
|
",wire_fee_val"
|
||||||
",wire_fee_frac"
|
",wire_fee_frac"
|
||||||
",wire_fee_curr"
|
",wire_fee_curr"
|
||||||
|
",closing_fee_val"
|
||||||
|
",closing_fee_frac"
|
||||||
|
",closing_fee_curr"
|
||||||
",master_sig"
|
",master_sig"
|
||||||
") VALUES "
|
") VALUES "
|
||||||
"($1, $2, $3, $4, $5, $6, $7);",
|
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);",
|
||||||
7),
|
19),
|
||||||
/* Used in #postgres_store_wire_transfer_out */
|
/* Used in #postgres_store_wire_transfer_out */
|
||||||
GNUNET_PQ_make_prepare ("insert_wire_out",
|
GNUNET_PQ_make_prepare ("insert_wire_out",
|
||||||
"INSERT INTO wire_out "
|
"INSERT INTO wire_out "
|
||||||
@ -3032,6 +3041,128 @@ postgres_insert_refund (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure for #get_refunds_cb().
|
||||||
|
*/
|
||||||
|
struct SelectRefundContext
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Function to call on each result.
|
||||||
|
*/
|
||||||
|
TALER_EXCHANGEDB_RefundCoinCallback cb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure for @a cb.
|
||||||
|
*/
|
||||||
|
void *cb_cls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to #GNUNET_SYSERR on error.
|
||||||
|
*/
|
||||||
|
int status;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to be called with the results of a SELECT statement
|
||||||
|
* that has returned @a num_results results.
|
||||||
|
*
|
||||||
|
* @param cls closure of type `struct SelectRefundContext *`
|
||||||
|
* @param result the postgres result
|
||||||
|
* @param num_result the number of results in @a result
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
get_refunds_cb (void *cls,
|
||||||
|
PGresult *result,
|
||||||
|
unsigned int num_results)
|
||||||
|
{
|
||||||
|
struct SelectRefundContext *srctx = cls;
|
||||||
|
|
||||||
|
for (unsigned int i=0;i<num_results;i++)
|
||||||
|
{
|
||||||
|
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||||
|
struct TALER_MerchantSignatureP merchant_sig;
|
||||||
|
struct GNUNET_HashCode h_contract;
|
||||||
|
uint64_t rtransaction_id;
|
||||||
|
struct TALER_Amount amount_with_fee;
|
||||||
|
struct TALER_Amount refund_fee;
|
||||||
|
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||||
|
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
|
||||||
|
&merchant_pub),
|
||||||
|
GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
|
||||||
|
&merchant_sig),
|
||||||
|
GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
|
||||||
|
&h_contract),
|
||||||
|
GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
|
||||||
|
&rtransaction_id),
|
||||||
|
TALER_PQ_result_spec_amount ("amount_with_fee",
|
||||||
|
&amount_with_fee),
|
||||||
|
TALER_PQ_result_spec_amount ("fee_refund",
|
||||||
|
&refund_fee),
|
||||||
|
GNUNET_PQ_result_spec_end
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_PQ_extract_result (result,
|
||||||
|
rs,
|
||||||
|
i))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
srctx->status = GNUNET_SYSERR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
srctx->cb (srctx->cb_cls,
|
||||||
|
&merchant_pub,
|
||||||
|
&merchant_sig,
|
||||||
|
&h_contract,
|
||||||
|
rtransaction_id,
|
||||||
|
&amount_with_fee,
|
||||||
|
&refund_fee))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select refunds by @a coin_pub.
|
||||||
|
*
|
||||||
|
* @param cls closure of plugin
|
||||||
|
* @param session database handle to use
|
||||||
|
* @param coin_pub coin to get refunds for
|
||||||
|
* @param cb function to call for each refund found
|
||||||
|
* @param cb_cls closure for @a cb
|
||||||
|
* @return query result status
|
||||||
|
*/
|
||||||
|
static enum GNUNET_DB_QueryStatus
|
||||||
|
postgres_select_refunds_by_coin (void *cls,
|
||||||
|
struct TALER_EXCHANGEDB_Session *session,
|
||||||
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
|
TALER_EXCHANGEDB_RefundCoinCallback cb,
|
||||||
|
void *cb_cls)
|
||||||
|
{
|
||||||
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
|
GNUNET_PQ_query_param_auto_from_type (coin_pub),
|
||||||
|
GNUNET_PQ_query_param_end
|
||||||
|
};
|
||||||
|
struct SelectRefundContext srctx = {
|
||||||
|
.cb = cb,
|
||||||
|
.cb_cls = cb_cls,
|
||||||
|
.status = GNUNET_OK
|
||||||
|
};
|
||||||
|
|
||||||
|
qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
|
||||||
|
"get_refunds_by_coin",
|
||||||
|
params,
|
||||||
|
&get_refunds_cb,
|
||||||
|
&srctx);
|
||||||
|
if (GNUNET_SYSERR == srctx.status)
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup refresh melt commitment data under the given @a rc.
|
* Lookup refresh melt commitment data under the given @a rc.
|
||||||
*
|
*
|
||||||
@ -4234,6 +4365,7 @@ postgres_insert_aggregation_tracking (void *cls,
|
|||||||
* @param[out] start_date when does the fee go into effect
|
* @param[out] start_date when does the fee go into effect
|
||||||
* @param[out] end_date when does the fee end being valid
|
* @param[out] end_date when does the fee end being valid
|
||||||
* @param[out] wire_fee how high is the wire transfer fee
|
* @param[out] wire_fee how high is the wire transfer fee
|
||||||
|
* @param[out] closing_fee how high is the closing fee
|
||||||
* @param[out] master_sig signature over the above by the exchange master key
|
* @param[out] master_sig signature over the above by the exchange master key
|
||||||
* @return status of the transaction
|
* @return status of the transaction
|
||||||
*/
|
*/
|
||||||
@ -4245,6 +4377,7 @@ postgres_get_wire_fee (void *cls,
|
|||||||
struct GNUNET_TIME_Absolute *start_date,
|
struct GNUNET_TIME_Absolute *start_date,
|
||||||
struct GNUNET_TIME_Absolute *end_date,
|
struct GNUNET_TIME_Absolute *end_date,
|
||||||
struct TALER_Amount *wire_fee,
|
struct TALER_Amount *wire_fee,
|
||||||
|
struct TALER_Amount *closing_fee,
|
||||||
struct TALER_MasterSignatureP *master_sig)
|
struct TALER_MasterSignatureP *master_sig)
|
||||||
{
|
{
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
@ -4256,6 +4389,7 @@ postgres_get_wire_fee (void *cls,
|
|||||||
TALER_PQ_result_spec_absolute_time ("start_date", start_date),
|
TALER_PQ_result_spec_absolute_time ("start_date", start_date),
|
||||||
TALER_PQ_result_spec_absolute_time ("end_date", end_date),
|
TALER_PQ_result_spec_absolute_time ("end_date", end_date),
|
||||||
TALER_PQ_result_spec_amount ("wire_fee", wire_fee),
|
TALER_PQ_result_spec_amount ("wire_fee", wire_fee),
|
||||||
|
TALER_PQ_result_spec_amount ("closing_fee", closing_fee),
|
||||||
GNUNET_PQ_result_spec_auto_from_type ("master_sig", master_sig),
|
GNUNET_PQ_result_spec_auto_from_type ("master_sig", master_sig),
|
||||||
GNUNET_PQ_result_spec_end
|
GNUNET_PQ_result_spec_end
|
||||||
};
|
};
|
||||||
@ -4276,6 +4410,7 @@ postgres_get_wire_fee (void *cls,
|
|||||||
* @param start_date when does the fee go into effect
|
* @param start_date when does the fee go into effect
|
||||||
* @param end_date when does the fee end being valid
|
* @param end_date when does the fee end being valid
|
||||||
* @param wire_fee how high is the wire transfer fee
|
* @param wire_fee how high is the wire transfer fee
|
||||||
|
* @param closing_fee how high is the closing fee
|
||||||
* @param master_sig signature over the above by the exchange master key
|
* @param master_sig signature over the above by the exchange master key
|
||||||
* @return transaction status code
|
* @return transaction status code
|
||||||
*/
|
*/
|
||||||
@ -4286,6 +4421,7 @@ postgres_insert_wire_fee (void *cls,
|
|||||||
struct GNUNET_TIME_Absolute start_date,
|
struct GNUNET_TIME_Absolute start_date,
|
||||||
struct GNUNET_TIME_Absolute end_date,
|
struct GNUNET_TIME_Absolute end_date,
|
||||||
const struct TALER_Amount *wire_fee,
|
const struct TALER_Amount *wire_fee,
|
||||||
|
const struct TALER_Amount *closing_fee,
|
||||||
const struct TALER_MasterSignatureP *master_sig)
|
const struct TALER_MasterSignatureP *master_sig)
|
||||||
{
|
{
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
@ -4293,10 +4429,12 @@ postgres_insert_wire_fee (void *cls,
|
|||||||
TALER_PQ_query_param_absolute_time (&start_date),
|
TALER_PQ_query_param_absolute_time (&start_date),
|
||||||
TALER_PQ_query_param_absolute_time (&end_date),
|
TALER_PQ_query_param_absolute_time (&end_date),
|
||||||
TALER_PQ_query_param_amount (wire_fee),
|
TALER_PQ_query_param_amount (wire_fee),
|
||||||
|
TALER_PQ_query_param_amount (closing_fee),
|
||||||
GNUNET_PQ_query_param_auto_from_type (master_sig),
|
GNUNET_PQ_query_param_auto_from_type (master_sig),
|
||||||
GNUNET_PQ_query_param_end
|
GNUNET_PQ_query_param_end
|
||||||
};
|
};
|
||||||
struct TALER_Amount wf;
|
struct TALER_Amount wf;
|
||||||
|
struct TALER_Amount cf;
|
||||||
struct TALER_MasterSignatureP sig;
|
struct TALER_MasterSignatureP sig;
|
||||||
struct GNUNET_TIME_Absolute sd;
|
struct GNUNET_TIME_Absolute sd;
|
||||||
struct GNUNET_TIME_Absolute ed;
|
struct GNUNET_TIME_Absolute ed;
|
||||||
@ -4309,6 +4447,7 @@ postgres_insert_wire_fee (void *cls,
|
|||||||
&sd,
|
&sd,
|
||||||
&ed,
|
&ed,
|
||||||
&wf,
|
&wf,
|
||||||
|
&cf,
|
||||||
&sig);
|
&sig);
|
||||||
if (qs < 0)
|
if (qs < 0)
|
||||||
return qs;
|
return qs;
|
||||||
@ -4327,6 +4466,12 @@ postgres_insert_wire_fee (void *cls,
|
|||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
}
|
}
|
||||||
|
if (0 != TALER_amount_cmp (closing_fee,
|
||||||
|
&cf))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
}
|
||||||
if ( (sd.abs_value_us != start_date.abs_value_us) ||
|
if ( (sd.abs_value_us != start_date.abs_value_us) ||
|
||||||
(ed.abs_value_us != end_date.abs_value_us) )
|
(ed.abs_value_us != end_date.abs_value_us) )
|
||||||
{
|
{
|
||||||
@ -6236,6 +6381,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
|
|||||||
plugin->iterate_matching_deposits = &postgres_iterate_matching_deposits;
|
plugin->iterate_matching_deposits = &postgres_iterate_matching_deposits;
|
||||||
plugin->insert_deposit = &postgres_insert_deposit;
|
plugin->insert_deposit = &postgres_insert_deposit;
|
||||||
plugin->insert_refund = &postgres_insert_refund;
|
plugin->insert_refund = &postgres_insert_refund;
|
||||||
|
plugin->select_refunds_by_coin = &postgres_select_refunds_by_coin;
|
||||||
plugin->insert_melt = &postgres_insert_melt;
|
plugin->insert_melt = &postgres_insert_melt;
|
||||||
plugin->get_melt = &postgres_get_melt;
|
plugin->get_melt = &postgres_get_melt;
|
||||||
plugin->insert_refresh_reveal = &postgres_insert_refresh_reveal;
|
plugin->insert_refresh_reveal = &postgres_insert_refresh_reveal;
|
||||||
|
@ -1062,10 +1062,12 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
|
|||||||
struct GNUNET_TIME_Absolute start_date;
|
struct GNUNET_TIME_Absolute start_date;
|
||||||
struct GNUNET_TIME_Absolute end_date;
|
struct GNUNET_TIME_Absolute end_date;
|
||||||
struct TALER_Amount wire_fee;
|
struct TALER_Amount wire_fee;
|
||||||
|
struct TALER_Amount closing_fee;
|
||||||
struct TALER_MasterSignatureP master_sig;
|
struct TALER_MasterSignatureP master_sig;
|
||||||
struct GNUNET_TIME_Absolute sd;
|
struct GNUNET_TIME_Absolute sd;
|
||||||
struct GNUNET_TIME_Absolute ed;
|
struct GNUNET_TIME_Absolute ed;
|
||||||
struct TALER_Amount fee;
|
struct TALER_Amount fee;
|
||||||
|
struct TALER_Amount fee2;
|
||||||
struct TALER_MasterSignatureP ms;
|
struct TALER_MasterSignatureP ms;
|
||||||
|
|
||||||
start_date = GNUNET_TIME_absolute_get ();
|
start_date = GNUNET_TIME_absolute_get ();
|
||||||
@ -1075,6 +1077,9 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
|
|||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_string_to_amount (CURRENCY ":1.424242",
|
TALER_string_to_amount (CURRENCY ":1.424242",
|
||||||
&wire_fee));
|
&wire_fee));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_string_to_amount (CURRENCY ":2.424242",
|
||||||
|
&closing_fee));
|
||||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||||
&master_sig,
|
&master_sig,
|
||||||
sizeof (master_sig));
|
sizeof (master_sig));
|
||||||
@ -1085,6 +1090,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
|
|||||||
start_date,
|
start_date,
|
||||||
end_date,
|
end_date,
|
||||||
&wire_fee,
|
&wire_fee,
|
||||||
|
&closing_fee,
|
||||||
&master_sig))
|
&master_sig))
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
@ -1097,6 +1103,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
|
|||||||
start_date,
|
start_date,
|
||||||
end_date,
|
end_date,
|
||||||
&wire_fee,
|
&wire_fee,
|
||||||
|
&closing_fee,
|
||||||
&master_sig))
|
&master_sig))
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
@ -1112,6 +1119,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
|
|||||||
&sd,
|
&sd,
|
||||||
&ed,
|
&ed,
|
||||||
&fee,
|
&fee,
|
||||||
|
&fee2,
|
||||||
&ms))
|
&ms))
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
@ -1125,6 +1133,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
|
|||||||
&sd,
|
&sd,
|
||||||
&ed,
|
&ed,
|
||||||
&fee,
|
&fee,
|
||||||
|
&fee2,
|
||||||
&ms))
|
&ms))
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
@ -1134,6 +1143,8 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
|
|||||||
(ed.abs_value_us != end_date.abs_value_us) ||
|
(ed.abs_value_us != end_date.abs_value_us) ||
|
||||||
(0 != TALER_amount_cmp (&fee,
|
(0 != TALER_amount_cmp (&fee,
|
||||||
&wire_fee)) ||
|
&wire_fee)) ||
|
||||||
|
(0 != TALER_amount_cmp (&fee2,
|
||||||
|
&closing_fee)) ||
|
||||||
(0 != memcmp (&ms,
|
(0 != memcmp (&ms,
|
||||||
&master_sig,
|
&master_sig,
|
||||||
sizeof (ms))) )
|
sizeof (ms))) )
|
||||||
@ -1393,6 +1404,72 @@ wire_missing_cb (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback invoked with information about refunds applicable
|
||||||
|
* to a particular coin.
|
||||||
|
*
|
||||||
|
* @param cls closure with the `struct TALER_EXCHANGEDB_Refund *` we expect to get
|
||||||
|
* @param merchant_pub public key of merchant who authorized refund
|
||||||
|
* @param merchant_sig signature of merchant authorizing refund
|
||||||
|
* @param h_contract hash of contract being refunded
|
||||||
|
* @param rtransaction_id refund transaction ID
|
||||||
|
* @param amount_with_fee amount being refunded
|
||||||
|
* @param refund_fee fee the exchange keeps for the refund processing
|
||||||
|
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
check_refund_cb (void *cls,
|
||||||
|
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
|
const struct TALER_MerchantSignatureP *merchant_sig,
|
||||||
|
const struct GNUNET_HashCode *h_contract,
|
||||||
|
uint64_t rtransaction_id,
|
||||||
|
const struct TALER_Amount *amount_with_fee,
|
||||||
|
const struct TALER_Amount *refund_fee)
|
||||||
|
{
|
||||||
|
const struct TALER_EXCHANGEDB_Refund *refund = cls;
|
||||||
|
|
||||||
|
if (0 != memcmp (merchant_pub,
|
||||||
|
&refund->merchant_pub,
|
||||||
|
sizeof (struct TALER_MerchantPublicKeyP)))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
result = 66;
|
||||||
|
}
|
||||||
|
if (0 != memcmp (merchant_sig,
|
||||||
|
&refund->merchant_sig,
|
||||||
|
sizeof (struct TALER_MerchantSignatureP)))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
result = 66;
|
||||||
|
}
|
||||||
|
if (0 != memcmp (h_contract,
|
||||||
|
&refund->h_contract_terms,
|
||||||
|
sizeof (struct GNUNET_HashCode)))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
result = 66;
|
||||||
|
}
|
||||||
|
if (rtransaction_id != refund->rtransaction_id)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
result = 66;
|
||||||
|
}
|
||||||
|
if (0 != TALER_amount_cmp (amount_with_fee,
|
||||||
|
&refund->refund_amount))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
result = 66;
|
||||||
|
}
|
||||||
|
if (0 != TALER_amount_cmp (refund_fee,
|
||||||
|
&refund->refund_fee))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
result = 66;
|
||||||
|
}
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main function that will be run by the scheduler.
|
* Main function that will be run by the scheduler.
|
||||||
*
|
*
|
||||||
@ -1890,14 +1967,20 @@ run (void *cls)
|
|||||||
refund.merchant_pub = deposit.merchant_pub;
|
refund.merchant_pub = deposit.merchant_pub;
|
||||||
RND_BLK (&refund.merchant_sig);
|
RND_BLK (&refund.merchant_sig);
|
||||||
refund.h_contract_terms = deposit.h_contract_terms;
|
refund.h_contract_terms = deposit.h_contract_terms;
|
||||||
refund.rtransaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
|
refund.rtransaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||||
|
UINT64_MAX);
|
||||||
refund.refund_amount = deposit.amount_with_fee;
|
refund.refund_amount = deposit.amount_with_fee;
|
||||||
refund.refund_fee = fee_refund;
|
refund.refund_fee = fee_refund;
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
plugin->insert_refund (plugin->cls,
|
plugin->insert_refund (plugin->cls,
|
||||||
session,
|
session,
|
||||||
&refund));
|
&refund));
|
||||||
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
|
plugin->select_refunds_by_coin (plugin->cls,
|
||||||
|
session,
|
||||||
|
&refund.coin.coin_pub,
|
||||||
|
&check_refund_cb,
|
||||||
|
&refund));
|
||||||
|
|
||||||
/* test payback / revocation */
|
/* test payback / revocation */
|
||||||
RND_BLK (&master_sig);
|
RND_BLK (&master_sig);
|
||||||
@ -2127,9 +2210,11 @@ main (int argc,
|
|||||||
NULL);
|
NULL);
|
||||||
plugin_name++;
|
plugin_name++;
|
||||||
(void) GNUNET_asprintf (&testname,
|
(void) GNUNET_asprintf (&testname,
|
||||||
"test-exchange-db-%s", plugin_name);
|
"test-exchange-db-%s",
|
||||||
|
plugin_name);
|
||||||
(void) GNUNET_asprintf (&config_filename,
|
(void) GNUNET_asprintf (&config_filename,
|
||||||
"%s.conf", testname);
|
"%s.conf",
|
||||||
|
testname);
|
||||||
cfg = GNUNET_CONFIGURATION_create ();
|
cfg = GNUNET_CONFIGURATION_create ();
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CONFIGURATION_parse (cfg,
|
GNUNET_CONFIGURATION_parse (cfg,
|
||||||
@ -2140,7 +2225,8 @@ main (int argc,
|
|||||||
GNUNET_free (testname);
|
GNUNET_free (testname);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
GNUNET_SCHEDULER_run (&run, cfg);
|
GNUNET_SCHEDULER_run (&run,
|
||||||
|
cfg);
|
||||||
GNUNET_CONFIGURATION_destroy (cfg);
|
GNUNET_CONFIGURATION_destroy (cfg);
|
||||||
GNUNET_free (config_filename);
|
GNUNET_free (config_filename);
|
||||||
GNUNET_free (testname);
|
GNUNET_free (testname);
|
||||||
|
@ -86,6 +86,9 @@ main (int argc,
|
|||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_string_to_amount ("EUR:1.0",
|
TALER_string_to_amount ("EUR:1.0",
|
||||||
&af->wire_fee));
|
&af->wire_fee));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_string_to_amount ("EUR:1.0",
|
||||||
|
&af->closing_fee));
|
||||||
sign_af (af,
|
sign_af (af,
|
||||||
priv);
|
priv);
|
||||||
n = GNUNET_new (struct TALER_EXCHANGEDB_AggregateFees);
|
n = GNUNET_new (struct TALER_EXCHANGEDB_AggregateFees);
|
||||||
@ -94,6 +97,9 @@ main (int argc,
|
|||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_string_to_amount ("EUR:0.1",
|
TALER_string_to_amount ("EUR:0.1",
|
||||||
&n->wire_fee));
|
&n->wire_fee));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_string_to_amount ("EUR:0.1",
|
||||||
|
&n->closing_fee));
|
||||||
sign_af (n,
|
sign_af (n,
|
||||||
priv);
|
priv);
|
||||||
af->next = n;
|
af->next = n;
|
||||||
|
@ -1001,6 +1001,7 @@ enum TALER_ErrorCode
|
|||||||
TALER_EC_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE = 2114,
|
TALER_EC_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE = 2114,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
* The request fails to provide coins for the payment.
|
* The request fails to provide coins for the payment.
|
||||||
* This response is provided with HTTP status code
|
* This response is provided with HTTP status code
|
||||||
* MHD_HTTP_BAD_REQUEST.
|
* MHD_HTTP_BAD_REQUEST.
|
||||||
@ -1503,67 +1504,84 @@ enum TALER_ErrorCode
|
|||||||
/* *************** Taler BANK/FAKEBANK error codes *************** */
|
/* *************** Taler BANK/FAKEBANK error codes *************** */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication failed for an unspecified request.
|
* The request cannot be served because the client failed to
|
||||||
* To return when the view name is not available, or
|
* login. To be returned along HTTP 401 Unauthorized.
|
||||||
* no specific error code is defined yet.
|
|
||||||
*/
|
*/
|
||||||
TALER_EC_BANK_NOT_AUTHORIZED = 5000,
|
TALER_EC_BANK_REJECT_LOGIN_FAILED = 5312,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The bank could not find the bank account specified
|
* The transaction cannot be rejected becasue it does not exist
|
||||||
* in the request. Returned with a status code of MHD_HTTP_NOT_FOUND.
|
* at the bank. To be returned along HTTP 404 Not Found.
|
||||||
*/
|
*/
|
||||||
TALER_EC_BANK_UNKNOWN_ACCOUNT = 5001,
|
TALER_EC_BANK_REJECT_TRANSACTION_NOT_FOUND = 5301,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication failed for the /admin/add/incoming request.
|
* The client does not own the account credited by the transaction
|
||||||
* Returned with a status code of MHD_HTTP_FORBIDDEN.
|
* which is to be rejected, so it has no rights do reject it. To be
|
||||||
|
* returned along HTTP 403 Forbidden.
|
||||||
*/
|
*/
|
||||||
TALER_EC_BANK_TRANSFER_NOT_AUHTORIZED = 5100,
|
TALER_EC_BANK_REJECT_NO_RIGHTS = 5313,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The wire transfer cannot be done because the debitor would
|
* The POSTed JSON at /reject was invalid. To be returned along
|
||||||
* reach a unallowed debit.
|
* HTTP 400 Bad Request.
|
||||||
*/
|
*/
|
||||||
TALER_EC_BANK_TRANSFER_DEBIT = 5101,
|
TALER_EC_BANK_REJECT_JSON_INVALID = 5306,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The wire transfer cannot be done because the credit and
|
* A URL parameter for /history was missing. To be returned along
|
||||||
* debit account are the same.
|
* HTTP 400 Bad Request.
|
||||||
*/
|
*/
|
||||||
TALER_EC_BANK_TRANSFER_SAME_ACCOUNT = 5102,
|
TALER_EC_BANK_HISTORY_PARAMETER_MISSING = 5208,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication failed for the /history request.
|
* A URL parameter for /history was malformed. To be returned along
|
||||||
* Returned with a status code of MHD_HTTP_FORBIDDEN.
|
* HTTP 400 Bad Request.
|
||||||
*/
|
*/
|
||||||
TALER_EC_BANK_HISTORY_NOT_AUHTORIZED = 5200,
|
TALER_EC_BANK_HISTORY_PARAMETER_MALFORMED = 5209,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The bank library had trouble obtaining a valid
|
* The client failed to login for /history. To be returned along
|
||||||
* HTTP response.
|
* HTTP 401 Unauthorized.
|
||||||
* Returned with a status code of 0.
|
|
||||||
*/
|
*/
|
||||||
TALER_EC_BANK_HISTORY_HTTP_FAILURE = 5201,
|
TALER_EC_BANK_HISTORY_LOGIN_FAILED = 5212,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The bank could not find the wire transfer that was supposed to
|
* The bank had trouble obtaining a valid HTTP response. To be returned
|
||||||
* be rejected.
|
* along status code 0.
|
||||||
* Returned with a status code of MHD_HTTP_NOT_FOUND.
|
|
||||||
*/
|
*/
|
||||||
TALER_EC_BANK_REJECT_NOT_FOUND = 5300,
|
TALER_EC_BANK_HISTORY_HTTP_FAILURE = 5213,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication failed for the /reject request.
|
* The debit account for /admin/add/incoming is not known to the
|
||||||
* Returned with a status code of MHD_HTTP_FORBIDDEN.
|
* bank. To be returned along HTTP 404 Not Found.
|
||||||
*/
|
*/
|
||||||
TALER_EC_BANK_REJECT_NOT_AUTHORIZED = 5301,
|
TALER_EC_BANK_ADD_INCOMING_UNKNOWN_ACCOUNT = 5100,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The client wants to reject a transaction where they are
|
* The client specified the same bank account for both the credit
|
||||||
* not the _credit_ party, impossible!
|
* and the debit account. The bank will not accomplish this operation.
|
||||||
|
* To be returned along HTTP 403 Forbidden.
|
||||||
*/
|
*/
|
||||||
TALER_EC_BANK_REJECT_NO_RIGHTS = 5302,
|
TALER_EC_BANK_ADD_INCOMING_SAME_ACCOUNT = 5102,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The operation would put the client in a debit situation which is
|
||||||
|
* forbidden to them. To return along HTTP 403 Forbidden.
|
||||||
|
*/
|
||||||
|
TALER_EC_BANK_ADD_INCOMING_UNALLOWED_DEBIT = 5103,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client POSTed an invalid JSON. To be returned along HTTP
|
||||||
|
* 400 Bad Request.
|
||||||
|
*/
|
||||||
|
TALER_EC_BANK_ADD_INCOMING_JSON_INVALID = 5106,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client failed to login for /admin/add/incoming. To be returned
|
||||||
|
* along HTTP 401 Unauthorized.
|
||||||
|
*/
|
||||||
|
TALER_EC_BANK_ADD_INCOMING_LOGIN_FAILED = 5112,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* End of error code range.
|
* End of error code range.
|
||||||
|
@ -716,6 +716,50 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange,
|
|||||||
void *cb_cls);
|
void *cb_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit a refund request to the exchange and get the exchange's
|
||||||
|
* response. This API is used by a merchant. Note that
|
||||||
|
* while we return the response verbatim to the caller for further
|
||||||
|
* processing, we do already verify that the response is well-formed
|
||||||
|
* (i.e. that signatures included in the response are all valid). If
|
||||||
|
* the exchange's reply is not well-formed, we return an HTTP status code
|
||||||
|
* of zero to @a cb.
|
||||||
|
*
|
||||||
|
* The @a exchange must be ready to operate (i.e. have
|
||||||
|
* finished processing the /keys reply). If this check fails, we do
|
||||||
|
* NOT initiate the transaction with the exchange and instead return NULL.
|
||||||
|
*
|
||||||
|
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||||
|
* @param amount the amount to be refunded; must be larger than the refund fee
|
||||||
|
* (as that fee is still being subtracted), and smaller than the amount
|
||||||
|
* (with deposit fee) of the original deposit contribution of this coin
|
||||||
|
* @param refund_fee fee applicable to this coin for the refund
|
||||||
|
* @param h_contract_terms hash of the contact of the merchant with the customer that is being refunded
|
||||||
|
* @param coin_pub coin’s public key of the coin from the original deposit operation
|
||||||
|
* @param rtransaction_id transaction id for the transaction between merchant and customer (of refunding operation);
|
||||||
|
* this is needed as we may first do a partial refund and later a full refund. If both
|
||||||
|
* refunds are also over the same amount, we need the @a rtransaction_id to make the disjoint
|
||||||
|
* refund requests different (as requests are idempotent and otherwise the 2nd refund might not work).
|
||||||
|
* @param merchant_pub public key of the merchant
|
||||||
|
* @param merchant_sig signature affirming the refund from the merchant
|
||||||
|
* @param cb the callback to call when a reply for this request is available
|
||||||
|
* @param cb_cls closure for the above callback
|
||||||
|
* @return a handle for this request; NULL if the inputs are invalid (i.e.
|
||||||
|
* signatures fail to verify). In this case, the callback is not called.
|
||||||
|
*/
|
||||||
|
struct TALER_EXCHANGE_RefundHandle *
|
||||||
|
TALER_EXCHANGE_refund2 (struct TALER_EXCHANGE_Handle *exchange,
|
||||||
|
const struct TALER_Amount *amount,
|
||||||
|
const struct TALER_Amount *refund_fee,
|
||||||
|
const struct GNUNET_HashCode *h_contract_terms,
|
||||||
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
|
uint64_t rtransaction_id,
|
||||||
|
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
|
const struct TALER_MerchantSignatureP *merchant_sig,
|
||||||
|
TALER_EXCHANGE_RefundResultCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel a refund permission request. This function cannot be used
|
* Cancel a refund permission request. This function cannot be used
|
||||||
* on a request handle if a response is already served for it. If
|
* on a request handle if a response is already served for it. If
|
||||||
|
@ -732,6 +732,29 @@ typedef int
|
|||||||
const struct TALER_RefreshCommitmentP *rc);
|
const struct TALER_RefreshCommitmentP *rc);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback invoked with information about refunds applicable
|
||||||
|
* to a particular coin.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param merchant_pub public key of merchant who authorized refund
|
||||||
|
* @param merchant_sig signature of merchant authorizing refund
|
||||||
|
* @param h_contract hash of contract being refunded
|
||||||
|
* @param rtransaction_id refund transaction ID
|
||||||
|
* @param amount_with_fee amount being refunded
|
||||||
|
* @param refund_fee fee the exchange keeps for the refund processing
|
||||||
|
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||||
|
*/
|
||||||
|
typedef int
|
||||||
|
(*TALER_EXCHANGEDB_RefundCoinCallback)(void *cls,
|
||||||
|
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
|
const struct TALER_MerchantSignatureP *merchant_sig,
|
||||||
|
const struct GNUNET_HashCode *h_contract,
|
||||||
|
uint64_t rtransaction_id,
|
||||||
|
const struct TALER_Amount *amount_with_fee,
|
||||||
|
const struct TALER_Amount *refund_fee);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about a coin that was revealed to the exchange
|
* Information about a coin that was revealed to the exchange
|
||||||
* during /refresh/reveal.
|
* during /refresh/reveal.
|
||||||
@ -1358,6 +1381,23 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
struct TALER_EXCHANGEDB_Session *session,
|
struct TALER_EXCHANGEDB_Session *session,
|
||||||
const struct TALER_EXCHANGEDB_Refund *refund);
|
const struct TALER_EXCHANGEDB_Refund *refund);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select refunds by @a coin_pub.
|
||||||
|
*
|
||||||
|
* @param cls closure of plugin
|
||||||
|
* @param session database handle to use
|
||||||
|
* @param coin_pub coin to get refunds for
|
||||||
|
* @param cb function to call for each refund found
|
||||||
|
* @param cb_cls closure for @a cb
|
||||||
|
* @return query result status
|
||||||
|
*/
|
||||||
|
enum GNUNET_DB_QueryStatus
|
||||||
|
(*select_refunds_by_coin)(void *cls,
|
||||||
|
struct TALER_EXCHANGEDB_Session *session,
|
||||||
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
|
TALER_EXCHANGEDB_RefundCoinCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark a deposit as tiny, thereby declaring that it cannot be
|
* Mark a deposit as tiny, thereby declaring that it cannot be
|
||||||
@ -1658,6 +1698,7 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
* @param start_date when does the fee go into effect
|
* @param start_date when does the fee go into effect
|
||||||
* @param end_date when does the fee end being valid
|
* @param end_date when does the fee end being valid
|
||||||
* @param wire_fee how high is the wire transfer fee
|
* @param wire_fee how high is the wire transfer fee
|
||||||
|
* @param closing_fee how high is the closing fee
|
||||||
* @param master_sig signature over the above by the exchange master key
|
* @param master_sig signature over the above by the exchange master key
|
||||||
* @return transaction status code
|
* @return transaction status code
|
||||||
*/
|
*/
|
||||||
@ -1668,6 +1709,7 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
struct GNUNET_TIME_Absolute start_date,
|
struct GNUNET_TIME_Absolute start_date,
|
||||||
struct GNUNET_TIME_Absolute end_date,
|
struct GNUNET_TIME_Absolute end_date,
|
||||||
const struct TALER_Amount *wire_fee,
|
const struct TALER_Amount *wire_fee,
|
||||||
|
const struct TALER_Amount *closing_fee,
|
||||||
const struct TALER_MasterSignatureP *master_sig);
|
const struct TALER_MasterSignatureP *master_sig);
|
||||||
|
|
||||||
|
|
||||||
@ -1681,6 +1723,7 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
* @param[out] start_date when does the fee go into effect
|
* @param[out] start_date when does the fee go into effect
|
||||||
* @param[out] end_date when does the fee end being valid
|
* @param[out] end_date when does the fee end being valid
|
||||||
* @param[out] wire_fee how high is the wire transfer fee
|
* @param[out] wire_fee how high is the wire transfer fee
|
||||||
|
* @param[out] closing_fee how high is the closing fee
|
||||||
* @param[out] master_sig signature over the above by the exchange master key
|
* @param[out] master_sig signature over the above by the exchange master key
|
||||||
* @return query status of the transaction
|
* @return query status of the transaction
|
||||||
*/
|
*/
|
||||||
@ -1692,6 +1735,7 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
struct GNUNET_TIME_Absolute *start_date,
|
struct GNUNET_TIME_Absolute *start_date,
|
||||||
struct GNUNET_TIME_Absolute *end_date,
|
struct GNUNET_TIME_Absolute *end_date,
|
||||||
struct TALER_Amount *wire_fee,
|
struct TALER_Amount *wire_fee,
|
||||||
|
struct TALER_Amount *closing_fee,
|
||||||
struct TALER_MasterSignatureP *master_sig);
|
struct TALER_MasterSignatureP *master_sig);
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,6 +178,12 @@
|
|||||||
*/
|
*/
|
||||||
#define TALER_SIGNATURE_MERCHANT_REFUND_OK 1105
|
#define TALER_SIGNATURE_MERCHANT_REFUND_OK 1105
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signature where the merchant confirms that the user replayed
|
||||||
|
* a payment for a browser session.
|
||||||
|
*/
|
||||||
|
#define TALER_SIGNATURE_MERCHANT_PAY_SESSION 1106
|
||||||
|
|
||||||
|
|
||||||
/*********************/
|
/*********************/
|
||||||
/* Wallet signatures */
|
/* Wallet signatures */
|
||||||
@ -1291,6 +1297,31 @@ struct TALER_MerchantRefundConfirmationPS
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by the merchant to confirm to the frontend that
|
||||||
|
* the user did a payment replay with the current browser session.
|
||||||
|
*/
|
||||||
|
struct TALER_MerchantPaySessionSigPS
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Set to #TALER_SIGNATURE_MERCHANT_PAY_SESSION.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashed order id.
|
||||||
|
* Hashed without the 0-termination.
|
||||||
|
*/
|
||||||
|
struct GNUNET_HashCode h_order_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashed session id.
|
||||||
|
* Hashed without the 0-termination.
|
||||||
|
*/
|
||||||
|
struct GNUNET_HashCode h_session_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
GNUNET_NETWORK_STRUCT_END
|
GNUNET_NETWORK_STRUCT_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -207,6 +207,8 @@ void
|
|||||||
TALER_amount_hton (struct TALER_AmountNBO *res,
|
TALER_amount_hton (struct TALER_AmountNBO *res,
|
||||||
const struct TALER_Amount *d)
|
const struct TALER_Amount *d)
|
||||||
{
|
{
|
||||||
|
GNUNET_assert (GNUNET_YES ==
|
||||||
|
TALER_amount_is_valid (d));
|
||||||
res->value = GNUNET_htonll (d->value);
|
res->value = GNUNET_htonll (d->value);
|
||||||
res->fraction = htonl (d->fraction);
|
res->fraction = htonl (d->fraction);
|
||||||
memcpy (res->currency,
|
memcpy (res->currency,
|
||||||
@ -230,6 +232,8 @@ TALER_amount_ntoh (struct TALER_Amount *res,
|
|||||||
memcpy (res->currency,
|
memcpy (res->currency,
|
||||||
dn->currency,
|
dn->currency,
|
||||||
TALER_CURRENCY_LEN);
|
TALER_CURRENCY_LEN);
|
||||||
|
GNUNET_assert (GNUNET_YES ==
|
||||||
|
TALER_amount_is_valid (res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user