summaryrefslogtreecommitdiff
path: root/src/exchange
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-07-24 00:13:53 +0200
committerChristian Grothoff <christian@grothoff.org>2019-07-24 00:13:53 +0200
commit5844a20f15cf6d35503386a717e9d582189a7261 (patch)
tree0175ab0041b8e5f01a4f5cdcb561314ac8c3e804 /src/exchange
parente75d552227a4c06faad0a0eae7539458ff58f9af (diff)
downloadexchange-5844a20f15cf6d35503386a717e9d582189a7261.tar.gz
exchange-5844a20f15cf6d35503386a717e9d582189a7261.tar.bz2
exchange-5844a20f15cf6d35503386a717e9d582189a7261.zip
implement zombie check
Diffstat (limited to 'src/exchange')
-rw-r--r--src/exchange/taler-exchange-httpd_deposit.c4
-rw-r--r--src/exchange/taler-exchange-httpd_payback.c2
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_melt.c107
-rw-r--r--src/exchange/taler-exchange-httpd_refund.c2
-rw-r--r--src/exchange/taler-exchange-httpd_responses.c2
5 files changed, 75 insertions, 42 deletions
diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c
index 5320c9c75..51adacb7c 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -179,7 +179,9 @@ deposit_transaction (void *cls,
/* Start with fee for THIS transaction */
spent = deposit->amount_with_fee;
- /* add cost of all previous transactions */
+ /* add cost of all previous transactions; skip PAYBACK as revoked
+ denominations are not eligible for deposit, and if we are the old coin
+ pub of a revoked coin (aka a zombie), then ONLY refresh is allowed. */
qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
session,
&deposit->coin.coin_pub,
diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c
index 195e5613c..8cfc1aecc 100644
--- a/src/exchange/taler-exchange-httpd_payback.c
+++ b/src/exchange/taler-exchange-httpd_payback.c
@@ -289,7 +289,7 @@ payback_transaction (void *cls,
return GNUNET_DB_STATUS_HARD_ERROR;
}
- /* Calculate remaining balance. */
+ /* Calculate remaining balance, including paybacks already applied. */
qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
session,
&pc->coin->coin_pub,
diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c
index 5674a12f8..8677d6270 100644
--- a/src/exchange/taler-exchange-httpd_refresh_melt.c
+++ b/src/exchange/taler-exchange-httpd_refresh_melt.c
@@ -48,11 +48,11 @@
*/
static int
reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- struct TALER_Amount coin_value,
- struct TALER_EXCHANGEDB_TransactionList *tl,
- const struct TALER_Amount *requested,
- const struct TALER_Amount *residual)
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ struct TALER_Amount coin_value,
+ struct TALER_EXCHANGEDB_TransactionList *tl,
+ const struct TALER_Amount *requested,
+ const struct TALER_Amount *residual)
{
json_t *history;
@@ -64,9 +64,9 @@ reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection,
MHD_HTTP_FORBIDDEN,
"{s:s, s:I, s:o, s:o, s:o, s:o, s:o}",
"error",
- "insufficient funds",
- "code",
- (json_int_t) TALER_EC_REFRESH_MELT_INSUFFICIENT_FUNDS,
+ "insufficient funds",
+ "code",
+ (json_int_t) TALER_EC_REFRESH_MELT_INSUFFICIENT_FUNDS,
"coin_pub",
GNUNET_JSON_from_data_auto (coin_pub),
"original_value",
@@ -90,8 +90,8 @@ reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection,
*/
static int
reply_refresh_melt_success (struct MHD_Connection *connection,
- const struct TALER_RefreshCommitmentP *rc,
- uint32_t noreveal_index)
+ const struct TALER_RefreshCommitmentP *rc,
+ uint32_t noreveal_index)
{
struct TALER_RefreshMeltConfirmationPS body;
struct TALER_ExchangePublicKeyP pub;
@@ -139,6 +139,13 @@ struct RefreshMeltContext
*/
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
+ /**
+ * Set to #GNUNET_YES if this @a dki was revoked and the operation
+ * is thus only allowed for zombie coins where the transaction
+ * history includes a #TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK.
+ */
+ int zombie_required;
+
};
@@ -168,11 +175,12 @@ refresh_check_melt (struct MHD_Connection *connection,
/* Start with cost of this melt transaction */
spent = rmc->refresh_session.amount_with_fee;
- /* add historic transaction costs of this coin */
+ /* add historic transaction costs of this coin, including paybacks as
+ we might be a zombie coin */
qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
session,
&rmc->refresh_session.coin.coin_pub,
- GNUNET_NO,
+ GNUNET_YES,
&tl);
if (0 > qs)
{
@@ -181,16 +189,40 @@ refresh_check_melt (struct MHD_Connection *connection,
TALER_EC_REFRESH_MELT_DB_FETCH_ERROR);
return qs;
}
+ if (rmc->zombie_required)
+ {
+ for (struct TALER_EXCHANGEDB_TransactionList *tp = tl;
+ NULL != tp;
+ tp = tp->next)
+ {
+ if (TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK == tp->type)
+ {
+ rmc->zombie_required = GNUNET_NO; /* was satisfied! */
+ break;
+ }
+ }
+ if (rmc->zombie_required)
+ {
+ /* zombie status not satisfied */
+ GNUNET_break (0);
+ TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
+ tl);
+ *mhd_ret = TEH_RESPONSE_reply_external_error (connection,
+ TALER_EC_REFRESH_MELT_COIN_EXPIRED_NO_ZOMBIE,
+ "denomination expired");
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ }
if (GNUNET_OK !=
TEH_DB_calculate_transaction_list_totals (tl,
- &spent,
- &spent))
+ &spent,
+ &spent))
{
GNUNET_break (0);
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
tl);
*mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
- TALER_EC_REFRESH_MELT_COIN_HISTORY_COMPUTATION_FAILED);
+ TALER_EC_REFRESH_MELT_COIN_HISTORY_COMPUTATION_FAILED);
return GNUNET_DB_STATUS_HARD_ERROR;
}
@@ -206,11 +238,11 @@ refresh_check_melt (struct MHD_Connection *connection,
&spent,
&rmc->refresh_session.amount_with_fee));
*mhd_ret = reply_refresh_melt_insufficient_funds (connection,
- &rmc->refresh_session.coin.coin_pub,
- coin_value,
- tl,
- &rmc->refresh_session.amount_with_fee,
- &coin_residual);
+ &rmc->refresh_session.coin.coin_pub,
+ coin_value,
+ tl,
+ &rmc->refresh_session.amount_with_fee,
+ &coin_residual);
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
tl);
return GNUNET_DB_STATUS_HARD_ERROR;
@@ -245,9 +277,9 @@ refresh_check_melt (struct MHD_Connection *connection,
*/
static enum GNUNET_DB_QueryStatus
refresh_melt_transaction (void *cls,
- struct MHD_Connection *connection,
- struct TALER_EXCHANGEDB_Session *session,
- int *mhd_ret)
+ struct MHD_Connection *connection,
+ struct TALER_EXCHANGEDB_Session *session,
+ int *mhd_ret)
{
struct RefreshMeltContext *rmc = cls;
enum GNUNET_DB_QueryStatus qs;
@@ -262,8 +294,8 @@ refresh_melt_transaction (void *cls,
{
TALER_LOG_DEBUG ("Found already-melted coin\n");
*mhd_ret = reply_refresh_melt_success (connection,
- &rmc->refresh_session.rc,
- noreveal_index);
+ &rmc->refresh_session.rc,
+ noreveal_index);
/* Note: we return "hard error" to ensure the wrapper
does not retry the transaction, and to also not generate
a "fresh" response (as we would on "success") */
@@ -273,22 +305,22 @@ refresh_melt_transaction (void *cls,
{
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;
}
/* check coin has enough funds remaining on it to cover melt cost */
qs = refresh_check_melt (connection,
- session,
- rmc,
- mhd_ret);
+ session,
+ rmc,
+ mhd_ret);
if (0 > qs)
return qs;
/* pick challenge and persist it */
rmc->refresh_session.noreveal_index
= GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
- TALER_CNC_KAPPA);
+ TALER_CNC_KAPPA);
if (0 >=
(qs = TEH_plugin->insert_melt (TEH_plugin->cls,
@@ -298,7 +330,7 @@ refresh_melt_transaction (void *cls,
if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
{
*mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
- TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR);
+ TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR);
return GNUNET_DB_STATUS_HARD_ERROR;
}
return qs;
@@ -327,9 +359,9 @@ handle_refresh_melt (struct MHD_Connection *connection,
struct TALER_Amount fee_refresh;
TALER_amount_ntoh (&fee_refresh,
- &rmc->dki->issue.properties.fee_refresh);
+ &rmc->dki->issue.properties.fee_refresh);
if (TALER_amount_cmp (&fee_refresh,
- &rmc->refresh_session.amount_with_fee) > 0)
+ &rmc->refresh_session.amount_with_fee) > 0)
{
GNUNET_break_op (0);
return TEH_RESPONSE_reply_external_error (connection,
@@ -358,8 +390,8 @@ handle_refresh_melt (struct MHD_Connection *connection,
{
GNUNET_break_op (0);
return TEH_RESPONSE_reply_signature_invalid (connection,
- TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID,
- "confirm_sig");
+ TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID,
+ "confirm_sig");
}
}
@@ -505,9 +537,8 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
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;
+ rmc.dki = dki;
+ rmc.zombie_required = GNUNET_YES;
}
}
diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c
index 69b5cae96..5fea37da0 100644
--- a/src/exchange/taler-exchange-httpd_refund.c
+++ b/src/exchange/taler-exchange-httpd_refund.c
@@ -165,7 +165,7 @@ refund_transaction (void *cls,
session,
&refund->coin.coin_pub,
GNUNET_NO,
- &tl);
+ &tl);
if (0 > qs)
{
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c
index 3cf3e781b..f05e42604 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -393,7 +393,7 @@ TEH_RESPONSE_reply_external_error (struct MHD_Connection *connection,
*/
int
TEH_RESPONSE_reply_commit_error (struct MHD_Connection *connection,
- enum TALER_ErrorCode ec)
+ enum TALER_ErrorCode ec)
{
return TEH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,