diff --git a/contrib/gana b/contrib/gana index 4cfefdf37..25eb78f2d 160000 --- a/contrib/gana +++ b/contrib/gana @@ -1 +1 @@ -Subproject commit 4cfefdf374de55fe9be3f0f039c7a13f496ab970 +Subproject commit 25eb78f2d0e20a137020dd0ab1c6474123843dbe diff --git a/src/exchange/taler-exchange-httpd_reserves_history.c b/src/exchange/taler-exchange-httpd_reserves_history.c index 4115988f9..96902d01c 100644 --- a/src/exchange/taler-exchange-httpd_reserves_history.c +++ b/src/exchange/taler-exchange-httpd_reserves_history.c @@ -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, diff --git a/src/exchange/taler-exchange-httpd_reserves_status.c b/src/exchange/taler-exchange-httpd_reserves_status.c index 0b6ee2d30..6a3260d12 100644 --- a/src/exchange/taler-exchange-httpd_reserves_status.c +++ b/src/exchange/taler-exchange-httpd_reserves_status.c @@ -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, diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 73f7b90d8..3f8716261 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -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; diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index f59e1b46c..41f01c97a 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -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); diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c index c9bff71f1..1da36fe8b 100644 --- a/src/lib/exchange_api_common.c +++ b/src/lib/exchange_api_common.c @@ -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; offtype = 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; } diff --git a/src/lib/exchange_api_reserves_history.c b/src/lib/exchange_api_reserves_history.c index c0f6c42d2..d9c42d691 100644 --- a/src/lib/exchange_api_reserves_history.c +++ b/src/lib/exchange_api_reserves_history.c @@ -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)) { diff --git a/src/lib/exchange_api_reserves_status.c b/src/lib/exchange_api_reserves_status.c index a99a080bc..eecd40b9c 100644 --- a/src/lib/exchange_api_reserves_status.c +++ b/src/lib/exchange_api_reserves_status.c @@ -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)) { diff --git a/src/lib/exchange_api_withdraw2.c b/src/lib/exchange_api_withdraw2.c index bc138db0f..a5371442f 100644 --- a/src/lib/exchange_api_withdraw2.c +++ b/src/lib/exchange_api_withdraw2.c @@ -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))