add logic to check timestamp, revise history balance calculation logic in client
This commit is contained in:
parent
1f86b02ffa
commit
c7e2d206ba
@ -1 +1 @@
|
||||
Subproject commit 4cfefdf374de55fe9be3f0f039c7a13f496ab970
|
||||
Subproject commit 25eb78f2d0e20a137020dd0ab1c6474123843dbe
|
@ -31,6 +31,14 @@
|
||||
#include "taler-exchange-httpd_responses.h"
|
||||
|
||||
|
||||
/**
|
||||
* How far do we allow a client's time to be off when
|
||||
* checking the request timestamp?
|
||||
*/
|
||||
#define TIMESTAMP_TOLERANCE \
|
||||
GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #reserve_history_transaction.
|
||||
*/
|
||||
@ -121,8 +129,7 @@ reserve_history_transaction (void *cls,
|
||||
struct ReserveHistoryContext *rsc = cls;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
// FIXME: first deduct rsc->gf->fees.history from balance!
|
||||
// FIXME: pass rsc.gf->history_expiration?
|
||||
// FIXME: first deduct rsc->gf->fees.history from reserve balance (and persist the signature justifying this)
|
||||
qs = TEH_plugin->get_reserve_history (TEH_plugin->cls,
|
||||
rsc->reserve_pub,
|
||||
&rsc->balance,
|
||||
@ -175,13 +182,21 @@ TEH_handler_reserves_history (struct TEH_RequestContext *rc,
|
||||
}
|
||||
}
|
||||
now = GNUNET_TIME_timestamp_get ();
|
||||
/* FIXME: check that 'timestamp' is close to 'now' */
|
||||
|
||||
if (! GNUNET_TIME_absolute_approx_eq (now.abs_time,
|
||||
rsc.timestamp.abs_time,
|
||||
TIMESTAMP_TOLERANCE))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_GENERIC_CLOCK_SKEW,
|
||||
NULL);
|
||||
}
|
||||
rsc.gf = TEH_keys_global_fee_by_time (TEH_keys_get_state (),
|
||||
rsc.timestamp);
|
||||
if (NULL == rsc.gf)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
|
||||
|
@ -30,6 +30,13 @@
|
||||
#include "taler-exchange-httpd_reserves_status.h"
|
||||
#include "taler-exchange-httpd_responses.h"
|
||||
|
||||
/**
|
||||
* How far do we allow a client's time to be off when
|
||||
* checking the request timestamp?
|
||||
*/
|
||||
#define TIMESTAMP_TOLERANCE \
|
||||
GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #reserve_status_transaction.
|
||||
@ -140,6 +147,7 @@ TEH_handler_reserves_status (struct TEH_RequestContext *rc,
|
||||
&reserve_sig),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
struct GNUNET_TIME_Timestamp now;
|
||||
|
||||
rsc.reserve_pub = reserve_pub;
|
||||
{
|
||||
@ -159,6 +167,17 @@ TEH_handler_reserves_status (struct TEH_RequestContext *rc,
|
||||
return MHD_YES; /* failure */
|
||||
}
|
||||
}
|
||||
now = GNUNET_TIME_timestamp_get ();
|
||||
if (! GNUNET_TIME_absolute_approx_eq (now.abs_time,
|
||||
timestamp.abs_time,
|
||||
TIMESTAMP_TOLERANCE))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_GENERIC_CLOCK_SKEW,
|
||||
NULL);
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_reserve_status_verify (timestamp,
|
||||
reserve_pub,
|
||||
|
@ -5595,6 +5595,7 @@ postgres_get_reserve_status (void *cls,
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
|
||||
/* FIXME: actually implement reserve history truncation logic! */
|
||||
rhc.reserve_pub = reserve_pub;
|
||||
rhc.rh = NULL;
|
||||
rhc.rh_tail = NULL;
|
||||
|
@ -1583,10 +1583,21 @@ struct TALER_EXCHANGE_ReserveStatus
|
||||
{
|
||||
|
||||
/**
|
||||
* Reserve balance.
|
||||
* Current reserve balance. May not be the difference between
|
||||
* @e total_in and @e total_out because the @e may be truncated.
|
||||
*/
|
||||
struct TALER_Amount balance;
|
||||
|
||||
/**
|
||||
* Total of all inbound transactions in @e history.
|
||||
*/
|
||||
struct TALER_Amount total_in;
|
||||
|
||||
/**
|
||||
* Total of all outbound transactions in @e history.
|
||||
*/
|
||||
struct TALER_Amount total_out;
|
||||
|
||||
/**
|
||||
* Reserve history.
|
||||
*/
|
||||
@ -1687,10 +1698,22 @@ struct TALER_EXCHANGE_ReserveHistory
|
||||
{
|
||||
|
||||
/**
|
||||
* Reserve balance.
|
||||
* Reserve balance. May not be the difference between
|
||||
* @e total_in and @e total_out because the @e may be truncated
|
||||
* due to expiration.
|
||||
*/
|
||||
struct TALER_Amount balance;
|
||||
|
||||
/**
|
||||
* Total of all inbound transactions in @e history.
|
||||
*/
|
||||
struct TALER_Amount total_in;
|
||||
|
||||
/**
|
||||
* Total of all outbound transactions in @e history.
|
||||
*/
|
||||
struct TALER_Amount total_out;
|
||||
|
||||
/**
|
||||
* Reserve history.
|
||||
*/
|
||||
@ -2685,7 +2708,8 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
* @param history JSON array with the history
|
||||
* @param reserve_pub public key of the reserve to inspect
|
||||
* @param currency currency we expect the balance to be in
|
||||
* @param[out] balance final balance
|
||||
* @param[out] total_in set to value of credits to reserve
|
||||
* @param[out] total_out set to value of debits from reserve
|
||||
* @param history_length number of entries in @a history
|
||||
* @param[out] rhistory array of length @a history_length, set to the
|
||||
* parsed history entries
|
||||
@ -2699,7 +2723,8 @@ TALER_EXCHANGE_parse_reserve_history (
|
||||
const json_t *history,
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
const char *currency,
|
||||
struct TALER_Amount *balance,
|
||||
struct TALER_Amount *total_in,
|
||||
struct TALER_Amount *total_out,
|
||||
unsigned int history_length,
|
||||
struct TALER_EXCHANGE_ReserveHistoryEntry *rhistory);
|
||||
|
||||
|
@ -32,21 +32,20 @@ TALER_EXCHANGE_parse_reserve_history (
|
||||
const json_t *history,
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
const char *currency,
|
||||
struct TALER_Amount *balance,
|
||||
struct TALER_Amount *total_in,
|
||||
struct TALER_Amount *total_out,
|
||||
unsigned int history_length,
|
||||
struct TALER_EXCHANGE_ReserveHistoryEntry *rhistory)
|
||||
{
|
||||
struct GNUNET_HashCode uuid[history_length];
|
||||
unsigned int uuid_off;
|
||||
struct TALER_Amount total_in;
|
||||
struct TALER_Amount total_out;
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_set_zero (currency,
|
||||
&total_in));
|
||||
total_in));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_set_zero (currency,
|
||||
&total_out));
|
||||
total_out));
|
||||
uuid_off = 0;
|
||||
for (unsigned int off = 0; off<history_length; off++)
|
||||
{
|
||||
@ -76,7 +75,7 @@ TALER_EXCHANGE_parse_reserve_history (
|
||||
rhistory[off].amount = amount;
|
||||
if (GNUNET_YES !=
|
||||
TALER_amount_cmp_currency (&amount,
|
||||
&total_in))
|
||||
total_in))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
@ -99,8 +98,8 @@ TALER_EXCHANGE_parse_reserve_history (
|
||||
|
||||
rh->type = TALER_EXCHANGE_RTT_CREDIT;
|
||||
if (0 >
|
||||
TALER_amount_add (&total_in,
|
||||
&total_in,
|
||||
TALER_amount_add (total_in,
|
||||
total_in,
|
||||
&amount))
|
||||
{
|
||||
/* overflow in history already!? inconceivable! Bad exchange! */
|
||||
@ -206,8 +205,8 @@ TALER_EXCHANGE_parse_reserve_history (
|
||||
uuid_off++;
|
||||
|
||||
if (0 >
|
||||
TALER_amount_add (&total_out,
|
||||
&total_out,
|
||||
TALER_amount_add (total_out,
|
||||
total_out,
|
||||
&amount))
|
||||
{
|
||||
/* overflow in history already!? inconceivable! Bad exchange! */
|
||||
@ -274,8 +273,8 @@ TALER_EXCHANGE_parse_reserve_history (
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 >
|
||||
TALER_amount_add (&total_in,
|
||||
&total_in,
|
||||
TALER_amount_add (total_in,
|
||||
total_in,
|
||||
&rh->amount))
|
||||
{
|
||||
/* overflow in history already!? inconceivable! Bad exchange! */
|
||||
@ -349,8 +348,8 @@ TALER_EXCHANGE_parse_reserve_history (
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 >
|
||||
TALER_amount_add (&total_out,
|
||||
&total_out,
|
||||
TALER_amount_add (total_out,
|
||||
total_out,
|
||||
&rh->amount))
|
||||
{
|
||||
/* overflow in history already!? inconceivable! Bad exchange! */
|
||||
@ -366,23 +365,6 @@ TALER_EXCHANGE_parse_reserve_history (
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* check balance = total_in - total_out < withdraw-amount */
|
||||
if (NULL != balance)
|
||||
{
|
||||
/* if balance is NULL, we may have a partial history
|
||||
in which case the subtraction may fail, so we do
|
||||
not even check that invariant in this case. */
|
||||
if (0 >
|
||||
TALER_amount_subtract (balance,
|
||||
&total_in,
|
||||
&total_out))
|
||||
{
|
||||
/* total_in < total_out, why did the exchange ever allow this!? */
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,6 @@ handle_reserves_history_ok (struct TALER_EXCHANGE_ReservesHistoryHandle *rsh,
|
||||
{
|
||||
json_t *history;
|
||||
unsigned int len;
|
||||
struct TALER_Amount history_balance;
|
||||
struct TALER_EXCHANGE_ReserveHistory rs = {
|
||||
.hr.reply = j,
|
||||
.hr.http_status = MHD_HTTP_OK
|
||||
@ -123,15 +122,13 @@ handle_reserves_history_ok (struct TALER_EXCHANGE_ReservesHistoryHandle *rsh,
|
||||
|
||||
rhistory = GNUNET_new_array (len,
|
||||
struct TALER_EXCHANGE_ReserveHistoryEntry);
|
||||
// FIXME: even this history could be partial
|
||||
// (if the reserve is too old!); update API
|
||||
// and return incoming & outgoing totals separately?
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGE_parse_reserve_history (rsh->exchange,
|
||||
history,
|
||||
&rsh->reserve_pub,
|
||||
rs.details.ok.balance.currency,
|
||||
&history_balance,
|
||||
&rs.details.ok.total_in,
|
||||
&rs.details.ok.total_out,
|
||||
len,
|
||||
rhistory))
|
||||
{
|
||||
|
@ -127,7 +127,8 @@ handle_reserves_status_ok (struct TALER_EXCHANGE_ReservesStatusHandle *rsh,
|
||||
history,
|
||||
&rsh->reserve_pub,
|
||||
rs.details.ok.balance.currency,
|
||||
NULL,
|
||||
&rs.details.ok.total_in,
|
||||
&rs.details.ok.total_out,
|
||||
len,
|
||||
rhistory))
|
||||
{
|
||||
|
@ -148,7 +148,8 @@ reserve_withdraw_payment_required (
|
||||
const json_t *json)
|
||||
{
|
||||
struct TALER_Amount balance;
|
||||
struct TALER_Amount balance_from_history;
|
||||
struct TALER_Amount total_in_from_history;
|
||||
struct TALER_Amount total_out_from_history;
|
||||
json_t *history;
|
||||
size_t len;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
@ -197,7 +198,8 @@ reserve_withdraw_payment_required (
|
||||
history,
|
||||
&wh->reserve_pub,
|
||||
balance.currency,
|
||||
&balance_from_history,
|
||||
&total_in_from_history,
|
||||
&total_out_from_history,
|
||||
len,
|
||||
rhistory))
|
||||
{
|
||||
@ -210,14 +212,6 @@ reserve_withdraw_payment_required (
|
||||
len);
|
||||
}
|
||||
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&balance_from_history,
|
||||
&balance))
|
||||
{
|
||||
/* exchange cannot add up balances!? */
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
/* Check that funds were really insufficient */
|
||||
if (0 >= TALER_amount_cmp (&wh->requested_amount,
|
||||
&balance))
|
||||
|
Loading…
Reference in New Issue
Block a user