aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <grothoff@gnunet.org>2023-12-10 00:55:49 +0900
committerChristian Grothoff <grothoff@gnunet.org>2023-12-10 00:55:49 +0900
commitcfdbc9a3c3fba99982beaf156794cb51494e0c3f (patch)
tree07052b2458b21ecb21a8be031f9c23756968716c
parent1a9f82e0e5e85e81f3381d32730855d4c4880c56 (diff)
parent25f93cf043632f520954aa2adcc8afa38a5c92f2 (diff)
Merge branch 'master' of git+ssh://git.taler.net/exchange
-rw-r--r--src/exchange/taler-exchange-httpd_batch-deposit.c50
-rw-r--r--src/exchange/taler-exchange-httpd_db.c11
-rw-r--r--src/exchange/taler-exchange-httpd_responses.c22
-rw-r--r--src/exchange/taler-exchange-httpd_responses.h21
-rw-r--r--src/exchangedb/exchange_do_deposit.sql1
-rw-r--r--src/exchangedb/exchange_do_insert_or_update_policy_details.sql6
-rw-r--r--src/exchangedb/pg_do_deposit.c1
-rw-r--r--src/include/taler_extensions_policy.h2
-rw-r--r--src/util/exchange_signatures.c3
9 files changed, 91 insertions, 26 deletions
diff --git a/src/exchange/taler-exchange-httpd_batch-deposit.c b/src/exchange/taler-exchange-httpd_batch-deposit.c
index 9f66a99a4..835a974fc 100644
--- a/src/exchange/taler-exchange-httpd_batch-deposit.c
+++ b/src/exchange/taler-exchange-httpd_batch-deposit.c
@@ -60,16 +60,24 @@ struct BatchDepositContext
*/
struct TALER_EXCHANGEDB_BatchDeposit bd;
+
/**
- * Additional details for policy extension relevant for this
- * deposit operation, possibly NULL!
+ * Total amount that is accumulated with this deposit,
+ * without fee.
*/
- json_t *policy_json;
+ struct TALER_Amount accumulated_total_without_fee;
/**
- * Hash over the merchant's payto://-URI with the wire salt.
+ * True, if no policy was present in the request. Then
+ * @e policy_json is NULL and @e h_policy will be all zero.
*/
- struct TALER_MerchantWireHashP h_wire;
+ bool has_no_policy;
+
+ /**
+ * Additional details for policy extension relevant for this
+ * deposit operation, possibly NULL!
+ */
+ json_t *policy_json;
/**
* If @e policy_json was present, the corresponding policy extension
@@ -84,6 +92,11 @@ struct BatchDepositContext
struct TALER_ExtensionPolicyHashP h_policy;
/**
+ * Hash over the merchant's payto://-URI with the wire salt.
+ */
+ struct TALER_MerchantWireHashP h_wire;
+
+ /**
* When @e policy_details are persisted, this contains the id of the record
* in the policy_details table.
*/
@@ -121,11 +134,11 @@ reply_batch_deposit_success (
&TEH_keys_exchange_sign_,
&bd->h_contract_terms,
&dc->h_wire,
- NULL != dc->policy_json ? &dc->h_policy : NULL,
+ dc->has_no_policy ? NULL : &dc->h_policy,
dc->exchange_timestamp,
bd->wire_deadline,
bd->refund_deadline,
- &dc->policy_details.accumulated_total, /* excludes fees */
+ &dc->accumulated_total_without_fee,
bd->num_cdis,
csigs,
&dc->bd.merchant_pub,
@@ -176,13 +189,13 @@ batch_deposit_transaction (void *cls,
/* If the deposit has a policy associated to it, persist it. This will
* insert or update the record. */
- if (NULL != dc->policy_json)
+ if (! dc->has_no_policy)
{
qs = TEH_plugin->persist_policy_details (
TEH_plugin->cls,
&dc->policy_details,
&dc->bd.policy_details_serial_id,
- &dc->policy_details.accumulated_total,
+ &dc->accumulated_total_without_fee,
&dc->policy_details.fulfillment_state);
if (qs < 0)
return qs;
@@ -237,13 +250,13 @@ batch_deposit_transaction (void *cls,
in_conflict ? "in conflict" : "no conflict");
if (in_conflict)
{
- /* FIXME: #7267 conflicting contract != insufficient funds */
+ /* FIXME: #8002 conflicting contract != insufficient funds */
*mhd_ret
= TEH_RESPONSE_reply_coin_insufficient_funds (
connection,
TALER_EC_EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT,
- &bd->cdis[0 /* SEE FIXME-#7267 Oec above! */].coin.denom_pub_hash,
- &bd->cdis[0 /* SEE FIXME-#7267 Oec above! */].coin.coin_pub);
+ &bd->cdis[0 /* SEE FIXME-#8002 Oec above! */].coin.denom_pub_hash,
+ &bd->cdis[0 /* SEE FIXME-#8002 Oec above! */].coin.coin_pub);
return GNUNET_DB_STATUS_HARD_ERROR;
}
if (! balance_ok)
@@ -495,7 +508,7 @@ TEH_handler_batch_deposit (struct TEH_RequestContext *rc,
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_json ("policy",
&dc.policy_json),
- NULL),
+ &dc.has_no_policy),
GNUNET_JSON_spec_timestamp ("timestamp",
&bd->wallet_timestamp),
GNUNET_JSON_spec_mark_optional (
@@ -571,8 +584,12 @@ TEH_handler_batch_deposit (struct TEH_RequestContext *rc,
&bd->wire_salt,
&dc.h_wire);
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TEH_currency,
+ &dc.accumulated_total_without_fee));
+
/* handle policy, if present */
- if (NULL != dc.policy_json)
+ if (! dc.has_no_policy)
{
const char *error_hint = NULL;
@@ -641,10 +658,11 @@ TEH_handler_batch_deposit (struct TEH_RequestContext *rc,
&amount_without_fee,
&cdis[i].amount_with_fee,
&deposit_fees[i]));
+
GNUNET_assert (0 <=
TALER_amount_add (
- &dc.policy_details.accumulated_total,
- &dc.policy_details.accumulated_total,
+ &dc.accumulated_total_without_fee,
+ &dc.accumulated_total_without_fee,
&amount_without_fee));
}
if (GNUNET_OK != res)
diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c
index 5660074ee..a00a97856 100644
--- a/src/exchange/taler-exchange-httpd_db.c
+++ b/src/exchange/taler-exchange-httpd_db.c
@@ -37,14 +37,14 @@ TEH_make_coin_known (const struct TALER_CoinPublicInfo *coin,
{
enum TALER_EXCHANGEDB_CoinKnownStatus cks;
struct TALER_DenominationHashP h_denom_pub;
- struct TALER_AgeCommitmentHash age_hash;
+ struct TALER_AgeCommitmentHash h_age_commitment;
/* make sure coin is 'known' in database */
cks = TEH_plugin->ensure_coin_known (TEH_plugin->cls,
coin,
known_coin_id,
&h_denom_pub,
- &age_hash);
+ &h_age_commitment);
switch (cks)
{
case TALER_EXCHANGEDB_CKS_ADDED:
@@ -70,13 +70,12 @@ TEH_make_coin_known (const struct TALER_CoinPublicInfo *coin,
&coin->coin_pub);
return GNUNET_DB_STATUS_HARD_ERROR;
case TALER_EXCHANGEDB_CKS_AGE_CONFLICT:
- /* FIXME: insufficient_funds != Age conflict! See issue #7267, need new
- * strategy for evidence gathering */
- *mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (
+ *mhd_ret = TEH_RESPONSE_reply_coin_age_commitment_conflict (
connection,
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH,
&h_denom_pub,
- &coin->coin_pub);
+ &coin->coin_pub,
+ &h_age_commitment);
return GNUNET_DB_STATUS_HARD_ERROR;
}
GNUNET_assert (0);
diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c
index 322da3877..c1aa9db6f 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -178,6 +178,28 @@ TEH_RESPONSE_reply_coin_insufficient_funds (
MHD_RESULT
+TEH_RESPONSE_reply_coin_age_commitment_conflict (
+ struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const struct TALER_DenominationHashP *h_denom_pub,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_AgeCommitmentHash *h_age_commitment_hash)
+{
+ return TALER_MHD_REPLY_JSON_PACK (
+ connection,
+ TALER_ErrorCode_get_http_status_safe (ec),
+ TALER_JSON_pack_ec (ec),
+ GNUNET_JSON_pack_data_auto ("coin_pub",
+ coin_pub),
+ GNUNET_JSON_pack_data_auto ("h_denom_pub",
+ h_denom_pub),
+ GNUNET_JSON_pack_data_auto ("h_age_commitment_hash",
+ h_age_commitment_hash)
+ );
+}
+
+
+MHD_RESULT
TEH_RESPONSE_reply_reserve_insufficient_balance (
struct MHD_Connection *connection,
enum TALER_ErrorCode ec,
diff --git a/src/exchange/taler-exchange-httpd_responses.h b/src/exchange/taler-exchange-httpd_responses.h
index 8adf1136b..5fe106e17 100644
--- a/src/exchange/taler-exchange-httpd_responses.h
+++ b/src/exchange/taler-exchange-httpd_responses.h
@@ -160,6 +160,27 @@ TEH_RESPONSE_reply_coin_insufficient_funds (
const struct TALER_CoinSpendPublicKeyP *coin_pub);
/**
+ * Send proof that a request is invalid to client because of
+ * a conflicting value for the age commitment hash of a coin.
+ * This function will create a message with the conflicting
+ * hash value for the age commitment of the given coin.
+ *
+ * @param connection connection to the client
+ * @param ec error code to return
+ * @param h_denom_pub hash of the denomination of the coin
+ * @param coin_pub public key of the coin
+ * @param h_age_commitment hash of the age commitment as found in the database
+ * @return MHD result code
+ */
+MHD_RESULT
+TEH_RESPONSE_reply_coin_age_commitment_conflict (
+ struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const struct TALER_DenominationHashP *h_denom_pub,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_AgeCommitmentHash *h_age_commitment);
+
+/**
* Fundamental details about a purse.
*/
struct TEH_PurseDetails
diff --git a/src/exchangedb/exchange_do_deposit.sql b/src/exchangedb/exchange_do_deposit.sql
index 1156c7de5..7116117ff 100644
--- a/src/exchangedb/exchange_do_deposit.sql
+++ b/src/exchangedb/exchange_do_deposit.sql
@@ -142,6 +142,7 @@ THEN
IF NOT FOUND
THEN
-- Deposit exists, but with *strange* differences. Not allowed.
+ -- FIXME #8002: Surely we need to provide the client more data in this case.
out_conflict=TRUE;
RETURN;
END IF;
diff --git a/src/exchangedb/exchange_do_insert_or_update_policy_details.sql b/src/exchangedb/exchange_do_insert_or_update_policy_details.sql
index 53cd2989e..85e52d3d3 100644
--- a/src/exchangedb/exchange_do_insert_or_update_policy_details.sql
+++ b/src/exchangedb/exchange_do_insert_or_update_policy_details.sql
@@ -93,14 +93,14 @@ BEGIN
-- Set the fulfillment_state according to the values.
-- For now, we only update the state when it was INSUFFICIENT.
- -- FIXME: What to do in case of Failure or other state?
- IF (out_fullfillment_state = 1) -- INSUFFICIENT
+ -- FIXME[oec] #7999: What to do in case of Failure or other state?
+ IF (out_fullfillment_state = 2) -- INSUFFICIENT
THEN
IF (out_accumulated_total.val >= cur_commitment.val OR
(out_accumulated_total.val = cur_commitment.val AND
out_accumulated_total.frac >= cur_commitment.frac))
THEN
- out_fulfillment_state = 2; -- READY
+ out_fulfillment_state = 3; -- READY
END IF;
END IF;
diff --git a/src/exchangedb/pg_do_deposit.c b/src/exchangedb/pg_do_deposit.c
index 0ba45b628..64e7886a7 100644
--- a/src/exchangedb/pg_do_deposit.c
+++ b/src/exchangedb/pg_do_deposit.c
@@ -83,6 +83,7 @@ TEH_PG_do_deposit (
GNUNET_PQ_result_spec_uint32 ("insufficient_balance_coin_index",
bad_balance_index),
balance_ok),
+ /* FIXME #8002: We need more data to communicate the conflict to the client */
GNUNET_PQ_result_spec_bool ("conflicted",
ctr_conflict),
GNUNET_PQ_result_spec_end
diff --git a/src/include/taler_extensions_policy.h b/src/include/taler_extensions_policy.h
index 7750f58f1..b10c0d8a2 100644
--- a/src/include/taler_extensions_policy.h
+++ b/src/include/taler_extensions_policy.h
@@ -28,6 +28,8 @@
/*
* @brief Describes the states of fulfillment of a policy bound to a deposit
+ * NOTE: These values must be in sync with their use in stored procedures, f.e.
+ * exchange_do_insert_or_update_policy_details.
*/
enum TALER_PolicyFulfillmentState
{
diff --git a/src/util/exchange_signatures.c b/src/util/exchange_signatures.c
index bc5fe439f..aaefb5cec 100644
--- a/src/util/exchange_signatures.c
+++ b/src/util/exchange_signatures.c
@@ -120,7 +120,8 @@ TALER_exchange_online_deposit_confirmation_sign (
.exchange_timestamp = GNUNET_TIME_timestamp_hton (exchange_timestamp),
.wire_deadline = GNUNET_TIME_timestamp_hton (wire_deadline),
.refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
- .merchant_pub = *merchant_pub
+ .merchant_pub = *merchant_pub,
+ .h_policy = {{{0}}}
};
struct GNUNET_HashContext *hc;