diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-05-16 10:53:42 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-05-16 10:53:42 +0200 |
commit | 439c872af48aed41dea1027fd03a28225d3bc59b (patch) | |
tree | 297ab9b23e67dfd492613a25278d013aa51eae89 | |
parent | 10a97996f70ffb4891bc62d06499833a03f0ebc9 (diff) | |
download | exchange-439c872af48aed41dea1027fd03a28225d3bc59b.tar.xz |
-implement purse_deposit error handling
-rw-r--r-- | src/exchange/taler-exchange-httpd_purses_deposit.c | 8 | ||||
-rw-r--r-- | src/include/taler_exchange_service.h | 25 | ||||
-rw-r--r-- | src/lib/exchange_api_purse_deposit.c | 126 |
3 files changed, 140 insertions, 19 deletions
diff --git a/src/exchange/taler-exchange-httpd_purses_deposit.c b/src/exchange/taler-exchange-httpd_purses_deposit.c index 8ac63c517..38bd84729 100644 --- a/src/exchange/taler-exchange-httpd_purses_deposit.c +++ b/src/exchange/taler-exchange-httpd_purses_deposit.c @@ -167,8 +167,16 @@ reply_deposit_success (struct MHD_Connection *connection, MHD_HTTP_OK, TALER_JSON_pack_amount ("total_deposited", &pcc->deposit_total), + TALER_JSON_pack_amount ("purse_value_after_fees", + &pcc->amount), GNUNET_JSON_pack_timestamp ("exchange_timestamp", pcc->exchange_timestamp), + GNUNET_JSON_pack_timestamp ("purse_expiration", + pcc->purse_expiration), + GNUNET_JSON_pack_data_auto ("h_contract_terms", + &pcc->h_contract_terms), + GNUNET_JSON_pack_data_auto ("merge_pub", + &pcc->merge_pub), GNUNET_JSON_pack_data_auto ("exchange_sig", &sig), GNUNET_JSON_pack_data_auto ("exchange_pub", diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index cb4d83520..c615ca7c3 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -4493,6 +4493,31 @@ struct TALER_EXCHANGE_PurseDepositResponse struct { + /** + * When does the purse expire. + */ + struct GNUNET_TIME_Timestamp purse_expiration; + + /** + * How much was actually deposited into the purse. + */ + struct TALER_Amount total_deposited; + + /** + * How much should be in the purse in total in the end. + */ + struct TALER_Amount purse_value_after_fees; + + /** + * Hash of the contract (needed to verify signature). + */ + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * Key with the merge capability (needed to verify signature). + */ + struct TALER_PurseMergePublicKeyP merge_pub; + } success; } details; diff --git a/src/lib/exchange_api_purse_deposit.c b/src/lib/exchange_api_purse_deposit.c index dfe9a6ecf..f71bb3895 100644 --- a/src/lib/exchange_api_purse_deposit.c +++ b/src/lib/exchange_api_purse_deposit.c @@ -50,6 +50,11 @@ struct TALER_EXCHANGE_PurseDepositHandle char *url; /** + * The base url of the exchange we are talking to. + */ + char *base_url; + + /** * Context for #TEH_curl_easy_post(). Keeps the data that must * persist for Curl to make the upload. */ @@ -75,6 +80,15 @@ struct TALER_EXCHANGE_PurseDepositHandle */ struct TALER_PurseContractPublicKeyP purse_pub; + /** + * Array of @e num_deposits coins we are depositing. + */ + struct TALER_CoinSpendPublicKeyP *coins; + + /** + * Number of coins we are depositing. + */ + unsigned int num_deposits; }; @@ -110,7 +124,6 @@ handle_purse_deposit_finished (void *cls, { const struct TALER_EXCHANGE_Keys *key_state; struct GNUNET_TIME_Timestamp etime; - struct TALER_Amount total_deposited; struct TALER_ExchangeSignatureP exchange_sig; struct TALER_ExchangePublicKeyP exchange_pub; struct GNUNET_JSON_Specification spec[] = { @@ -118,11 +131,20 @@ handle_purse_deposit_finished (void *cls, &exchange_sig), GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub), + GNUNET_JSON_spec_fixed_auto ("merge_pub", + &dr.details.success.merge_pub), + GNUNET_JSON_spec_fixed_auto ("h_contract_terms", + &dr.details.success.h_contract_terms), GNUNET_JSON_spec_timestamp ("exchange_timestamp", &etime), + GNUNET_JSON_spec_timestamp ("purse_expiration", + &dr.details.success.purse_expiration), TALER_JSON_spec_amount ("total_deposited", keys->currency, - &total_deposited), + &dr.details.success.total_deposited), + TALER_JSON_spec_amount ("purse_value_after_fees", + keys->currency, + &dr.details.success.purse_value_after_fees), GNUNET_JSON_spec_end () }; @@ -146,16 +168,15 @@ handle_purse_deposit_finished (void *cls, dr.hr.ec = TALER_EC_EXCHANGE_PURSE_DEPOSIT_EXCHANGE_SIGNATURE_INVALID; break; } -#if FIXME if (GNUNET_OK != TALER_exchange_online_purse_created_verify ( etime, - pch->purse_expiration, - &pch->purse_value_after_fees, - &total_deposited, + dr.details.success.purse_expiration, + &dr.details.success.purse_value_after_fees, + &dr.details.success.total_deposited, &pch->purse_pub, - &pch->merge_pub, - &pch->h_contract_terms, + &dr.details.success.merge_pub, + &dr.details.success.h_contract_terms, &exchange_pub, &exchange_sig)) { @@ -164,7 +185,6 @@ handle_purse_deposit_finished (void *cls, dr.hr.ec = TALER_EC_EXCHANGE_PURSE_DEPOSIT_EXCHANGE_SIGNATURE_INVALID; break; } -#endif } break; case MHD_HTTP_BAD_REQUEST: @@ -187,7 +207,69 @@ handle_purse_deposit_finished (void *cls, happen, we should pass the JSON reply to the application */ break; case MHD_HTTP_CONFLICT: - // FIXME: check reply! + { + const char *partner_url = NULL; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_Amount amount; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("coin_sig", + &coin_sig), + GNUNET_JSON_spec_fixed_auto ("coin_pub", + &coin_pub), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("partner_url", + &partner_url), + NULL), + TALER_JSON_spec_amount ("amount", + keys->currency, + &amount), + GNUNET_JSON_spec_end () + }; + bool found = false; + + if (GNUNET_OK != + GNUNET_JSON_parse (j, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + dr.hr.http_status = 0; + dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + break; + } + for (unsigned int i = 0; i<pch->num_deposits; i++) + if (0 == GNUNET_memcmp (&coin_pub, + &pch->coins[i])) + { + found = true; + break; + } + if (! found) + { + /* proof is about a coin we did not even deposit */ + GNUNET_break_op (0); + dr.hr.http_status = 0; + dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + break; + } + if (NULL == partner_url) + partner_url = pch->base_url; + if (GNUNET_OK != + TALER_wallet_purse_deposit_verify ( + partner_url, + &pch->purse_pub, + &amount, + &coin_pub, + &coin_sig)) + { + GNUNET_break_op (0); + dr.hr.http_status = 0; + dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + break; + } + /* conflict is real! */ + } break; case MHD_HTTP_GONE: /* could happen if denomination was revoked */ @@ -236,7 +318,6 @@ TALER_EXCHANGE_purse_deposit ( json_t *create_obj; json_t *deposit_arr; CURL *eh; - char *url; char arg_str[sizeof (pch->purse_pub) * 2 + 32]; if (0 == num_deposits) @@ -276,14 +357,17 @@ TALER_EXCHANGE_purse_deposit ( } deposit_arr = json_array (); GNUNET_assert (NULL != deposit_arr); - url = TEAH_path_to_url (exchange, - "/"); + pch->base_url = TEAH_path_to_url (exchange, + "/"); + pch->num_deposits = num_deposits; + pch->coins = GNUNET_new_array (num_deposits, + struct TALER_CoinSpendPublicKeyP); for (unsigned int i = 0; i<num_deposits; i++) { const struct TALER_EXCHANGE_PurseDeposit *deposit = &deposits[i]; + struct TALER_CoinSpendPublicKeyP *coin_pub = &pch->coins[i]; json_t *jdeposit; struct TALER_CoinSpendSignatureP coin_sig; - struct TALER_CoinSpendPublicKeyP coin_pub; #if FIXME_OEC struct TALER_AgeCommitmentHash agh; struct TALER_AgeCommitmentHash *aghp = NULL; @@ -299,15 +383,16 @@ TALER_EXCHANGE_purse_deposit ( { GNUNET_break (0); json_decref (deposit_arr); - GNUNET_free (url); + GNUNET_free (pch->base_url); + GNUNET_free (pch->coins); GNUNET_free (pch); return NULL; } #endif GNUNET_CRYPTO_eddsa_key_get_public (&deposit->coin_priv.eddsa_priv, - &coin_pub.eddsa_pub); + &coin_pub->eddsa_pub); TALER_wallet_purse_deposit_sign ( - url, + pch->base_url, &pch->purse_pub, &deposit->amount, &deposit->coin_priv, @@ -328,14 +413,13 @@ TALER_EXCHANGE_purse_deposit ( TALER_JSON_pack_denom_sig ("ub_sig", &deposit->denom_sig), GNUNET_JSON_pack_data_auto ("coin_pub", - &coin_pub), + coin_pub), GNUNET_JSON_pack_data_auto ("coin_sig", &coin_sig)); GNUNET_assert (0 == json_array_append_new (deposit_arr, jdeposit)); } - GNUNET_free (url); create_obj = GNUNET_JSON_PACK ( GNUNET_JSON_pack_array_steal ("deposits", deposit_arr)); @@ -351,7 +435,9 @@ TALER_EXCHANGE_purse_deposit ( if (NULL != eh) curl_easy_cleanup (eh); json_decref (create_obj); + GNUNET_free (pch->base_url); GNUNET_free (pch->url); + GNUNET_free (pch->coins); GNUNET_free (pch); return NULL; } @@ -378,7 +464,9 @@ TALER_EXCHANGE_purse_deposit_cancel ( GNUNET_CURL_job_cancel (pch->job); pch->job = NULL; } + GNUNET_free (pch->base_url); GNUNET_free (pch->url); + GNUNET_free (pch->coins); TALER_curl_easy_post_finished (&pch->ctx); GNUNET_free (pch); } |