summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-10-02 22:47:28 +0200
committerChristian Grothoff <christian@grothoff.org>2022-10-02 22:47:28 +0200
commit4a36ed7fbfcaa220d1b2605851b38fc1a386e7d3 (patch)
treeaaaaea2035914fc69a8321751816a5c5a6c56c3f
parentde657800a854a031e61f5bcc7d1c168150d1c626 (diff)
downloadexchange-4a36ed7fbfcaa220d1b2605851b38fc1a386e7d3.tar.gz
exchange-4a36ed7fbfcaa220d1b2605851b38fc1a386e7d3.tar.bz2
exchange-4a36ed7fbfcaa220d1b2605851b38fc1a386e7d3.zip
complete taler-exchange-httpd_reserves_open.c logic (first pass, still without DB logic or tests)
-rw-r--r--src/exchange/taler-exchange-httpd_reserves_open.c96
-rw-r--r--src/include/taler_crypto_lib.h12
-rw-r--r--src/include/taler_exchangedb_plugin.h49
-rw-r--r--src/lib/exchange_api_reserves_open.c15
-rw-r--r--src/util/wallet_signatures.c21
5 files changed, 152 insertions, 41 deletions
diff --git a/src/exchange/taler-exchange-httpd_reserves_open.c b/src/exchange/taler-exchange-httpd_reserves_open.c
index 2bc450ee2..c9f5e4019 100644
--- a/src/exchange/taler-exchange-httpd_reserves_open.c
+++ b/src/exchange/taler-exchange-httpd_reserves_open.c
@@ -84,6 +84,11 @@ struct ReserveOpenContext
struct TALER_Amount open_cost;
/**
+ * Total amount that was deposited.
+ */
+ struct TALER_Amount total;
+
+ /**
* Information about payments by coin.
*/
struct TEH_PurseDepositedCoin *payments;
@@ -111,9 +116,16 @@ static MHD_RESULT
reply_reserve_open_success (struct MHD_Connection *connection,
const struct ReserveOpenContext *rsc)
{
+ unsigned int status;
+
+ status = MHD_HTTP_OK;
+ if (GNUNET_TIME_timestamp_cmp (rsc->reserve_expiration,
+ <,
+ rsc->desired_expiration))
+ status = MHD_HTTP_PAYMENT_REQUIRED;
return TALER_MHD_REPLY_JSON_PACK (
connection,
- MHD_HTTP_OK,
+ status,
GNUNET_JSON_pack_timestamp ("reserve_expiration",
rsc->reserve_expiration),
TALER_JSON_pack_amount ("open_cost",
@@ -150,7 +162,7 @@ cleanup_rsc (struct ReserveOpenContext *rsc)
* @param cls a `struct ReserveOpenContext *`
* @param connection MHD request which triggered the transaction
* @param[out] mhd_ret set to MHD response status for @a connection,
- * if transaction failed (!); unused
+ * if transaction failed (!)
* @return transaction status
*/
static enum GNUNET_DB_QueryStatus
@@ -161,15 +173,63 @@ reserve_open_transaction (void *cls,
struct ReserveOpenContext *rsc = cls;
enum GNUNET_DB_QueryStatus qs;
- (void) rsc;
-#if 0
- // FIXME: implement!
+ for (unsigned int i = 0; i<rsc->payments_len; i++)
+ {
+ struct TEH_PurseDepositedCoin *coin = &rsc->payments[i];
+ bool insufficient_funds = true;
+
+ qs = TEH_make_coin_known (&coin->cpi,
+ connection,
+ &coin->known_coin_id,
+ mhd_ret);
+ if (qs < 0)
+ return qs;
+ qs = TEH_plugin->insert_reserve_open_deposit (
+ TEH_plugin->cls,
+ &coin->cpi,
+ &coin->coin_sig,
+ coin->known_coin_id,
+ &coin->amount,
+ &rsc->reserve_sig,
+ &insufficient_funds);
+ /* 0 == qs is fine, then the coin was already
+ spent for this very operation as identified
+ by reserve_sig! */
+ if (qs < 0)
+ {
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ return qs;
+ GNUNET_break (0);
+ *mhd_ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "insert_reserve_open_deposit");
+ return qs;
+ }
+ if (insufficient_funds)
+ {
+ *mhd_ret
+ = TEH_RESPONSE_reply_coin_insufficient_funds (
+ connection,
+ TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS,
+ &coin->cpi.denom_pub_hash,
+ &coin->cpi.coin_pub);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ }
+
qs = TEH_plugin->do_reserve_open (TEH_plugin->cls,
+ /* inputs */
rsc->reserve_pub,
- ...);
-#else
- qs = GNUNET_DB_STATUS_HARD_ERROR;
-#endif
+ &rsc->total,
+ rsc->purse_limit,
+ &rsc->reserve_sig,
+ rsc->desired_expiration,
+ rsc->timestamp,
+ &rsc->gf->fees.account,
+ /* outputs */
+ &rsc->open_cost,
+ &rsc->reserve_expiration);
switch (qs)
{
case GNUNET_DB_STATUS_HARD_ERROR:
@@ -178,7 +238,7 @@ reserve_open_transaction (void *cls,
= TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_FETCH_FAILED,
- "get_reserve_open");
+ "do_reserve_open");
return GNUNET_DB_STATUS_HARD_ERROR;
case GNUNET_DB_STATUS_SOFT_ERROR:
return qs;
@@ -258,6 +318,7 @@ TEH_handler_reserves_open (struct TEH_RequestContext *rc,
rsc.payments_len = json_array_size (payments);
rsc.payments = GNUNET_new_array (rsc.payments_len,
struct TEH_PurseDepositedCoin);
+ rsc.total = rsc.reserve_payment;
for (unsigned int i = 0; i<rsc.payments_len; i++)
{
struct TEH_PurseDepositedCoin *coin = &rsc.payments[i];
@@ -280,6 +341,21 @@ TEH_handler_reserves_open (struct TEH_RequestContext *rc,
cleanup_rsc (&rsc);
return MHD_YES; /* failure */
}
+ /* FIXME-DOLD: Alternatively, we could here add coin->amount_minus_fee and
+ thereby charge the deposit fee even when paying the reserve-open fee.
+ To be decided... */
+ if (0 >
+ TALER_amount_add (&rsc.total,
+ &rsc.total,
+ &coin->amount))
+ {
+ GNUNET_break (0);
+ cleanup_rsc (&rsc);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_FAILED_COMPUTE_AMOUNT,
+ NULL);
+ }
}
{
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index 09e386cd4..a861563b2 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -3107,16 +3107,14 @@ TALER_wallet_reserve_open_verify (
* Sign to deposit coin to pay for keeping a reserve open.
*
* @param coin_contribution how much the coin should contribute
- * @param reserve_pub public key of the reserve
- * @param request_timestamp time of the open request
+ * @param reserve_sig signature over the reserve open operation
* @param coin_priv private key of the coin
* @param[out] coin_sig signature by the coin
*/
void
TALER_wallet_reserve_open_deposit_sign (
const struct TALER_Amount *coin_contribution,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- struct GNUNET_TIME_Timestamp request_timestamp,
+ const struct TALER_ReserveSignatureP *reserve_sig,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
struct TALER_CoinSpendSignatureP *coin_sig);
@@ -3125,8 +3123,7 @@ TALER_wallet_reserve_open_deposit_sign (
* Verify signature that deposits coin to pay for keeping a reserve open.
*
* @param coin_contribution how much the coin should contribute
- * @param reserve_pub public key of the reserve
- * @param request_timestamp time of the open request
+ * @param reserve_sig signature over the reserve open operation
* @param coin_pub public key of the coin
* @param coin_sig signature by the coin
* @return #GNUNET_OK if the signature is valid
@@ -3134,8 +3131,7 @@ TALER_wallet_reserve_open_deposit_sign (
enum GNUNET_GenericReturnValue
TALER_wallet_reserve_open_deposit_verify (
const struct TALER_Amount *coin_contribution,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- struct GNUNET_TIME_Timestamp request_timestamp,
+ const struct TALER_ReserveSignatureP *reserve_sig,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig);
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index 261ffb184..e6c38ad9b 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -4044,6 +4044,55 @@ struct TALER_EXCHANGEDB_Plugin
/**
+ * Insert reserve open coin deposit data into database.
+ * Subtracts the @a coin_total from the coin's balance.
+ *
+ * @param cls closure
+ * @param cpi public information about the coin
+ * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT
+ * @param known_coin_id ID of the coin in the known_coins table
+ * @param coin_total amount to be spent of the coin (including deposit fee)
+ * @param reserve_sig signature by the reserve affirming the open operation
+ * @param[out] insufficient_funds set to true if the coin's balance is insufficient, otherwise to false
+ * @return transaction status code, 0 if operation is already in the DB
+ */
+ enum GNUNET_DB_QueryStatus
+ (*insert_reserve_open_deposit)(
+ void *cls,
+ const struct TALER_CoinPublicInfo *cpi,
+ const struct TALER_CoinSpendSignatureP *coin_sig,
+ uint64_t known_coin_id,
+ const struct TALER_Amount *coin_total,
+ const struct TALER_ReserveSignatureP *reserve_sig,
+ bool *insufficient_funds);
+
+
+ /**
+ * Insert reserve close operation into database.
+ *
+ * @param cls closure
+ * @param reserve_pub which reserve is this about?
+ * @param execution_date when did we perform the transfer?
+ * @param receiver_account to which account do we transfer, in payto://-format
+ * @param wtid identifier for the wire transfer
+ * @param amount_with_fee amount we charged to the reserve
+ * @param closing_fee how high is the closing fee
+ * @return transaction status code
+ */
+ enum GNUNET_DB_QueryStatus
+ (*do_reserve_open)(void *cls,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *total_paid,
+ uint32_t min_purse_limit,
+ const struct TALER_ReserveSignatureP *reserve_sig,
+ struct GNUNET_TIME_Timestamp desired_expiration,
+ struct GNUNET_TIME_Timestamp now,
+ const struct TALER_Amount *open_fee,
+ struct TALER_Amount *open_cost,
+ const struct GNUNET_TIME_Timestamp *final_expiration);
+
+
+ /**
* Insert reserve close operation into database.
*
* @param cls closure
diff --git a/src/lib/exchange_api_reserves_open.c b/src/lib/exchange_api_reserves_open.c
index eb63f8fe9..08d267fb7 100644
--- a/src/lib/exchange_api_reserves_open.c
+++ b/src/lib/exchange_api_reserves_open.c
@@ -393,6 +393,12 @@ TALER_EXCHANGE_reserves_open (
GNUNET_free (roh);
return NULL;
}
+ TALER_wallet_reserve_open_sign (reserve_contribution,
+ roh->ts,
+ expiration_time,
+ min_purses,
+ reserve_priv,
+ &roh->reserve_sig);
cpa = json_array ();
GNUNET_assert (NULL != cpa);
for (unsigned int i = 0; i<coin_payments_length; i++)
@@ -412,8 +418,7 @@ TALER_EXCHANGE_reserves_open (
achp = &ahac;
}
TALER_wallet_reserve_open_deposit_sign (&pd->amount,
- &roh->reserve_pub,
- roh->ts,
+ &roh->reserve_sig,
&pd->coin_priv,
&coin_sig);
GNUNET_CRYPTO_eddsa_key_get_public (&pd->coin_priv.eddsa_priv,
@@ -437,12 +442,6 @@ TALER_EXCHANGE_reserves_open (
json_array_append_new (cpa,
cp));
}
- TALER_wallet_reserve_open_sign (reserve_contribution,
- roh->ts,
- expiration_time,
- min_purses,
- reserve_priv,
- &roh->reserve_sig);
{
json_t *open_obj = GNUNET_JSON_PACK (
GNUNET_JSON_pack_timestamp ("request_timestamp",
diff --git a/src/util/wallet_signatures.c b/src/util/wallet_signatures.c
index 4e4932a2b..c57506bd8 100644
--- a/src/util/wallet_signatures.c
+++ b/src/util/wallet_signatures.c
@@ -1342,14 +1342,9 @@ struct TALER_ReserveOpenDepositPS
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
- * When was the request created.
- */
- struct GNUNET_TIME_TimestampNBO request_timestamp;
-
- /**
- * Which reserve's opening should be paid for?
+ * Which reserve's opening signature should be paid for?
*/
- struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_ReserveSignatureP reserve_sig;
/**
* Specifies how much of the coin's value should be spent on opening this
@@ -1364,16 +1359,14 @@ GNUNET_NETWORK_STRUCT_END
void
TALER_wallet_reserve_open_deposit_sign (
const struct TALER_Amount *coin_contribution,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- struct GNUNET_TIME_Timestamp request_timestamp,
+ const struct TALER_ReserveSignatureP *reserve_sig,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
struct TALER_CoinSpendSignatureP *coin_sig)
{
struct TALER_ReserveOpenDepositPS rod = {
.purpose.size = htonl (sizeof (rod)),
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT),
- .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp),
- .reserve_pub = *reserve_pub
+ .reserve_sig = *reserve_sig
};
TALER_amount_hton (&rod.coin_contribution,
@@ -1388,16 +1381,14 @@ TALER_wallet_reserve_open_deposit_sign (
enum GNUNET_GenericReturnValue
TALER_wallet_reserve_open_deposit_verify (
const struct TALER_Amount *coin_contribution,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- struct GNUNET_TIME_Timestamp request_timestamp,
+ const struct TALER_ReserveSignatureP *reserve_sig,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig)
{
struct TALER_ReserveOpenDepositPS rod = {
.purpose.size = htonl (sizeof (rod)),
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT),
- .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp),
- .reserve_pub = *reserve_pub
+ .reserve_sig = *reserve_sig
};
TALER_amount_hton (&rod.coin_contribution,