diff options
author | Joseph <Joseph.xu@efrei.net> | 2022-11-08 09:22:05 -0500 |
---|---|---|
committer | Joseph <Joseph.xu@efrei.net> | 2022-11-08 09:22:05 -0500 |
commit | f51e8a7150bee920f1bd3649c053b341419795c1 (patch) | |
tree | b0f9f4edd0bb00cefaf2c8a6873871caf91305b1 /src/lib/exchange_api_reserves_open.c | |
parent | 4394079a5e789189aa308ac85bcf704e34d3c1ee (diff) | |
parent | 0c32c48ac5628b2068fada9fc43fa0fa94d1c002 (diff) |
merge
Diffstat (limited to 'src/lib/exchange_api_reserves_open.c')
-rw-r--r-- | src/lib/exchange_api_reserves_open.c | 129 |
1 files changed, 117 insertions, 12 deletions
diff --git a/src/lib/exchange_api_reserves_open.c b/src/lib/exchange_api_reserves_open.c index 64d259ba0..2b7ef0d90 100644 --- a/src/lib/exchange_api_reserves_open.c +++ b/src/lib/exchange_api_reserves_open.c @@ -27,12 +27,40 @@ #include <gnunet/gnunet_curl_lib.h> #include "taler_exchange_service.h" #include "taler_json_lib.h" +#include "exchange_api_common.h" #include "exchange_api_handle.h" #include "taler_signatures.h" #include "exchange_api_curl_defaults.h" /** + * Information we keep per coin to validate the reply. + */ +struct CoinData +{ + /** + * Public key of the coin. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + /** + * Signature by the coin. + */ + struct TALER_CoinSpendSignatureP coin_sig; + + /** + * The hash of the denomination's public key + */ + struct TALER_DenominationHashP h_denom_pub; + + /** + * How much did this coin contribute. + */ + struct TALER_Amount contribution; +}; + + +/** * @brief A /reserves/$RID/open Handle */ struct TALER_EXCHANGE_ReservesOpenHandle @@ -70,6 +98,16 @@ struct TALER_EXCHANGE_ReservesOpenHandle void *cb_cls; /** + * Information we keep per coin to validate the reply. + */ + struct CoinData *coins; + + /** + * Length of the @e coins array. + */ + unsigned int num_coins; + + /** * Public key of the reserve we are querying. */ struct TALER_ReservePublicKeyP reserve_pub; @@ -282,12 +320,74 @@ handle_reserves_open_finished (void *cls, rs.hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_CONFLICT: - // FIXME: not yet specified (#7428), but needed in - // case of double-spending or insufficient - // reserve balance! - rs.hr.ec = TALER_JSON_get_error_code (j); - rs.hr.hint = TALER_JSON_get_error_hint (j); - break; + { + const struct TALER_EXCHANGE_Keys *keys; + const struct CoinData *cd = NULL; + struct TALER_CoinSpendPublicKeyP coin_pub; + const struct TALER_EXCHANGE_DenomPublicKey *dk; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("coin_pub", + &coin_pub), + GNUNET_JSON_spec_end () + }; + + keys = TALER_EXCHANGE_get_keys (roh->exchange); + GNUNET_assert (NULL != keys); + if (GNUNET_OK != + GNUNET_JSON_parse (j, + spec, + NULL, + NULL)) + { + GNUNET_break_op (0); + rs.hr.http_status = 0; + rs.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + break; + } + for (unsigned int i = 0; i<roh->num_coins; i++) + { + const struct CoinData *cdi = &roh->coins[i]; + + if (0 == GNUNET_memcmp (&coin_pub, + &cdi->coin_pub)) + { + cd = cdi; + break; + } + } + if (NULL == cd) + { + GNUNET_break_op (0); + rs.hr.http_status = 0; + rs.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + break; + } + dk = TALER_EXCHANGE_get_denomination_key_by_hash (keys, + &cd->h_denom_pub); + if (NULL == dk) + { + GNUNET_break_op (0); + rs.hr.http_status = 0; + rs.hr.ec = TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR; + break; + } + if (GNUNET_OK != + TALER_EXCHANGE_check_coin_conflict_ (keys, + j, + dk, + &coin_pub, + &cd->coin_sig, + &cd->contribution)) + { + GNUNET_break_op (0); + rs.hr.http_status = 0; + rs.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + break; + } + rs.hr.ec = TALER_JSON_get_error_code (j); + rs.hr.hint = TALER_JSON_get_error_hint (j); + break; + } case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: if (GNUNET_OK != handle_reserves_open_kyc (roh, @@ -402,18 +502,21 @@ TALER_EXCHANGE_reserves_open ( min_purses, reserve_priv, &roh->reserve_sig); + roh->coins = GNUNET_new_array (coin_payments_length, + struct CoinData); cpa = json_array (); GNUNET_assert (NULL != cpa); for (unsigned int i = 0; i<coin_payments_length; i++) { const struct TALER_EXCHANGE_PurseDeposit *pd = &coin_payments[i]; - struct TALER_CoinSpendSignatureP coin_sig; - struct TALER_CoinSpendPublicKeyP coin_pub; const struct TALER_AgeCommitmentProof *acp = pd->age_commitment_proof; struct TALER_AgeCommitmentHash ahac; struct TALER_AgeCommitmentHash *achp = NULL; + struct CoinData *cd = &roh->coins[i]; json_t *cp; + cd->contribution = pd->amount; + cd->h_denom_pub = pd->h_denom_pub; if (NULL != acp) { TALER_age_commitment_hash (&acp->commitment, @@ -423,9 +526,9 @@ TALER_EXCHANGE_reserves_open ( TALER_wallet_reserve_open_deposit_sign (&pd->amount, &roh->reserve_sig, &pd->coin_priv, - &coin_sig); + &cd->coin_sig); GNUNET_CRYPTO_eddsa_key_get_public (&pd->coin_priv.eddsa_priv, - &coin_pub.eddsa_pub); + &cd->coin_pub.eddsa_pub); cp = GNUNET_JSON_PACK ( GNUNET_JSON_pack_allow_null ( @@ -438,9 +541,9 @@ TALER_EXCHANGE_reserves_open ( TALER_JSON_pack_denom_sig ("ub_sig", &pd->denom_sig), GNUNET_JSON_pack_data_auto ("coin_pub", - &coin_pub), + &cd->coin_pub), GNUNET_JSON_pack_data_auto ("coin_sig", - &coin_sig)); + &cd->coin_sig)); GNUNET_assert (0 == json_array_append_new (cpa, cp)); @@ -468,6 +571,7 @@ TALER_EXCHANGE_reserves_open ( GNUNET_break (0); curl_easy_cleanup (eh); json_decref (open_obj); + GNUNET_free (roh->coins); GNUNET_free (roh->url); GNUNET_free (roh); return NULL; @@ -494,6 +598,7 @@ TALER_EXCHANGE_reserves_open_cancel ( roh->job = NULL; } TALER_curl_easy_post_finished (&roh->post_ctx); + GNUNET_free (roh->coins); GNUNET_free (roh->url); GNUNET_free (roh); } |