summaryrefslogtreecommitdiff
path: root/src/exchange/taler-exchange-httpd_deposit.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-03-16 19:27:39 +0100
committerChristian Grothoff <christian@grothoff.org>2020-03-16 19:27:39 +0100
commitc04bcb0a828e739f0b23a98748d81a9f0993cc06 (patch)
treee802efaaecf4a6d8fe6be25201da314336789266 /src/exchange/taler-exchange-httpd_deposit.c
parentbb7bd4b12895c202fa90951be6f9d23272a8ed1d (diff)
downloadexchange-c04bcb0a828e739f0b23a98748d81a9f0993cc06.tar.gz
exchange-c04bcb0a828e739f0b23a98748d81a9f0993cc06.tar.bz2
exchange-c04bcb0a828e739f0b23a98748d81a9f0993cc06.zip
clean up and de-duplicate deposit logic
Diffstat (limited to 'src/exchange/taler-exchange-httpd_deposit.c')
-rw-r--r--src/exchange/taler-exchange-httpd_deposit.c204
1 files changed, 87 insertions, 117 deletions
diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c
index 7e4c8427..4008ed27 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -193,7 +193,15 @@ deposit_transaction (void *cls,
GNUNET_NO,
&tl);
if (0 > qs)
+ {
+ if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+ *mhd_ret = TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_DEPOSIT_HISTORY_DB_ERROR,
+ "could not fetch coin transaction history");
return qs;
+ }
if (GNUNET_OK !=
TALER_EXCHANGEDB_calculate_transaction_list_totals (tl,
&spent, /* starting offset */
@@ -201,14 +209,15 @@ deposit_transaction (void *cls,
{
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
tl);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_DEPOSIT_HISTORY_DB_ERROR,
- "could not access coin history");
+ *mhd_ret = TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_DEPOSIT_HISTORY_DB_ERROR,
+ "could not calculate historic coin amount total");
return GNUNET_DB_STATUS_HARD_ERROR;
}
- /* Check that cost of all transactions is smaller than
- the value of the coin. */
+ /* Check that cost of all transactions (including the current one) is
+ smaller (or equal) than the value of the coin. */
if (0 < TALER_amount_cmp (&spent,
&dc->value))
{
@@ -242,110 +251,6 @@ deposit_transaction (void *cls,
/**
- * We have parsed the JSON information about the deposit, do some
- * basic sanity checks (especially that the signature on the coin is
- * valid, and that this type of coin exists) and then execute the
- * deposit.
- *
- * @param connection the MHD connection to handle
- * @param deposit information about the deposit
- * @return MHD result code
- */
-static int
-verify_and_execute_deposit (struct MHD_Connection *connection,
- const struct TALER_EXCHANGEDB_Deposit *deposit)
-{
- struct TALER_DepositRequestPS dr;
- int mhd_ret;
- struct TALER_Amount amount_without_fee;
- struct DepositContext dc;
- const struct TALER_EXCHANGEDB_DenominationKey *dki;
- enum TALER_ErrorCode ec;
- unsigned int hc;
-
- /* check signature */
- dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
- dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
- dr.h_contract_terms = deposit->h_contract_terms;
- dr.h_wire = deposit->h_wire;
- dr.timestamp = GNUNET_TIME_absolute_hton (deposit->timestamp);
- dr.refund_deadline = GNUNET_TIME_absolute_hton (deposit->refund_deadline);
- TALER_amount_hton (&dr.amount_with_fee,
- &deposit->amount_with_fee);
- TALER_amount_hton (&dr.deposit_fee,
- &deposit->deposit_fee);
- dr.merchant = deposit->merchant_pub;
- dr.coin_pub = deposit->coin.coin_pub;
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
- &dr.purpose,
- &deposit->csig.eddsa_signature,
- &deposit->coin.coin_pub.eddsa_pub))
- {
- TALER_LOG_WARNING ("Invalid signature on /deposit request\n");
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_UNAUTHORIZED,
- TALER_EC_DEPOSIT_COIN_SIGNATURE_INVALID,
- "coin_sig");
- }
-
- /* check denomination */
- {
- struct TEH_KS_StateHandle *key_state;
-
- key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
- if (NULL == key_state)
- {
- TALER_LOG_ERROR ("Lacking keys to operate\n");
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_EXCHANGE_BAD_CONFIGURATION,
- "no keys");
- }
- dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
- &deposit->coin.denom_pub_hash,
- TEH_KS_DKU_DEPOSIT,
- &ec,
- &hc);
- if (NULL == dki)
- {
- TEH_KS_release (key_state);
- return TALER_MHD_reply_with_error (connection,
- hc,
- ec,
- "Could not find denomination key used in deposit");
- }
- TALER_amount_ntoh (&dc.value,
- &dki->issue.properties.value);
- TEH_KS_release (key_state);
- }
- /* execute transaction */
- dc.deposit = deposit;
- if (GNUNET_OK !=
- TEH_DB_run_transaction (connection,
- "execute deposit",
- &mhd_ret,
- &deposit_transaction,
- &dc))
- return mhd_ret;
-
- /* generate regular response */
- GNUNET_assert (GNUNET_SYSERR !=
- TALER_amount_subtract (&amount_without_fee,
- &deposit->amount_with_fee,
- &deposit->deposit_fee));
- return reply_deposit_success (connection,
- &deposit->coin.coin_pub,
- &deposit->h_wire,
- &deposit->h_contract_terms,
- deposit->timestamp,
- deposit->refund_deadline,
- &deposit->merchant_pub,
- &amount_without_fee);
-}
-
-
-/**
* Check that @a ts is reasonably close to our own RTC.
*
* @param ts timestamp to check
@@ -357,7 +262,8 @@ check_timestamp_current (struct GNUNET_TIME_Absolute ts)
struct GNUNET_TIME_Relative r;
struct GNUNET_TIME_Relative tolerance;
- /* Let's be VERY generous */
+ /* Let's be VERY generous (after all, this is basically about
+ which year the deposit counts for in terms of tax purposes) */
tolerance = GNUNET_TIME_UNIT_MONTHS;
r = GNUNET_TIME_absolute_get_duration (ts);
if (r.rel_value_us > tolerance.rel_value_us)
@@ -401,10 +307,8 @@ TEH_handler_deposit (struct MHD_Connection *connection,
const json_t *root)
{
json_t *wire;
- enum TALER_ErrorCode ec;
- unsigned int hc;
+ struct DepositContext dc;
struct TALER_EXCHANGEDB_Deposit deposit;
- struct TALER_EXCHANGEDB_DenominationKey *dki;
struct GNUNET_HashCode my_h_wire;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_json ("wire", &wire),
@@ -481,7 +385,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
if (0 != GNUNET_memcmp (&deposit.h_wire,
&my_h_wire))
{
- /* Client hashed contract differently than we did, reject */
+ /* Client hashed wire details differently than we did, reject */
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
@@ -492,6 +396,9 @@ TEH_handler_deposit (struct MHD_Connection *connection,
/* check denomination exists and is valid */
{
struct TEH_KS_StateHandle *key_state;
+ struct TALER_EXCHANGEDB_DenominationKey *dki;
+ enum TALER_ErrorCode ec;
+ unsigned int hc;
key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
if (NULL == key_state)
@@ -535,6 +442,8 @@ TEH_handler_deposit (struct MHD_Connection *connection,
}
TALER_amount_ntoh (&deposit.deposit_fee,
&dki->issue.properties.fee_deposit);
+ TALER_amount_ntoh (&dc.value,
+ &dki->issue.properties.value);
TEH_KS_release (key_state);
}
if (0 < TALER_amount_cmp (&deposit.deposit_fee,
@@ -568,11 +477,72 @@ TEH_handler_deposit (struct MHD_Connection *connection,
}
}
+ /* check deposit signature */
{
+ struct TALER_DepositRequestPS dr = {
+ .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
+ .purpose.size = htonl (sizeof (dr)),
+ .h_contract_terms = deposit.h_contract_terms,
+ .h_wire = deposit.h_wire,
+ .timestamp = GNUNET_TIME_absolute_hton (deposit.timestamp),
+ .refund_deadline = GNUNET_TIME_absolute_hton (deposit.refund_deadline),
+ .merchant = deposit.merchant_pub,
+ .coin_pub = deposit.coin.coin_pub
+ };
+
+ TALER_amount_hton (&dr.amount_with_fee,
+ &deposit.amount_with_fee);
+ TALER_amount_hton (&dr.deposit_fee,
+ &deposit.deposit_fee);
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
+ &dr.purpose,
+ &deposit.csig.eddsa_signature,
+ &deposit.coin.coin_pub.eddsa_pub))
+ {
+ TALER_LOG_WARNING ("Invalid signature on /deposit request\n");
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_UNAUTHORIZED,
+ TALER_EC_DEPOSIT_COIN_SIGNATURE_INVALID,
+ "coin_sig");
+ }
+ }
+
+ /* execute transaction */
+ dc.deposit = &deposit;
+ {
+ int mhd_ret;
+
+ if (GNUNET_OK !=
+ TEH_DB_run_transaction (connection,
+ "execute deposit",
+ &mhd_ret,
+ &deposit_transaction,
+ &dc))
+ {
+ GNUNET_JSON_parse_free (spec);
+ return mhd_ret;
+ }
+ }
+
+ /* generate regular response */
+ {
+ struct TALER_Amount amount_without_fee;
int res;
- res = verify_and_execute_deposit (connection,
- &deposit);
+ GNUNET_assert (GNUNET_SYSERR !=
+ TALER_amount_subtract (&amount_without_fee,
+ &deposit.amount_with_fee,
+ &deposit.deposit_fee));
+ res = reply_deposit_success (connection,
+ &deposit.coin.coin_pub,
+ &deposit.h_wire,
+ &deposit.h_contract_terms,
+ deposit.timestamp,
+ deposit.refund_deadline,
+ &deposit.merchant_pub,
+ &amount_without_fee);
GNUNET_JSON_parse_free (spec);
return res;
}