summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-06-26 23:58:48 +0200
committerChristian Grothoff <christian@grothoff.org>2019-06-27 00:04:20 +0200
commit19e0b66f8780f97f15f0a40a739eb277244750f1 (patch)
tree1823f46f36a74e7b54bbc4be4640eef5a95a666d /src
parent9a69fd81ed1eb5de13509f565947f01de8bdf38c (diff)
downloadexchange-19e0b66f8780f97f15f0a40a739eb277244750f1.tar.gz
exchange-19e0b66f8780f97f15f0a40a739eb277244750f1.tar.bz2
exchange-19e0b66f8780f97f15f0a40a739eb277244750f1.zip
first steps on #5777
Diffstat (limited to 'src')
-rw-r--r--src/exchange/taler-exchange-httpd_keystate.c13
-rw-r--r--src/exchange/taler-exchange-httpd_keystate.h9
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_melt.c61
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c3
4 files changed, 82 insertions, 4 deletions
diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c
index 24eef36ea..7d67b8768 100644
--- a/src/exchange/taler-exchange-httpd_keystate.c
+++ b/src/exchange/taler-exchange-httpd_keystate.c
@@ -1907,6 +1907,9 @@ TEH_KS_denomination_key_lookup_by_hash (const struct TEH_KS_StateHandle *key_sta
map = (TEH_KS_DKU_PAYBACK == use) ? key_state->revoked_map : key_state->denomkey_map;
dki = GNUNET_CONTAINER_multihashmap_get (map,
denom_pub_hash);
+ if ( (NULL == dki) && (TEH_KS_DKU_ZOMBIE == use))
+ dki = GNUNET_CONTAINER_multihashmap_get (key_state->revoked_map,
+ denom_pub_hash);
if (NULL == dki)
return NULL;
now = GNUNET_TIME_absolute_get ();
@@ -1958,6 +1961,16 @@ TEH_KS_denomination_key_lookup_by_hash (const struct TEH_KS_StateHandle *key_sta
return NULL;
}
break;
+ case TEH_KS_DKU_ZOMBIE:
+ if (now.abs_value_us >
+ GNUNET_TIME_absolute_ntoh (dki->issue.properties.expire_legal).abs_value_us)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Not returning DKI for %s, as legal expiration of coin has passed\n",
+ GNUNET_h2s (denom_pub_hash));
+ return NULL;
+ }
+ break;
}
return dki;
}
diff --git a/src/exchange/taler-exchange-httpd_keystate.h b/src/exchange/taler-exchange-httpd_keystate.h
index e197e7acc..6f5d338cb 100644
--- a/src/exchange/taler-exchange-httpd_keystate.h
+++ b/src/exchange/taler-exchange-httpd_keystate.h
@@ -109,7 +109,14 @@ enum TEH_KS_DenominationKeyUse {
/**
* The key is to be used for a /payback operation.
*/
- TEH_KS_DKU_PAYBACK
+ TEH_KS_DKU_PAYBACK,
+
+ /**
+ * The key is to be used for a /refresh/payback operation,
+ * i.e. it is an old coin that regained value from a
+ * payback on a new coin derived from the old coin.
+ */
+ TEH_KS_DKU_ZOMBIE
};
diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c
index 36ad1a738..5674a12f8 100644
--- a/src/exchange/taler-exchange-httpd_refresh_melt.c
+++ b/src/exchange/taler-exchange-httpd_refresh_melt.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2019 Inria & GNUnet e.V.
+ Copyright (C) 2014-2019 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -173,12 +173,12 @@ refresh_check_melt (struct MHD_Connection *connection,
session,
&rmc->refresh_session.coin.coin_pub,
GNUNET_NO,
- &tl);
+ &tl);
if (0 > qs)
{
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
*mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
- TALER_EC_REFRESH_MELT_DB_FETCH_ERROR);
+ TALER_EC_REFRESH_MELT_DB_FETCH_ERROR);
return qs;
}
if (GNUNET_OK !=
@@ -453,9 +453,64 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
"no keys");
goto cleanup;
}
+
+ /* Baseline: check if deposits/refreshs are generally
+ simply still allowed for this denomination */
rmc.dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
&rmc.refresh_session.coin.denom_pub_hash,
TEH_KS_DKU_DEPOSIT);
+ /* Consider case that denomination was revoked but
+ this coin was already seen and thus refresh is OK. */
+ if (NULL == rmc.dki)
+ {
+ struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
+
+ dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
+ &rmc.refresh_session.coin.denom_pub_hash,
+ TEH_KS_DKU_PAYBACK);
+ if (NULL != dki)
+ {
+ struct TALER_CoinPublicInfo coin_info;
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = TEH_plugin->get_known_coin (TEH_plugin->cls,
+ NULL,
+ &rmc.refresh_session.coin.coin_pub,
+ &coin_info);
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ res = TEH_RESPONSE_reply_internal_db_error (connection,
+ TALER_EC_REFRESH_MELT_DB_FETCH_ERROR);
+ goto cleanup;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ {
+ /* Coin was known beforehand, so we should allow the refresh */
+ rmc.dki = dki;
+ GNUNET_CRYPTO_rsa_signature_free (coin_info.denom_sig.rsa_signature);
+ }
+ }
+ }
+
+ /* Consider the case that the denomination expired for deposits,
+ but /refresh/payback refilled the balance of the 'zombie' coin
+ and we should thus allow the refresh during the legal period. */
+ if (NULL == rmc.dki)
+ {
+ struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
+
+ dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
+ &rmc.refresh_session.coin.denom_pub_hash,
+ TEH_KS_DKU_ZOMBIE);
+ if (NULL != dki)
+ {
+ /* Test if zombie-condition is actually satisfied for the coin */
+ if (0 /* FIXME: test if zombie-satisfied */)
+ rmc.dki = dki;
+ }
+ }
+
if (NULL == rmc.dki)
{
TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n");
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index a8b2e36c6..b4c2d49d8 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -3304,6 +3304,7 @@ postgres_get_known_coin (void *cls,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
struct TALER_CoinPublicInfo *coin_info)
{
+ struct PostgresClosure *pc = cls;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (coin_pub),
GNUNET_PQ_query_param_end
@@ -3320,6 +3321,8 @@ postgres_get_known_coin (void *cls,
"Getting known coin data for coin %s\n",
TALER_B2S (coin_pub));
coin_info->coin_pub = *coin_pub;
+ if (NULL == session)
+ session = postgres_get_session (pc);
return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
"get_known_coin",
params,