exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 8613b596000e80c18addd174b84ee518261b0009
parent 31c134102eeabd2a0f68e2cb8893790803d5e93f
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon,  2 Mar 2026 17:11:45 +0100

complete libtalerexchange API cleanup, 1st pass

Diffstat:
Msrc/exchange-tools/taler-auditor-offline.c | 24+++++++++++++-----------
Msrc/exchangedb/pg_do_withdraw.c | 2+-
Msrc/include/taler/taler-exchange/get-aml-OFFICER_PUB-transfers-credit.h | 68--------------------------------------------------------------------
Msrc/include/taler/taler-exchange/get-coins-COIN_PUB-history.h | 54------------------------------------------------------
Msrc/include/taler/taler-exchange/get-contracts-CONTRACT_PUB.h | 53-----------------------------------------------------
Msrc/include/taler/taler-exchange/get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.h | 129+++++++++++++++++++++----------------------------------------------------------
Msrc/include/taler/taler-exchange/get-purses-PURSE_PUB-merge.h | 57---------------------------------------------------------
Msrc/include/taler/taler-exchange/get-reserves-RESERVE_PUB-history.h | 58----------------------------------------------------------
Msrc/include/taler/taler-exchange/get-reserves-RESERVE_PUB.h | 53-----------------------------------------------------
Msrc/include/taler/taler-exchange/get-reserves-attest-RESERVE_PUB.h | 52----------------------------------------------------
Msrc/include/taler/taler-exchange/get-transfers-WTID.h | 52----------------------------------------------------
Msrc/include/taler/taler-exchange/post-auditors-AUDITOR_PUB-H_DENOM_PUB.h | 46----------------------------------------------
Msrc/include/taler/taler-exchange/post-batch-deposit.h | 78------------------------------------------------------------------------------
Msrc/include/taler/taler-exchange/post-blinding-prepare.h | 96-------------------------------------------------------------------------------
Msrc/include/taler/taler-exchange/post-coins-COIN_PUB-refund.h | 56--------------------------------------------------------
Msrc/include/taler/taler-exchange/post-melt.h | 56--------------------------------------------------------
Msrc/include/taler/taler-exchange/post-purses-PURSE_PUB-create.h | 78++----------------------------------------------------------------------------
Msrc/include/taler/taler-exchange/post-purses-PURSE_PUB-deposit.h | 59-----------------------------------------------------------
Msrc/include/taler/taler-exchange/post-purses-PURSE_PUB-merge.h | 64----------------------------------------------------------------
Msrc/include/taler/taler-exchange/post-recoup-refresh.h | 57---------------------------------------------------------
Msrc/include/taler/taler-exchange/post-recoup-withdraw.h | 55-------------------------------------------------------
Msrc/include/taler/taler-exchange/post-reserves-RESERVE_PUB-close.h | 53-----------------------------------------------------
Msrc/include/taler/taler-exchange/post-reserves-RESERVE_PUB-open.h | 69---------------------------------------------------------------------
Msrc/include/taler/taler-exchange/post-reserves-RESERVE_PUB-purse.h | 70++--------------------------------------------------------------------
Msrc/include/taler/taler-exchange/post-reserves-attest-RESERVE_PUB.h | 58----------------------------------------------------------
Msrc/include/taler/taler-exchange/post-reveal-melt.h | 53-----------------------------------------------------
Msrc/include/taler/taler-exchange/post-reveal-withdraw.h | 55-------------------------------------------------------
Msrc/include/taler/taler-exchange/post-withdraw.h | 521+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/include/taler/taler_error_codes.h | 8++++++++
Msrc/lib/exchange_api_get-coins-COIN_PUB-history.c | 250++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/lib/exchange_api_get-contracts-CONTRACT_PUB.c | 140++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/lib/exchange_api_get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.c | 236+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/lib/exchange_api_get-purses-PURSE_PUB-merge.c | 193+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/lib/exchange_api_get-reserves-RESERVE_PUB-history.c | 270++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/lib/exchange_api_get-reserves-RESERVE_PUB.c | 203+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/lib/exchange_api_get-reserves-attest-RESERVE_PUB.c | 150+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/lib/exchange_api_get-transfers-WTID.c | 166+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/lib/exchange_api_post-auditors-AUDITOR_PUB-H_DENOM_PUB.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/lib/exchange_api_post-batch-deposit.c | 216+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/lib/exchange_api_post-blinding-prepare.c | 215++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/lib/exchange_api_post-coins-COIN_PUB-refund.c | 174++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/lib/exchange_api_post-melt.c | 135++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/lib/exchange_api_post-purses-PURSE_PUB-create.c | 373+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/lib/exchange_api_post-purses-PURSE_PUB-deposit.c | 177+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/lib/exchange_api_post-purses-PURSE_PUB-merge.c | 177+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/lib/exchange_api_post-recoup-refresh.c | 169+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/lib/exchange_api_post-recoup-withdraw.c | 162+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/lib/exchange_api_post-reserves-RESERVE_PUB-close.c | 257++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/lib/exchange_api_post-reserves-RESERVE_PUB-open.c | 310++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/lib/exchange_api_post-reserves-RESERVE_PUB-purse.c | 454++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/lib/exchange_api_post-reserves-attest-RESERVE_PUB.c | 240++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/lib/exchange_api_post-reveal-melt.c | 95++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/lib/exchange_api_post-reveal-withdraw.c | 134+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/lib/exchange_api_post-withdraw.c | 870+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/testing/testing_api_cmd_age_withdraw.c | 45+++++++++++++++++++++++++++------------------
Msrc/testing/testing_api_cmd_auditor_add_denom_sig.c | 19++++++++++---------
Msrc/testing/testing_api_cmd_batch_deposit.c | 13+++++++------
Msrc/testing/testing_api_cmd_batch_withdraw.c | 18++++++++++--------
Msrc/testing/testing_api_cmd_coin_history.c | 18++++++++++--------
Msrc/testing/testing_api_cmd_contract_get.c | 23++++++++++++++++-------
Msrc/testing/testing_api_cmd_deposit.c | 13+++++++------
Msrc/testing/testing_api_cmd_deposits_get.c | 31++++++++++++++++++++++---------
Msrc/testing/testing_api_cmd_purse_create_deposit.c | 30++++++++++++++----------------
Msrc/testing/testing_api_cmd_purse_deposit.c | 16+++++++++-------
Msrc/testing/testing_api_cmd_purse_get.c | 35++++++++++++++++++++++++++---------
Msrc/testing/testing_api_cmd_purse_merge.c | 25++++++++++---------------
Msrc/testing/testing_api_cmd_recoup.c | 16+++++++++-------
Msrc/testing/testing_api_cmd_recoup_refresh.c | 16+++++++++-------
Msrc/testing/testing_api_cmd_refresh.c | 43+++++++++++++++++++++++++------------------
Msrc/testing/testing_api_cmd_refund.c | 16+++++++++-------
Msrc/testing/testing_api_cmd_reserve_attest.c | 32+++++++++++++++++++++++++-------
Msrc/testing/testing_api_cmd_reserve_close.c | 40++++++++++++++++++++++++++++++++--------
Msrc/testing/testing_api_cmd_reserve_get.c | 34++++++++++++++++++++++++++--------
Msrc/testing/testing_api_cmd_reserve_get_attestable.c | 29++++++++++++++++++++++-------
Msrc/testing/testing_api_cmd_reserve_history.c | 30++++++++++++++++++++++--------
Msrc/testing/testing_api_cmd_reserve_open.c | 32+++++++++++++++++++++++++-------
Msrc/testing/testing_api_cmd_reserve_purse.c | 22++++++++++++++--------
Msrc/testing/testing_api_cmd_transfer_get.c | 16+++++++++-------
Msrc/testing/testing_api_cmd_withdraw.c | 25+++++++++++++++----------
Msrc/util/taler_error_codes.c | 10+++++++++-
80 files changed, 4159 insertions(+), 4497 deletions(-)

diff --git a/src/exchange-tools/taler-auditor-offline.c b/src/exchange-tools/taler-auditor-offline.c @@ -148,7 +148,7 @@ struct DenominationAddRequest /** * Operation handle. */ - struct TALER_EXCHANGE_AuditorAddDenominationHandle *h; + struct TALER_EXCHANGE_PostAuditorsHandle *h; /** * Array index of the associated command. @@ -196,7 +196,7 @@ do_shutdown (void *cls) fprintf (stderr, "Aborting incomplete wire add #%u\n", (unsigned int) dar->idx); - TALER_EXCHANGE_add_auditor_denomination_cancel (dar->h); + TALER_EXCHANGE_post_auditors_cancel (dar->h); GNUNET_CONTAINER_DLL_remove (dar_head, dar_tail, dar); @@ -394,7 +394,7 @@ load_offline_key (int do_create) static void denomination_add_cb ( void *cls, - const struct TALER_EXCHANGE_AuditorAddDenominationResponse *adr) + const struct TALER_EXCHANGE_PostAuditorsResponse *adr) { struct DenominationAddRequest *dar = cls; const struct TALER_EXCHANGE_HttpResponse *hr = &adr->hr; @@ -461,14 +461,16 @@ upload_denomination_add (const char *exchange_url, } dar = GNUNET_new (struct DenominationAddRequest); dar->idx = idx; - dar->h = - TALER_EXCHANGE_add_auditor_denomination (ctx, - exchange_url, - &h_denom_pub, - &auditor_pub, - &auditor_sig, - &denomination_add_cb, - dar); + dar->h = TALER_EXCHANGE_post_auditors_create (ctx, + exchange_url, + &h_denom_pub, + &auditor_pub, + &auditor_sig); + GNUNET_assert (NULL != dar->h); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_auditors_start (dar->h, + &denomination_add_cb, + dar)); GNUNET_CONTAINER_DLL_insert (dar_head, dar_tail, dar); diff --git a/src/exchangedb/pg_do_withdraw.c b/src/exchangedb/pg_do_withdraw.c @@ -107,7 +107,7 @@ TEH_PG_do_withdraw ( }; enum GNUNET_DB_QueryStatus qs; - GNUNET_assert ((withdraw->no_blinding_seed) == + GNUNET_assert ((! withdraw->no_blinding_seed) || (0 == withdraw->num_cs_r_values)); gc = GNUNET_TIME_absolute_to_timestamp ( diff --git a/src/include/taler/taler-exchange/get-aml-OFFICER_PUB-transfers-credit.h b/src/include/taler/taler-exchange/get-aml-OFFICER_PUB-transfers-credit.h @@ -389,72 +389,4 @@ TALER_EXCHANGE_get_aml_transfers_cancel ( struct TALER_EXCHANGE_GetAmlTransfersHandle *atgh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_GetAmlTransfersEntry instead. - */ -struct TALER_EXCHANGE_AmlTransfersKycauthGetTransferEntry -{ - uint64_t rowid; - const char *payto_uri; - struct TALER_Amount amount; - struct GNUNET_TIME_Timestamp execution_time; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_GetAmlTransfersResponse instead. - */ -struct TALER_EXCHANGE_AmlTransfersKycauthGetResult -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - size_t transfers_length; - const struct TALER_EXCHANGE_AmlTransfersKycauthGetTransferEntry *transfers - ; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_GetAmlTransfersCallback instead. - */ -typedef void -(*TALER_EXCHANGE_AmlTransfersKycauthGetCallback)( - void *cls, - const struct TALER_EXCHANGE_AmlTransfersKycauthGetResult *result); - -/** - * @deprecated Use #TALER_EXCHANGE_GetAmlTransfersHandle instead. - */ -struct TALER_EXCHANGE_AmlTransfersKycauthGetHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_get_aml_transfers_kycauth_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_AmlTransfersKycauthGetHandle * -TALER_EXCHANGE_aml_transfers_kycauth_get ( - struct GNUNET_CURL_Context *ctx, - const char *exchange_url, - const struct TALER_NormalizedPaytoHashP *h_payto, - const struct TALER_Amount *threshold, - uint64_t offset, - int64_t limit, - const struct TALER_AmlOfficerPrivateKeyP *officer_priv, - TALER_EXCHANGE_AmlTransfersKycauthGetCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_get_aml_transfers_cancel() instead. - */ -void -TALER_EXCHANGE_aml_transfers_kycauth_get_cancel ( - struct TALER_EXCHANGE_AmlTransfersKycauthGetHandle *atkgh); - - #endif /* _TALER_EXCHANGE__GET_AML_OFFICER_PUB_TRANSFERS_CREDIT_H */ diff --git a/src/include/taler/taler-exchange/get-coins-COIN_PUB-history.h b/src/include/taler/taler-exchange/get-coins-COIN_PUB-history.h @@ -492,58 +492,4 @@ TALER_EXCHANGE_get_coins_history_cancel ( struct TALER_EXCHANGE_GetCoinsHistoryHandle *gcsh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_GetCoinsHistoryResponse instead. - */ -struct TALER_EXCHANGE_CoinHistory -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - const json_t *history; - struct TALER_DenominationHashP h_denom_pub; - struct TALER_Amount balance; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_GetCoinsHistoryCallback instead. - */ -typedef void -(*TALER_EXCHANGE_CoinsHistoryCallback)( - void *cls, - const struct TALER_EXCHANGE_CoinHistory *ch); - -/** - * @deprecated Use #TALER_EXCHANGE_GetCoinsHistoryHandle instead. - */ -struct TALER_EXCHANGE_CoinsHistoryHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_get_coins_history_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_CoinsHistoryHandle * -TALER_EXCHANGE_coins_history ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_CoinSpendPrivateKeyP *coin_priv, - uint64_t start_off, - TALER_EXCHANGE_CoinsHistoryCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_get_coins_history_cancel() instead. - */ -void -TALER_EXCHANGE_coins_history_cancel ( - struct TALER_EXCHANGE_CoinsHistoryHandle *rsh); - - #endif /* _TALER_EXCHANGE__GET_COINS_COIN_PUB_HISTORY_H */ diff --git a/src/include/taler/taler-exchange/get-contracts-CONTRACT_PUB.h b/src/include/taler/taler-exchange/get-contracts-CONTRACT_PUB.h @@ -136,57 +136,4 @@ TALER_EXCHANGE_get_contracts_cancel ( struct TALER_EXCHANGE_GetContractsHandle *gch); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_GetContractsResponse instead. - */ -struct TALER_EXCHANGE_ContractGetResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct TALER_PurseContractPublicKeyP purse_pub; - const void *econtract; - size_t econtract_size; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_GetContractsCallback instead. - */ -typedef void -(*TALER_EXCHANGE_ContractGetCallback) ( - void *cls, - const struct TALER_EXCHANGE_ContractGetResponse *cgr); - -/** - * @deprecated Use #TALER_EXCHANGE_GetContractsHandle instead. - */ -struct TALER_EXCHANGE_ContractsGetHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_get_contracts_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_ContractsGetHandle * -TALER_EXCHANGE_contract_get ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_ContractDiffiePrivateP *contract_priv, - TALER_EXCHANGE_ContractGetCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_get_contracts_cancel() instead. - */ -void -TALER_EXCHANGE_contract_get_cancel ( - struct TALER_EXCHANGE_ContractsGetHandle *cgh); - - #endif /* _TALER_EXCHANGE__GET_CONTRACTS_CONTRACT_PUB_H */ diff --git a/src/include/taler/taler-exchange/get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.h b/src/include/taler/taler-exchange/get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.h @@ -172,6 +172,39 @@ TALER_EXCHANGE_get_deposits_set_options_ ( /** + * Data returned for a successfully executed wire transfer (HTTP 200 OK). + */ +struct TALER_EXCHANGE_DepositData +{ + /** + * Exchange key used to sign. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * Signature from the exchange over the deposit data. + */ + struct TALER_ExchangeSignatureP exchange_sig; + + /** + * Wire transfer identifier used by the exchange. + */ + struct TALER_WireTransferIdentifierRawP wtid; + + /** + * Actual execution time for the wire transfer. + */ + struct GNUNET_TIME_Timestamp execution_time; + + /** + * This coin's contribution to the total wire transfer amount. + */ + struct TALER_Amount coin_contribution; + +}; + + +/** * Data returned for a successful GET /deposits/... request. */ struct TALER_EXCHANGE_GetDepositsResponse @@ -190,34 +223,7 @@ struct TALER_EXCHANGE_GetDepositsResponse * Response if the status was #MHD_HTTP_OK. * The wire transfer has been executed. */ - struct - { - /** - * Exchange key used to sign. - */ - struct TALER_ExchangePublicKeyP exchange_pub; - - /** - * Signature from the exchange over the deposit data. - */ - struct TALER_ExchangeSignatureP exchange_sig; - - /** - * Wire transfer identifier used by the exchange. - */ - struct TALER_WireTransferIdentifierRawP wtid; - - /** - * Actual execution time for the wire transfer. - */ - struct GNUNET_TIME_Timestamp execution_time; - - /** - * This coin's contribution to the total wire transfer amount. - */ - struct TALER_Amount coin_contribution; - - } ok; + struct TALER_EXCHANGE_DepositData ok; /** * Response if the status was #MHD_HTTP_ACCEPTED. @@ -305,72 +311,5 @@ TALER_EXCHANGE_get_deposits_cancel ( struct TALER_EXCHANGE_GetDepositsHandle *gdh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_GetDepositsResponse instead. - */ -struct TALER_EXCHANGE_GetDepositResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct TALER_EXCHANGE_DepositData - { - struct TALER_ExchangePublicKeyP exchange_pub; - struct TALER_ExchangeSignatureP exchange_sig; - struct TALER_WireTransferIdentifierRawP wtid; - struct GNUNET_TIME_Timestamp execution_time; - struct TALER_Amount coin_contribution; - } ok; - struct - { - struct GNUNET_TIME_Timestamp execution_time; - union TALER_AccountPublicKeyP account_pub; - uint64_t requirement_row; - bool kyc_ok; - } accepted; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_GetDepositsCallback instead. - */ -typedef void -(*TALER_EXCHANGE_DepositGetCallback)( - void *cls, - const struct TALER_EXCHANGE_GetDepositResponse *dr); - -/** - * @deprecated Use #TALER_EXCHANGE_GetDepositsHandle instead. - */ -struct TALER_EXCHANGE_DepositGetHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_get_deposits_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_DepositGetHandle * -TALER_EXCHANGE_deposits_get ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_MerchantPrivateKeyP *merchant_priv, - const struct TALER_MerchantWireHashP *h_wire, - const struct TALER_PrivateContractHashP *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct GNUNET_TIME_Relative timeout, - TALER_EXCHANGE_DepositGetCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_get_deposits_cancel() instead. - */ -void -TALER_EXCHANGE_deposits_get_cancel ( - struct TALER_EXCHANGE_DepositGetHandle *dwh); - - #endif /* \ _TALER_EXCHANGE__GET_DEPOSITS_H_WIRE_MERCHANT_PUB_H_CONTRACT_TERMS_COIN_PUB_H */ diff --git a/src/include/taler/taler-exchange/get-purses-PURSE_PUB-merge.h b/src/include/taler/taler-exchange/get-purses-PURSE_PUB-merge.h @@ -287,61 +287,4 @@ TALER_EXCHANGE_get_purses_cancel ( struct TALER_EXCHANGE_GetPursesHandle *gph); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_GetPursesResponse instead. - */ -struct TALER_EXCHANGE_PurseGetResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct GNUNET_TIME_Timestamp merge_timestamp; - struct GNUNET_TIME_Timestamp deposit_timestamp; - struct TALER_Amount balance; - struct GNUNET_TIME_Timestamp purse_expiration; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_GetPursesCallback instead. - */ -typedef void -(*TALER_EXCHANGE_PurseGetCallback) ( - void *cls, - const struct TALER_EXCHANGE_PurseGetResponse *pgr); - -/** - * @deprecated Use #TALER_EXCHANGE_GetPursesHandle instead. - */ -struct TALER_EXCHANGE_PurseGetHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_get_purses_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_PurseGetHandle * -TALER_EXCHANGE_purse_get ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_PurseContractPublicKeyP *purse_pub, - struct GNUNET_TIME_Relative timeout, - bool wait_for_merge, - TALER_EXCHANGE_PurseGetCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_get_purses_cancel() instead. - */ -void -TALER_EXCHANGE_purse_get_cancel ( - struct TALER_EXCHANGE_PurseGetHandle *pgh); - - #endif /* _TALER_EXCHANGE__GET_PURSES_PURSE_PUB_MERGE_H */ diff --git a/src/include/taler/taler-exchange/get-reserves-RESERVE_PUB-history.h b/src/include/taler/taler-exchange/get-reserves-RESERVE_PUB-history.h @@ -277,62 +277,4 @@ TALER_EXCHANGE_get_reserves_history_cancel ( struct TALER_EXCHANGE_GetReservesHistoryHandle *grhh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_GetReservesHistoryResponse instead. - */ -struct TALER_EXCHANGE_ReserveHistory -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct TALER_Amount balance; - struct TALER_Amount total_in; - struct TALER_Amount total_out; - uint64_t etag; - const struct TALER_EXCHANGE_ReserveHistoryEntry *history; - unsigned int history_len; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_GetReservesHistoryCallback instead. - */ -typedef void -(*TALER_EXCHANGE_ReservesHistoryCallback) ( - void *cls, - const struct TALER_EXCHANGE_ReserveHistory *rs); - -/** - * @deprecated Use #TALER_EXCHANGE_GetReservesHistoryHandle instead. - */ -struct TALER_EXCHANGE_ReservesHistoryHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_get_reserves_history_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_ReservesHistoryHandle * -TALER_EXCHANGE_reserves_history ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_ReservePrivateKeyP *reserve_priv, - uint64_t start_off, - TALER_EXCHANGE_ReservesHistoryCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_get_reserves_history_cancel() instead. - */ -void -TALER_EXCHANGE_reserves_history_cancel ( - struct TALER_EXCHANGE_ReservesHistoryHandle *rsh); - - #endif /* _TALER_EXCHANGE__GET_RESERVES_RESERVE_PUB_HISTORY_H */ diff --git a/src/include/taler/taler-exchange/get-reserves-RESERVE_PUB.h b/src/include/taler/taler-exchange/get-reserves-RESERVE_PUB.h @@ -584,57 +584,4 @@ TALER_EXCHANGE_get_reserves_cancel ( struct TALER_EXCHANGE_GetReservesHandle *grh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_GetReservesResponse instead. - */ -struct TALER_EXCHANGE_ReserveSummary -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct TALER_Amount balance; - struct TALER_FullPayto last_origin; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_GetReservesCallback instead. - */ -typedef void -(*TALER_EXCHANGE_ReservesGetCallback) ( - void *cls, - const struct TALER_EXCHANGE_ReserveSummary *rs); - -/** - * @deprecated Use #TALER_EXCHANGE_GetReservesHandle instead. - */ -struct TALER_EXCHANGE_ReservesGetHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_get_reserves_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_ReservesGetHandle * -TALER_EXCHANGE_reserves_get ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct GNUNET_TIME_Relative timeout, - TALER_EXCHANGE_ReservesGetCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_get_reserves_cancel() instead. - */ -void -TALER_EXCHANGE_reserves_get_cancel ( - struct TALER_EXCHANGE_ReservesGetHandle *rgh); - - #endif /* _TALER_EXCHANGE__GET_RESERVES_RESERVE_PUB_H */ diff --git a/src/include/taler/taler-exchange/get-reserves-attest-RESERVE_PUB.h b/src/include/taler/taler-exchange/get-reserves-attest-RESERVE_PUB.h @@ -131,56 +131,4 @@ TALER_EXCHANGE_get_reserves_attest_cancel ( struct TALER_EXCHANGE_GetReservesAttestHandle *grah); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_GetReservesAttestResponse instead. - */ -struct TALER_EXCHANGE_ReserveGetAttestResult -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - unsigned int attributes_length; - const char **attributes; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_GetReservesAttestCallback instead. - */ -typedef void -(*TALER_EXCHANGE_ReservesGetAttestCallback) ( - void *cls, - const struct TALER_EXCHANGE_ReserveGetAttestResult *ror); - -/** - * @deprecated Use #TALER_EXCHANGE_GetReservesAttestHandle instead. - */ -struct TALER_EXCHANGE_ReservesGetAttestHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_get_reserves_attest_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_ReservesGetAttestHandle * -TALER_EXCHANGE_reserves_get_attestable ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_ReservePublicKeyP *reserve_pub, - TALER_EXCHANGE_ReservesGetAttestCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_get_reserves_attest_cancel() instead. - */ -void -TALER_EXCHANGE_reserves_get_attestable_cancel ( - struct TALER_EXCHANGE_ReservesGetAttestHandle *rgah); - - #endif /* _TALER_EXCHANGE__GET_RESERVES_ATTEST_RESERVE_PUB_H */ diff --git a/src/include/taler/taler-exchange/get-transfers-WTID.h b/src/include/taler/taler-exchange/get-transfers-WTID.h @@ -180,56 +180,4 @@ TALER_EXCHANGE_get_transfers_cancel ( struct TALER_EXCHANGE_GetTransfersHandle *gth); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_GetTransfersResponse instead. - */ -struct TALER_EXCHANGE_TransfersGetResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct TALER_EXCHANGE_TransferData td; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_GetTransfersCallback instead. - */ -typedef void -(*TALER_EXCHANGE_TransfersGetCallback)( - void *cls, - const struct TALER_EXCHANGE_TransfersGetResponse *tgr); - -/** - * @deprecated Use #TALER_EXCHANGE_GetTransfersHandle instead. - */ -struct TALER_EXCHANGE_TransfersGetHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_get_transfers_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_TransfersGetHandle * -TALER_EXCHANGE_transfers_get ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_WireTransferIdentifierRawP *wtid, - TALER_EXCHANGE_TransfersGetCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_get_transfers_cancel() instead. - */ -void -TALER_EXCHANGE_transfers_get_cancel ( - struct TALER_EXCHANGE_TransfersGetHandle *wdh); - - #endif /* _TALER_EXCHANGE__GET_TRANSFERS_WTID_H */ diff --git a/src/include/taler/taler-exchange/post-auditors-AUDITOR_PUB-H_DENOM_PUB.h b/src/include/taler/taler-exchange/post-auditors-AUDITOR_PUB-H_DENOM_PUB.h @@ -111,50 +111,4 @@ TALER_EXCHANGE_post_auditors_cancel ( struct TALER_EXCHANGE_PostAuditorsHandle *pah); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostAuditorsResponse instead. - */ -struct TALER_EXCHANGE_AuditorAddDenominationResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostAuditorsCallback instead. - */ -typedef void -(*TALER_EXCHANGE_AuditorAddDenominationCallback) ( - void *cls, - const struct TALER_EXCHANGE_AuditorAddDenominationResponse *adr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostAuditorsHandle instead. - */ -struct TALER_EXCHANGE_AuditorAddDenominationHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_auditors_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_AuditorAddDenominationHandle * -TALER_EXCHANGE_add_auditor_denomination ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_DenominationHashP *h_denom_pub, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const struct TALER_AuditorSignatureP *auditor_sig, - TALER_EXCHANGE_AuditorAddDenominationCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_auditors_cancel() instead. - */ -void -TALER_EXCHANGE_add_auditor_denomination_cancel ( - struct TALER_EXCHANGE_AuditorAddDenominationHandle *ah); - - #endif /* _TALER_EXCHANGE__POST_AUDITORS_AUDITOR_PUB_H_DENOM_PUB_H */ diff --git a/src/include/taler/taler-exchange/post-batch-deposit.h b/src/include/taler/taler-exchange/post-batch-deposit.h @@ -319,82 +319,4 @@ TALER_EXCHANGE_post_batch_deposit_cancel ( struct TALER_EXCHANGE_PostBatchDepositHandle *pbdh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostBatchDepositResponse instead. - */ -struct TALER_EXCHANGE_BatchDepositResult -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct GNUNET_TIME_Timestamp deposit_timestamp; - const struct TALER_ExchangeSignatureP *exchange_sig; - const struct TALER_ExchangePublicKeyP *exchange_pub; - const char *transaction_base_url; - } ok; - struct - { - union - { - struct { struct TALER_CoinSpendPublicKeyP coin_pub; } insufficient_funds - ; - struct { struct TALER_CoinSpendPublicKeyP coin_pub; } - coin_conflicting_age_hash; - struct { struct TALER_CoinSpendPublicKeyP coin_pub; } - coin_conflicting_denomination_key; - } details; - } conflict; - struct TALER_EXCHANGE_KycNeededRedirect unavailable_for_legal_reasons; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostBatchDepositCallback instead. - */ -typedef void -(*TALER_EXCHANGE_BatchDepositResultCallback) ( - void *cls, - const struct TALER_EXCHANGE_BatchDepositResult *dr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostBatchDepositHandle instead. - */ -struct TALER_EXCHANGE_BatchDepositHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_batch_deposit_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_BatchDepositHandle * -TALER_EXCHANGE_batch_deposit ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_EXCHANGE_DepositContractDetail *dcd, - unsigned int num_cdds, - const struct TALER_EXCHANGE_CoinDepositDetail cdds[static num_cdds], - TALER_EXCHANGE_BatchDepositResultCallback cb, - void *cb_cls, - enum TALER_ErrorCode *ec); - -/** - * @deprecated Use #TALER_EXCHANGE_post_batch_deposit_force_dc() instead. - */ -void -TALER_EXCHANGE_batch_deposit_force_dc ( - struct TALER_EXCHANGE_BatchDepositHandle *deposit); - -/** - * @deprecated Use #TALER_EXCHANGE_post_batch_deposit_cancel() instead. - */ -void -TALER_EXCHANGE_batch_deposit_cancel ( - struct TALER_EXCHANGE_BatchDepositHandle *deposit); - - #endif /* _TALER_EXCHANGE__POST_BATCH_DEPOSIT_H */ diff --git a/src/include/taler/taler-exchange/post-blinding-prepare.h b/src/include/taler/taler-exchange/post-blinding-prepare.h @@ -193,100 +193,4 @@ TALER_EXCHANGE_post_blinding_prepare_cancel ( struct TALER_EXCHANGE_PostBlindingPrepareHandle *pbph); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostBlindingPrepareResponse instead. - */ -struct TALER_EXCHANGE_BlindingPrepareResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - size_t num_blinding_values; - const struct TALER_ExchangeBlindingValues *blinding_values; - } ok; - struct { /* TODO: maybe add details for status #MHD_HTTP_GONE */ } gone; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostBlindingPrepareCallback instead. - */ -typedef void -(*TALER_EXCHANGE_BlindingPrepareCallback)( - void *cls, - const struct TALER_EXCHANGE_BlindingPrepareResponse *bpr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostBlindingPrepareHandle instead. - */ -struct TALER_EXCHANGE_BlindingPrepareHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_blinding_prepare_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_BlindingPrepareHandle * -TALER_EXCHANGE_blinding_prepare ( - struct GNUNET_CURL_Context *curl_ctx, - const char *exchange_url, - const struct TALER_BlindingMasterSeedP *seed, - bool for_melt, - size_t num, - const struct TALER_EXCHANGE_NonceKey nonce_keys[static num], - TALER_EXCHANGE_BlindingPrepareCallback callback, - void *callback_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_blinding_prepare_for_withdraw_create(). - */ -#define TALER_EXCHANGE_blinding_prepare_for_withdraw( \ - curl_ctx, \ - exchange_url, \ - seed, \ - num, \ - nonce_keys, \ - callback, \ - callback_cls) TALER_EXCHANGE_blinding_prepare ( \ - (curl_ctx), \ - (exchange_url), \ - (seed), \ - false, \ - (num), \ - (nonce_keys), \ - (callback), \ - (callback_cls)) - -/** - * @deprecated Use #TALER_EXCHANGE_post_blinding_prepare_for_melt_create(). - */ -#define TALER_EXCHANGE_blinding_prepare_for_melt( \ - curl_ctx, \ - exchange_url, \ - seed, \ - num, \ - nonce_keys, \ - callback, \ - callback_cls) TALER_EXCHANGE_blinding_prepare ( \ - (curl_ctx), \ - (exchange_url), \ - (seed), \ - true, \ - (num), \ - (nonce_keys), \ - (callback), \ - (callback_cls)) - -/** - * @deprecated Use #TALER_EXCHANGE_post_blinding_prepare_cancel() instead. - */ -void -TALER_EXCHANGE_blinding_prepare_cancel ( - struct TALER_EXCHANGE_BlindingPrepareHandle *bph); - - #endif /* _TALER_EXCHANGE__POST_BLINDING_PREPARE_H */ diff --git a/src/include/taler/taler-exchange/post-coins-COIN_PUB-refund.h b/src/include/taler/taler-exchange/post-coins-COIN_PUB-refund.h @@ -143,60 +143,4 @@ TALER_EXCHANGE_post_coins_refund_cancel ( struct TALER_EXCHANGE_PostCoinsRefundHandle *pcrh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostCoinsRefundResponse instead. - */ -struct TALER_EXCHANGE_RefundResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct TALER_ExchangePublicKeyP exchange_pub; - struct TALER_ExchangeSignatureP exchange_sig; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostCoinsRefundCallback instead. - */ -typedef void -(*TALER_EXCHANGE_RefundCallback) ( - void *cls, - const struct TALER_EXCHANGE_RefundResponse *rr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostCoinsRefundHandle instead. - */ -struct TALER_EXCHANGE_RefundHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_coins_refund_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_RefundHandle * -TALER_EXCHANGE_refund ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_Amount *amount, - const struct TALER_PrivateContractHashP *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t rtransaction_id, - const struct TALER_MerchantPrivateKeyP *merchant_priv, - TALER_EXCHANGE_RefundCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_coins_refund_cancel() instead. - */ -void -TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund); - - #endif /* _TALER_EXCHANGE__POST_COINS_COIN_PUB_REFUND_H */ diff --git a/src/include/taler/taler-exchange/post-melt.h b/src/include/taler/taler-exchange/post-melt.h @@ -158,60 +158,4 @@ TALER_EXCHANGE_post_melt_cancel ( struct TALER_EXCHANGE_PostMeltHandle *pmh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostMeltResponse instead. - */ -struct TALER_EXCHANGE_MeltResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - unsigned int num_melt_blinding_values; - const struct TALER_ExchangeBlindingValues *melt_blinding_values; - const struct TALER_BlindingMasterSeedP *blinding_seed; - struct TALER_ExchangePublicKeyP sign_key; - uint32_t noreveal_index; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostMeltCallback instead. - */ -typedef void -(*TALER_EXCHANGE_MeltCallback) ( - void *cls, - const struct TALER_EXCHANGE_MeltResponse *mr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostMeltHandle instead. - */ -struct TALER_EXCHANGE_MeltHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_melt_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_MeltHandle * -TALER_EXCHANGE_melt ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_PublicRefreshMasterSeedP *rms, - const struct TALER_EXCHANGE_MeltInput *melt_input, - TALER_EXCHANGE_MeltCallback melt_cb, - void *melt_cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_melt_cancel() instead. - */ -void -TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh); - - #endif /* _TALER_EXCHANGE__POST_MELT_H */ diff --git a/src/include/taler/taler-exchange/post-purses-PURSE_PUB-create.h b/src/include/taler/taler-exchange/post-purses-PURSE_PUB-create.h @@ -55,19 +55,6 @@ struct TALER_EXCHANGE_PostPursesCreateOptionValue */ enum TALER_EXCHANGE_PostPursesCreateOption option; - /** - * Specific option value. - */ - union - { - /** - * Value if @e option is - * #TALER_EXCHANGE_POST_PURSES_CREATE_OPTION_UPLOAD_CONTRACT. - */ - bool upload_contract; - - } details; - }; @@ -117,16 +104,14 @@ TALER_EXCHANGE_post_purses_create_create ( } /** - * Set whether to upload the contract to the exchange. + * Set the flag that we are to upload the contract to the exchange to TRUE. * - * @param u true to upload the contract * @return representation of the option as a struct TALER_EXCHANGE_PostPursesCreateOptionValue */ -#define TALER_EXCHANGE_post_purses_create_option_upload_contract(u) \ +#define TALER_EXCHANGE_post_purses_create_option_upload_contract() \ (const struct TALER_EXCHANGE_PostPursesCreateOptionValue) \ { \ .option = TALER_EXCHANGE_POST_PURSES_CREATE_OPTION_UPLOAD_CONTRACT, \ - .details.upload_contract = (u) \ } @@ -259,63 +244,4 @@ TALER_EXCHANGE_post_purses_create_cancel ( struct TALER_EXCHANGE_PostPursesCreateHandle *ppch); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostPursesCreateResponse instead. - */ -struct TALER_EXCHANGE_PurseCreateDepositResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct TALER_ExchangePublicKeyP exchange_pub; - struct TALER_ExchangeSignatureP exchange_sig; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostPursesCreateCallback instead. - */ -typedef void -(*TALER_EXCHANGE_PurseCreateDepositCallback) ( - void *cls, - const struct TALER_EXCHANGE_PurseCreateDepositResponse *pcr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostPursesCreateHandle instead. - */ -struct TALER_EXCHANGE_PurseCreateDepositHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_purses_create_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_PurseCreateDepositHandle * -TALER_EXCHANGE_purse_create_with_deposit ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_PurseContractPrivateKeyP *purse_priv, - const struct TALER_PurseMergePrivateKeyP *merge_priv, - const struct TALER_ContractDiffiePrivateP *contract_priv, - const json_t *contract_terms, - unsigned int num_deposits, - const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits], - bool upload_contract, - TALER_EXCHANGE_PurseCreateDepositCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_purses_create_cancel() instead. - */ -void -TALER_EXCHANGE_purse_create_with_deposit_cancel ( - struct TALER_EXCHANGE_PurseCreateDepositHandle *pch); - - #endif /* _TALER_EXCHANGE__POST_PURSES_PURSE_PUB_CREATE_H */ diff --git a/src/include/taler/taler-exchange/post-purses-PURSE_PUB-deposit.h b/src/include/taler/taler-exchange/post-purses-PURSE_PUB-deposit.h @@ -150,63 +150,4 @@ TALER_EXCHANGE_post_purses_deposit_cancel ( struct TALER_EXCHANGE_PostPursesDepositHandle *ppdh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostPursesDepositResponse instead. - */ -struct TALER_EXCHANGE_PurseDepositResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct GNUNET_TIME_Timestamp purse_expiration; - struct TALER_Amount total_deposited; - struct TALER_Amount purse_value_after_fees; - struct TALER_PrivateContractHashP h_contract_terms; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostPursesDepositCallback instead. - */ -typedef void -(*TALER_EXCHANGE_PurseDepositCallback) ( - void *cls, - const struct TALER_EXCHANGE_PurseDepositResponse *pdr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostPursesDepositHandle instead. - */ -struct TALER_EXCHANGE_PurseDepositHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_purses_deposit_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_PurseDepositHandle * -TALER_EXCHANGE_purse_deposit ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const char *purse_exchange_url, - const struct TALER_PurseContractPublicKeyP *purse_pub, - uint8_t min_age, - unsigned int num_deposits, - const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits], - TALER_EXCHANGE_PurseDepositCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_purses_deposit_cancel() instead. - */ -void -TALER_EXCHANGE_purse_deposit_cancel ( - struct TALER_EXCHANGE_PurseDepositHandle *amh); - - #endif /* _TALER_EXCHANGE__POST_PURSES_PURSE_PUB_DEPOSIT_H */ diff --git a/src/include/taler/taler-exchange/post-purses-PURSE_PUB-merge.h b/src/include/taler/taler-exchange/post-purses-PURSE_PUB-merge.h @@ -164,68 +164,4 @@ TALER_EXCHANGE_post_purses_merge_cancel ( struct TALER_EXCHANGE_PostPursesMergeHandle *ppmh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostPursesMergeResponse instead. - */ -struct TALER_EXCHANGE_AccountMergeResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - const struct TALER_ReserveSignatureP *reserve_sig; - union - { - struct - { - struct TALER_ExchangeSignatureP exchange_sig; - struct TALER_ExchangePublicKeyP exchange_pub; - struct GNUNET_TIME_Timestamp etime; - } ok; - struct TALER_EXCHANGE_KycNeededRedirect unavailable_for_legal_reasons; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostPursesMergeCallback instead. - */ -typedef void -(*TALER_EXCHANGE_AccountMergeCallback) ( - void *cls, - const struct TALER_EXCHANGE_AccountMergeResponse *amr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostPursesMergeHandle instead. - */ -struct TALER_EXCHANGE_AccountMergeHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_purses_merge_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_AccountMergeHandle * -TALER_EXCHANGE_account_merge ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const char *reserve_exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_PurseMergePrivateKeyP *merge_priv, - const struct TALER_PrivateContractHashP *h_contract_terms, - uint8_t min_age, - const struct TALER_Amount *purse_value_after_fees, - struct GNUNET_TIME_Timestamp purse_expiration, - struct GNUNET_TIME_Timestamp merge_timestamp, - TALER_EXCHANGE_AccountMergeCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_purses_merge_cancel() instead. - */ -void -TALER_EXCHANGE_account_merge_cancel ( - struct TALER_EXCHANGE_AccountMergeHandle *amh); - - #endif /* _TALER_EXCHANGE__POST_PURSES_PURSE_PUB_MERGE_H */ diff --git a/src/include/taler/taler-exchange/post-recoup-refresh.h b/src/include/taler/taler-exchange/post-recoup-refresh.h @@ -143,61 +143,4 @@ TALER_EXCHANGE_post_recoup_refresh_cancel ( struct TALER_EXCHANGE_PostRecoupRefreshHandle *prrh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostRecoupRefreshResponse instead. - */ -struct TALER_EXCHANGE_RecoupRefreshResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct TALER_CoinSpendPublicKeyP old_coin_pub; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostRecoupRefreshCallback instead. - */ -typedef void -(*TALER_EXCHANGE_RecoupRefreshResultCallback) ( - void *cls, - const struct TALER_EXCHANGE_RecoupRefreshResponse *rrr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostRecoupRefreshHandle instead. - */ -struct TALER_EXCHANGE_RecoupRefreshHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_recoup_refresh_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_RecoupRefreshHandle * -TALER_EXCHANGE_recoup_refresh ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_EXCHANGE_DenomPublicKey *pk, - const struct TALER_DenominationSignature *denom_sig, - const struct TALER_ExchangeBlindingValues *exchange_vals, - const struct TALER_PublicRefreshMasterSeedP *rms, - const struct TALER_PlanchetMasterSecretP *ps, - unsigned int idx, - TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb, - void *recoup_cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_recoup_refresh_cancel() instead. - */ -void -TALER_EXCHANGE_recoup_refresh_cancel ( - struct TALER_EXCHANGE_RecoupRefreshHandle *ph); - - #endif /* _TALER_EXCHANGE__POST_RECOUP_REFRESH_H */ diff --git a/src/include/taler/taler-exchange/post-recoup-withdraw.h b/src/include/taler/taler-exchange/post-recoup-withdraw.h @@ -139,59 +139,4 @@ TALER_EXCHANGE_post_recoup_withdraw_cancel ( struct TALER_EXCHANGE_PostRecoupWithdrawHandle *prwh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostRecoupWithdrawResponse instead. - */ -struct TALER_EXCHANGE_RecoupResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct TALER_ReservePublicKeyP reserve_pub; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostRecoupWithdrawCallback instead. - */ -typedef void -(*TALER_EXCHANGE_RecoupResultCallback) ( - void *cls, - const struct TALER_EXCHANGE_RecoupResponse *rr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostRecoupWithdrawHandle instead. - */ -struct TALER_EXCHANGE_RecoupHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_recoup_withdraw_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_RecoupHandle * -TALER_EXCHANGE_recoup ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_EXCHANGE_DenomPublicKey *pk, - const struct TALER_DenominationSignature *denom_sig, - const struct TALER_ExchangeBlindingValues *exchange_vals, - const struct TALER_PlanchetMasterSecretP *ps, - const struct TALER_HashBlindedPlanchetsP *h_planchets, - TALER_EXCHANGE_RecoupResultCallback recoup_cb, - void *recoup_cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_recoup_withdraw_cancel() instead. - */ -void -TALER_EXCHANGE_recoup_cancel (struct TALER_EXCHANGE_RecoupHandle *ph); - - #endif /* _TALER_EXCHANGE__POST_RECOUP_WITHDRAW_H */ diff --git a/src/include/taler/taler-exchange/post-reserves-RESERVE_PUB-close.h b/src/include/taler/taler-exchange/post-reserves-RESERVE_PUB-close.h @@ -243,57 +243,4 @@ TALER_EXCHANGE_post_reserves_close_cancel ( struct TALER_EXCHANGE_PostReservesCloseHandle *prch); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesCloseResponse instead. - */ -struct TALER_EXCHANGE_ReserveCloseResult -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct TALER_Amount wire_amount; - } ok; - struct TALER_EXCHANGE_KycNeededRedirect unavailable_for_legal_reasons; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesCloseCallback instead. - */ -typedef void -(*TALER_EXCHANGE_ReservesCloseCallback) ( - void *cls, - const struct TALER_EXCHANGE_ReserveCloseResult *ror); - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesCloseHandle instead. - */ -struct TALER_EXCHANGE_ReservesCloseHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_reserves_close_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_ReservesCloseHandle * -TALER_EXCHANGE_reserves_close ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_FullPayto target_payto_uri, - TALER_EXCHANGE_ReservesCloseCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_reserves_close_cancel() instead. - */ -void -TALER_EXCHANGE_reserves_close_cancel ( - struct TALER_EXCHANGE_ReservesCloseHandle *rch); - - #endif /* _TALER_EXCHANGE__POST_RESERVES_RESERVE_PUB_CLOSE_H */ diff --git a/src/include/taler/taler-exchange/post-reserves-RESERVE_PUB-open.h b/src/include/taler/taler-exchange/post-reserves-RESERVE_PUB-open.h @@ -180,73 +180,4 @@ TALER_EXCHANGE_post_reserves_open_cancel ( struct TALER_EXCHANGE_PostReservesOpenHandle *proh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesOpenResponse instead. - */ -struct TALER_EXCHANGE_ReserveOpenResult -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct GNUNET_TIME_Timestamp expiration_time; - struct TALER_Amount open_cost; - } ok; - struct - { - struct GNUNET_TIME_Timestamp expiration_time; - struct TALER_Amount open_cost; - } payment_required; - struct - { - struct TALER_CoinSpendPublicKeyP coin_pub; - } conflict; - struct TALER_EXCHANGE_KycNeededRedirect unavailable_for_legal_reasons; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesOpenCallback instead. - */ -typedef void -(*TALER_EXCHANGE_ReservesOpenCallback) ( - void *cls, - const struct TALER_EXCHANGE_ReserveOpenResult *ror); - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesOpenHandle instead. - */ -struct TALER_EXCHANGE_ReservesOpenHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_reserves_open_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_ReservesOpenHandle * -TALER_EXCHANGE_reserves_open ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_Amount *reserve_contribution, - unsigned int coin_payments_length, - const struct TALER_EXCHANGE_PurseDeposit coin_payments[ - static coin_payments_length], - struct GNUNET_TIME_Timestamp expiration_time, - uint32_t min_purses, - TALER_EXCHANGE_ReservesOpenCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_reserves_open_cancel() instead. - */ -void -TALER_EXCHANGE_reserves_open_cancel ( - struct TALER_EXCHANGE_ReservesOpenHandle *roh); - - #endif /* _TALER_EXCHANGE__POST_RESERVES_RESERVE_PUB_OPEN_H */ diff --git a/src/include/taler/taler-exchange/post-reserves-RESERVE_PUB-purse.h b/src/include/taler/taler-exchange/post-reserves-RESERVE_PUB-purse.h @@ -58,12 +58,6 @@ struct TALER_EXCHANGE_PostReservesPurseOptionValue */ union { - /** - * Value if @e option is - * #TALER_EXCHANGE_POST_RESERVES_PURSE_OPTION_UPLOAD_CONTRACT. - */ - bool upload_contract; - } details; }; @@ -117,16 +111,14 @@ TALER_EXCHANGE_post_reserves_purse_create ( } /** - * Set whether to upload the contract to the exchange. + * Set flag to upload the contract to the exchange to true. * - * @param u true to upload the contract * @return representation of the option as a struct TALER_EXCHANGE_PostReservesPurseOptionValue */ -#define TALER_EXCHANGE_post_reserves_purse_option_upload_contract(u) \ +#define TALER_EXCHANGE_post_reserves_purse_option_upload_contract() \ (const struct TALER_EXCHANGE_PostReservesPurseOptionValue) \ { \ .option = TALER_EXCHANGE_POST_RESERVES_PURSE_OPTION_UPLOAD_CONTRACT, \ - .details.upload_contract = (u) \ } @@ -259,62 +251,4 @@ TALER_EXCHANGE_post_reserves_purse_cancel ( struct TALER_EXCHANGE_PostReservesPurseHandle *prph); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesPurseResponse instead. - */ -struct TALER_EXCHANGE_PurseCreateMergeResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - const struct TALER_ReserveSignatureP *reserve_sig; - union - { - struct { } ok; - struct TALER_EXCHANGE_KycNeededRedirect unavailable_for_legal_reasons; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesPurseCallback instead. - */ -typedef void -(*TALER_EXCHANGE_PurseCreateMergeCallback) ( - void *cls, - const struct TALER_EXCHANGE_PurseCreateMergeResponse *pcr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesPurseHandle instead. - */ -struct TALER_EXCHANGE_PurseCreateMergeHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_reserves_purse_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_PurseCreateMergeHandle * -TALER_EXCHANGE_purse_create_with_merge ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_PurseContractPrivateKeyP *purse_priv, - const struct TALER_PurseMergePrivateKeyP *merge_priv, - const struct TALER_ContractDiffiePrivateP *contract_priv, - const json_t *contract_terms, - bool upload_contract, - bool pay_for_purse, - struct GNUNET_TIME_Timestamp merge_timestamp, - TALER_EXCHANGE_PurseCreateMergeCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_reserves_purse_cancel() instead. - */ -void -TALER_EXCHANGE_purse_create_with_merge_cancel ( - struct TALER_EXCHANGE_PurseCreateMergeHandle *pcm); - - #endif /* _TALER_EXCHANGE__POST_RESERVES_RESERVE_PUB_PURSE_H */ diff --git a/src/include/taler/taler-exchange/post-reserves-attest-RESERVE_PUB.h b/src/include/taler/taler-exchange/post-reserves-attest-RESERVE_PUB.h @@ -153,62 +153,4 @@ TALER_EXCHANGE_post_reserves_attest_cancel ( struct TALER_EXCHANGE_PostReservesAttestHandle *prah); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesAttestResponse instead. - */ -struct TALER_EXCHANGE_ReservePostAttestResult -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - struct GNUNET_TIME_Timestamp exchange_time; - struct GNUNET_TIME_Timestamp expiration_time; - struct TALER_ExchangeSignatureP exchange_sig; - struct TALER_ExchangePublicKeyP exchange_pub; - const json_t *attributes; - } ok; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesAttestCallback instead. - */ -typedef void -(*TALER_EXCHANGE_ReservesPostAttestCallback) ( - void *cls, - const struct TALER_EXCHANGE_ReservePostAttestResult *ror); - -/** - * @deprecated Use #TALER_EXCHANGE_PostReservesAttestHandle instead. - */ -struct TALER_EXCHANGE_ReservesAttestHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_reserves_attest_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_ReservesAttestHandle * -TALER_EXCHANGE_reserves_attest ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_ReservePrivateKeyP *reserve_priv, - unsigned int attributes_length, - const char *attributes[const static attributes_length], - TALER_EXCHANGE_ReservesPostAttestCallback cb, - void *cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_reserves_attest_cancel() instead. - */ -void -TALER_EXCHANGE_reserves_attest_cancel ( - struct TALER_EXCHANGE_ReservesAttestHandle *rah); - - #endif /* _TALER_EXCHANGE__POST_RESERVES_ATTEST_RESERVE_PUB_H */ diff --git a/src/include/taler/taler-exchange/post-reveal-melt.h b/src/include/taler/taler-exchange/post-reveal-melt.h @@ -292,57 +292,4 @@ TALER_EXCHANGE_post_reveal_melt_cancel ( struct TALER_EXCHANGE_PostRevealMeltHandle *prmh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostRevealMeltResponse instead. - */ -struct TALER_EXCHANGE_RevealMeltResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - const struct TALER_EXCHANGE_RevealedCoinInfo *coins; - unsigned int num_coins; - } ok; - struct TALER_EXCHANGE_KycNeededRedirect unavailable_for_legal_reasons; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostRevealMeltCallback instead. - */ -typedef void -(*TALER_EXCHANGE_RevealMeltCallback)( - void *cls, - const struct TALER_EXCHANGE_RevealMeltResponse *awr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostRevealMeltHandle instead. - */ -struct TALER_EXCHANGE_RevealMeltHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_reveal_melt_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_RevealMeltHandle * -TALER_EXCHANGE_reveal_melt ( - struct GNUNET_CURL_Context *curl_ctx, - const char *exchange_url, - const struct TALER_EXCHANGE_RevealMeltInput *reveal_melt_input, - TALER_EXCHANGE_RevealMeltCallback reveal_cb, - void *reveal_cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_reveal_melt_cancel() instead. - */ -void -TALER_EXCHANGE_reveal_melt_cancel ( - struct TALER_EXCHANGE_RevealMeltHandle *awrh); - - #endif /* _TALER_EXCHANGE__POST_REVEAL_MELT_H */ diff --git a/src/include/taler/taler-exchange/post-reveal-withdraw.h b/src/include/taler/taler-exchange/post-reveal-withdraw.h @@ -151,59 +151,4 @@ TALER_EXCHANGE_post_reveal_withdraw_cancel ( struct TALER_EXCHANGE_PostRevealWithdrawHandle *prwh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostRevealWithdrawResponse instead. - */ -struct TALER_EXCHANGE_RevealWithdrawResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - unsigned int num_sigs; - const struct TALER_BlindedDenominationSignature *blinded_denom_sigs; - } ok; - struct TALER_EXCHANGE_KycNeededRedirect unavailable_for_legal_reasons; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostRevealWithdrawCallback instead. - */ -typedef void -(*TALER_EXCHANGE_RevealWithdrawCallback)( - void *cls, - const struct TALER_EXCHANGE_RevealWithdrawResponse *awr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostRevealWithdrawHandle instead. - */ -struct TALER_EXCHANGE_RevealWithdrawHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_reveal_withdraw_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_RevealWithdrawHandle * -TALER_EXCHANGE_reveal_withdraw ( - struct GNUNET_CURL_Context *curl_ctx, - const char *exchange_url, - size_t num_coins, - const struct TALER_HashBlindedPlanchetsP *h_planchets, - const struct TALER_RevealWithdrawMasterSeedsP *seeds, - TALER_EXCHANGE_RevealWithdrawCallback res_cb, - void *res_cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_reveal_withdraw_cancel() instead. - */ -void -TALER_EXCHANGE_reveal_withdraw_cancel ( - struct TALER_EXCHANGE_RevealWithdrawHandle *awrh); - - #endif /* _TALER_EXCHANGE__POST_REVEAL_WITHDRAW_H */ diff --git a/src/include/taler/taler-exchange/post-withdraw.h b/src/include/taler/taler-exchange/post-withdraw.h @@ -145,6 +145,66 @@ struct TALER_EXCHANGE_PostWithdrawHandle; /** + * Possible options we can set for the POST /withdraw request. + */ +enum TALER_EXCHANGE_PostWithdrawOption +{ + /** + * End of list of options. + */ + TALER_EXCHANGE_POST_WITHDRAW_OPTION_END = 0, + + /** + * Upgrade the withdraw to an age-proof withdrawal, requiring an + * additional call to POST /reveal-withdraw. + * The @e details.max_age field gives the maximum age to (provably) commit to. + */ + TALER_EXCHANGE_POST_WITHDRAW_OPTION_WITH_AGE_PROOF, + + /** + * Provide an explicit blinding seed for CS denominations, overriding + * the default derivation from the master seed. + * Primarily intended for testing. + * The @e details.blinding_seed field provides the seed. + */ + TALER_EXCHANGE_POST_WITHDRAW_OPTION_BLINDING_SEED + +}; + + +/** + * Value for an option we can set for the POST /withdraw request. + */ +struct TALER_EXCHANGE_PostWithdrawOptionValue +{ + /** + * Type of the option being set. + */ + enum TALER_EXCHANGE_PostWithdrawOption option; + + /** + * Specific option value. + */ + union + { + /** + * Value if @e option is + * #TALER_EXCHANGE_POST_WITHDRAW_OPTION_WITH_AGE_PROOF. + */ + uint8_t max_age; + + /** + * Value if @e option is + * #TALER_EXCHANGE_POST_WITHDRAW_OPTION_BLINDING_SEED. + */ + struct TALER_BlindingMasterSeedP blinding_seed; + + } details; + +}; + + +/** * Set up POST /withdraw operation (high-level variant, with automatic * blinding/unblinding). * Note that you must explicitly start the operation after setup. @@ -159,7 +219,7 @@ struct TALER_EXCHANGE_PostWithdrawHandle; * Only when the corresponding reserve has a birthday associated with it, the * exchange might require a _proof_ for the correct age-restriction to be set. * In that case, the exchange will respond with 409 and the client will need - * to call TALER_EXCHANGE_post_withdraw_create_with_age_proof() instead. + * to use the WITH_AGE_PROOF option instead. * * @param curl_ctx The curl context * @param exchange_url The base url of the exchange @@ -184,33 +244,83 @@ TALER_EXCHANGE_post_withdraw_create ( /** - * Set up POST /withdraw operation for age-restricted coins with age proof - * (high-level variant, with automatic blinding/unblinding). - * Note that you must explicitly start the operation after setup. + * Terminate the list of options. * - * This variant requires an additional protocol step /reveal-withdraw to proof - * that the age-restriction is correctly set by the client. + * @return the terminating object + */ +#define TALER_EXCHANGE_post_withdraw_option_end_() \ + (const struct TALER_EXCHANGE_PostWithdrawOptionValue) \ + { \ + .option = TALER_EXCHANGE_POST_WITHDRAW_OPTION_END \ + } + +/** + * Upgrade the withdraw to an age-proof withdrawal. * - * @param curl_ctx The curl context - * @param exchange_url The base url of the exchange - * @param keys The denomination keys from the exchange - * @param reserve_priv The private key to the reserve - * @param num_coins Number of coins to withdraw in a batch - * @param denoms_pub Array of @e num_coins denominations, MUST support age restriction - * @param seed seed from which all @e num_coins coin candidates and other secrets are derived from - * @param max_age maximum age to (provably) commit to - * @return handle to operation, NULL on error + * @param age the maximum age to commit to + * @return representation of the option */ -struct TALER_EXCHANGE_PostWithdrawHandle * -TALER_EXCHANGE_post_withdraw_create_with_age_proof ( - struct GNUNET_CURL_Context *curl_ctx, - const char *exchange_url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_ReservePrivateKeyP *reserve_priv, - size_t num_coins, - const struct TALER_EXCHANGE_DenomPublicKey denoms_pub[static num_coins], - const struct TALER_WithdrawMasterSeedP *seed, - uint8_t max_age); +#define TALER_EXCHANGE_post_withdraw_option_with_age_proof(age) \ + (const struct TALER_EXCHANGE_PostWithdrawOptionValue) \ + { \ + .option = TALER_EXCHANGE_POST_WITHDRAW_OPTION_WITH_AGE_PROOF, \ + .details.max_age = (age) \ + } + +/** + * Set an explicit blinding seed for CS denominations. + * Primarily for testing purposes. + * + * @param s pointer to the blinding seed + * @return representation of the option + */ +#define TALER_EXCHANGE_post_withdraw_option_blinding_seed(s) \ + (const struct TALER_EXCHANGE_PostWithdrawOptionValue) \ + { \ + .option = TALER_EXCHANGE_POST_WITHDRAW_OPTION_BLINDING_SEED, \ + .details.blinding_seed = *(s) \ + } + + +/** + * Set the requested options for the operation. + * + * If any option fails, other options may or may not be applied. + * + * @param pwh the request to set the options for + * @param num_options length of the @a options array + * @param options an array of options + * @return #GNUNET_OK on success, + * #GNUNET_NO on failure, + * #GNUNET_SYSERR on internal error + */ +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_post_withdraw_set_options_ ( + struct TALER_EXCHANGE_PostWithdrawHandle *pwh, + unsigned int num_options, + const struct TALER_EXCHANGE_PostWithdrawOptionValue options[]); + + +/** + * Set the requested options for the operation. + * + * If any option fails, other options may or may not be applied. + * + * @param pwh the request to set the options for + * @param ... the list of the options, each created by a + * TALER_EXCHANGE_post_withdraw_option_NAME(VALUE) macro + * @return #GNUNET_OK on success, + * #GNUNET_NO on failure, + * #GNUNET_SYSERR on internal error + */ +#define TALER_EXCHANGE_post_withdraw_set_options(pwh,...) \ + TALER_EXCHANGE_post_withdraw_set_options_ ( \ + pwh, \ + TALER_EXCHANGE_COMMON_OPTIONS_ARRAY_MAX_SIZE, \ + ((const struct TALER_EXCHANGE_PostWithdrawOptionValue[]) \ + {__VA_ARGS__, \ + TALER_EXCHANGE_post_withdraw_option_end_ ()} \ + )) /** @@ -359,20 +469,24 @@ struct TALER_EXCHANGE_PostWithdrawBlindedHandle; /** - * Set up POST /withdraw operation for non-age-restricted coins - * (low-level variant with pre-blinded planchets). + * Set up POST /withdraw operation (low-level variant with pre-blinded + * planchets). * Note that you must explicitly start the operation after setup. * * This variant does not do the blinding/unblinding and only * fetches the blind signatures on the already blinded planchets. * + * For age-restricted coins requiring a proof, pass @a blinded_input as NULL + * and supply the age-restricted input via the + * #TALER_EXCHANGE_POST_WITHDRAW_BLINDED_OPTION_WITH_AGE_PROOF option. + * * @param curl_ctx The curl context to use * @param keys The /keys material from the exchange * @param exchange_url The base-URL of the exchange * @param reserve_priv private key of the reserve to withdraw from * @param blinding_seed seed used for blinding of CS denominations, might be NULL * @param num_input number of entries in the @a blinded_input array - * @param blinded_input array of planchet details to withdraw + * @param blinded_input array of planchet details to withdraw, or NULL if using WITH_AGE_PROOF option * @return handle to operation, NULL on error */ struct TALER_EXCHANGE_PostWithdrawBlindedHandle * @@ -383,40 +497,139 @@ TALER_EXCHANGE_post_withdraw_blinded_create ( const struct TALER_ReservePrivateKeyP *reserve_priv, const struct TALER_BlindingMasterSeedP *blinding_seed, size_t num_input, - const struct TALER_EXCHANGE_WithdrawBlindedCoinInput - blinded_input[static num_input]); + const struct TALER_EXCHANGE_WithdrawBlindedCoinInput *blinded_input); /** - * Set up POST /withdraw operation for age-restricted coins - * (low-level variant with pre-blinded planchets). - * Note that you must explicitly start the operation after setup. + * Possible options we can set for the POST /withdraw request + * (low-level, pre-blinded variant). + */ +enum TALER_EXCHANGE_PostWithdrawBlindedOption +{ + /** + * End of list of options. + */ + TALER_EXCHANGE_POST_WITHDRAW_BLINDED_OPTION_END = 0, + + /** + * Upgrade to an age-proof withdrawal for age-restricted coins, requiring + * an additional call to POST /reveal-withdraw. + * The @e details.with_age_proof.max_age field gives the maximum age to + * (provably) commit to. + * The @e details.with_age_proof.input field gives the KAPPA planchet + * candidates per coin. + */ + TALER_EXCHANGE_POST_WITHDRAW_BLINDED_OPTION_WITH_AGE_PROOF + +}; + + +/** + * Value for an option we can set for the POST /withdraw request + * (low-level, pre-blinded variant). + */ +struct TALER_EXCHANGE_PostWithdrawBlindedOptionValue +{ + /** + * Type of the option being set. + */ + enum TALER_EXCHANGE_PostWithdrawBlindedOption option; + + /** + * Specific option value. + */ + union + { + /** + * Value if @e option is + * #TALER_EXCHANGE_POST_WITHDRAW_BLINDED_OPTION_WITH_AGE_PROOF. + */ + struct + { + /** + * The maximum age to commit to. + */ + uint8_t max_age; + + /** + * Array of KAPPA planchet candidates per coin, length matches + * the @e num_input given to _create(). + */ + const struct TALER_EXCHANGE_WithdrawBlindedAgeRestrictedCoinInput *input; + + } with_age_proof; + + } details; + +}; + + +/** + * Terminate the list of options. * - * Withdrawing age-restricted coins with age-proof requires an additional - * step, /reveal-withdraw, for which the wallet will need to provide - * to all but one index all of the coin secrets. + * @return the terminating object + */ +#define TALER_EXCHANGE_post_withdraw_blinded_option_end_() \ + (const struct TALER_EXCHANGE_PostWithdrawBlindedOptionValue) \ + { \ + .option = TALER_EXCHANGE_POST_WITHDRAW_BLINDED_OPTION_END \ + } + +/** + * Upgrade to an age-proof withdrawal for age-restricted coins. * - * @param curl_ctx The curl context to use - * @param keys The /keys material from the exchange - * @param exchange_url The base-URL of the exchange - * @param reserve_priv private key of the reserve to withdraw from - * @param blinding_seed seed used for blinding of CS denominations, might be NULL - * @param max_age the maximum age to commit to - * @param num_coins number of entries in the @a blinded_input array - * @param blinded_input array of planchet candidates to withdraw - * @return handle to operation, NULL on error + * @param age the maximum age to commit to + * @param inp pointer to array of KAPPA planchet candidates per coin + * @return representation of the option */ -struct TALER_EXCHANGE_PostWithdrawBlindedHandle * -TALER_EXCHANGE_post_withdraw_blinded_create_with_age_proof ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_BlindingMasterSeedP *blinding_seed, - uint8_t max_age, - unsigned int num_coins, - const struct TALER_EXCHANGE_WithdrawBlindedAgeRestrictedCoinInput - blinded_input[static num_coins]); +#define TALER_EXCHANGE_post_withdraw_blinded_option_with_age_proof(age, inp) \ + (const struct TALER_EXCHANGE_PostWithdrawBlindedOptionValue) \ + { \ + .option = TALER_EXCHANGE_POST_WITHDRAW_BLINDED_OPTION_WITH_AGE_PROOF, \ + .details.with_age_proof.max_age = (age), \ + .details.with_age_proof.input = (inp) \ + } + + +/** + * Set the requested options for the operation. + * + * If any option fails, other options may or may not be applied. + * + * @param pwbh the request to set the options for + * @param num_options length of the @a options array + * @param options an array of options + * @return #GNUNET_OK on success, + * #GNUNET_NO on failure, + * #GNUNET_SYSERR on internal error + */ +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_post_withdraw_blinded_set_options_ ( + struct TALER_EXCHANGE_PostWithdrawBlindedHandle *pwbh, + unsigned int num_options, + const struct TALER_EXCHANGE_PostWithdrawBlindedOptionValue options[]); + + +/** + * Set the requested options for the operation. + * + * If any option fails, other options may or may not be applied. + * + * @param pwbh the request to set the options for + * @param ... the list of the options, each created by a + * TALER_EXCHANGE_post_withdraw_blinded_option_NAME(VALUE) macro + * @return #GNUNET_OK on success, + * #GNUNET_NO on failure, + * #GNUNET_SYSERR on internal error + */ +#define TALER_EXCHANGE_post_withdraw_blinded_set_options(pwbh,...) \ + TALER_EXCHANGE_post_withdraw_blinded_set_options_ ( \ + pwbh, \ + TALER_EXCHANGE_COMMON_OPTIONS_ARRAY_MAX_SIZE, \ + ((const struct TALER_EXCHANGE_PostWithdrawBlindedOptionValue[]) \ + {__VA_ARGS__, \ + TALER_EXCHANGE_post_withdraw_blinded_option_end_ ()} \ + )) /** @@ -524,200 +737,4 @@ TALER_EXCHANGE_post_withdraw_blinded_cancel ( struct TALER_EXCHANGE_PostWithdrawBlindedHandle *pwbh); -/* **************** deprecated legacy API ***************** */ - - -/** - * @deprecated Use #TALER_EXCHANGE_PostWithdrawResponse instead. - */ -struct TALER_EXCHANGE_WithdrawResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - unsigned int num_sigs; - const struct TALER_EXCHANGE_WithdrawCoinPrivateDetails *coin_details; - struct TALER_HashBlindedPlanchetsP planchets_h; - } ok; - struct TALER_EXCHANGE_WithdrawCreated created; - struct TALER_EXCHANGE_KycNeededRedirect unavailable_for_legal_reasons; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostWithdrawCallback instead. - */ -typedef void -(*TALER_EXCHANGE_WithdrawCallback)( - void *cls, - const struct TALER_EXCHANGE_WithdrawResponse *awr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostWithdrawHandle instead. - */ -struct TALER_EXCHANGE_WithdrawHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_withdraw_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_WithdrawHandle * -TALER_EXCHANGE_withdraw ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - size_t num_coins, - const struct TALER_EXCHANGE_DenomPublicKey denoms_pub[static num_coins], - const struct TALER_WithdrawMasterSeedP *seed, - uint8_t opaque_max_age, - TALER_EXCHANGE_WithdrawCallback callback, - void *callback_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_withdraw_create_with_age_proof() and - * the new API instead. - */ -struct TALER_EXCHANGE_WithdrawHandle * -TALER_EXCHANGE_withdraw_with_age_proof ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - size_t num_coins, - const struct TALER_EXCHANGE_DenomPublicKey denoms_pub[static num_coins], - const struct TALER_WithdrawMasterSeedP *seed, - uint8_t max_age, - TALER_EXCHANGE_WithdrawCallback callback, - void *callback_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_withdraw_cancel() instead. - */ -void -TALER_EXCHANGE_withdraw_cancel ( - struct TALER_EXCHANGE_WithdrawHandle *awh); - - -/** - * These functions are made available for testing purposes. - * They SHOULD NOT be used in real applications! - */ -#ifdef TALER_TESTING_EXPORTS_DANGEROUS -/** - * Same as @e TALER_EXCHANGE_withdraw, - * but takes an additional blinding_seed as parameter. - */ -struct TALER_EXCHANGE_WithdrawHandle * -TALER_EXCHANGE_withdraw_extra_blinding_seed ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - size_t num_coins, - const struct TALER_EXCHANGE_DenomPublicKey denoms_pub[static num_coins], - const struct TALER_WithdrawMasterSeedP *seed, - const struct TALER_BlindingMasterSeedP *blinding_seed, - uint8_t opaque_max_age, - TALER_EXCHANGE_WithdrawCallback callback, - void *callback_cls); - -/** - * Same as @e TALER_EXCHANGE_withdraw_age_proof, - * but takes an additional blinding_seed as parameter. - */ -struct TALER_EXCHANGE_WithdrawHandle * -TALER_EXCHANGE_withdraw_with_age_proof_extra_blinding_seed ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - size_t num_coins, - const struct TALER_EXCHANGE_DenomPublicKey denoms_pub[static num_coins], - const struct TALER_WithdrawMasterSeedP *seed, - const struct TALER_BlindingMasterSeedP *blinding_seed, - uint8_t max_age, - TALER_EXCHANGE_WithdrawCallback res_cb, - void *res_cb_cls); - -#endif - - -/** - * @deprecated Use #TALER_EXCHANGE_PostWithdrawBlindedResponse instead. - */ -struct TALER_EXCHANGE_WithdrawBlindedResponse -{ - struct TALER_EXCHANGE_HttpResponse hr; - union - { - struct - { - unsigned int num_sigs; - const struct TALER_BlindedDenominationSignature *blinded_denom_sigs; - struct TALER_HashBlindedPlanchetsP planchets_h; - } ok; - struct TALER_EXCHANGE_WithdrawCreated created; - struct TALER_EXCHANGE_KycNeededRedirect unavailable_for_legal_reasons; - } details; -}; - -/** - * @deprecated Use #TALER_EXCHANGE_PostWithdrawBlindedCallback instead. - */ -typedef void -(*TALER_EXCHANGE_WithdrawBlindedCallback) ( - void *cls, - const struct TALER_EXCHANGE_WithdrawBlindedResponse *awbr); - -/** - * @deprecated Use #TALER_EXCHANGE_PostWithdrawBlindedHandle instead. - */ -struct TALER_EXCHANGE_WithdrawBlindedHandle; - -/** - * @deprecated Use #TALER_EXCHANGE_post_withdraw_blinded_create() and - * the new API instead. - */ -struct TALER_EXCHANGE_WithdrawBlindedHandle * -TALER_EXCHANGE_withdraw_blinded ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_BlindingMasterSeedP *blinding_seed, - size_t num_input, - const struct TALER_EXCHANGE_WithdrawBlindedCoinInput - blinded_input[static num_input], - TALER_EXCHANGE_WithdrawBlindedCallback res_cb, - void *res_cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_withdraw_blinded_create_with_age_proof() and - * the new API instead. - */ -struct TALER_EXCHANGE_WithdrawBlindedHandle * -TALER_EXCHANGE_withdraw_blinded_with_age_proof ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_BlindingMasterSeedP *blinding_seed, - uint8_t max_age, - unsigned int num_coins, - const struct TALER_EXCHANGE_WithdrawBlindedAgeRestrictedCoinInput - blinded_input[static num_coins], - TALER_EXCHANGE_WithdrawBlindedCallback res_cb, - void *res_cb_cls); - -/** - * @deprecated Use #TALER_EXCHANGE_post_withdraw_blinded_cancel() instead. - */ -void -TALER_EXCHANGE_withdraw_blinded_cancel ( - struct TALER_EXCHANGE_WithdrawBlindedHandle *awbh); - - #endif /* _TALER_EXCHANGE__POST_WITHDRAW_H */ diff --git a/src/include/taler/taler_error_codes.h b/src/include/taler/taler_error_codes.h @@ -239,6 +239,14 @@ enum TALER_ErrorCode /** + * A parameter in the request was given that must not be present. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers. + * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400). + * (A value of 0 indicates that the error is generated client-side). + */ + TALER_EC_GENERIC_PARAMETER_EXTRA = 33, + + + /** * The service refused the request due to lack of proper authorization. Accessing this endpoint requires an access token from the account owner. * Returned with an HTTP status code of #MHD_HTTP_UNAUTHORIZED (401). * (A value of 0 indicates that the error is generated client-side). diff --git a/src/lib/exchange_api_get-coins-COIN_PUB-history.c b/src/lib/exchange_api_get-coins-COIN_PUB-history.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA + Copyright (C) 2014-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -16,14 +16,12 @@ */ /** * @file lib/exchange_api_get-coins-COIN_PUB-history.c - * @brief Implementation of the POST /coins/$COIN_PUB/history requests + * @brief Implementation of the GET /coins/$COIN_PUB/history request * @author Christian Grothoff - * - * NOTE: this is an incomplete draft, never finished! */ #include "taler/platform.h" #include <jansson.h> -#include <microhttpd.h> /* just for HTTP history codes */ +#include <microhttpd.h> /* just for HTTP status codes */ #include <gnunet/gnunet_util_lib.h> #include <gnunet/gnunet_json_lib.h> #include <gnunet/gnunet_curl_lib.h> @@ -35,12 +33,17 @@ /** - * @brief A /coins/$RID/history Handle + * @brief A GET /coins/$COIN_PUB/history Handle */ -struct TALER_EXCHANGE_CoinsHistoryHandle +struct TALER_EXCHANGE_GetCoinsHistoryHandle { /** + * Base URL of the exchange. + */ + char *base_url; + + /** * The url for this request. */ char *url; @@ -51,15 +54,24 @@ struct TALER_EXCHANGE_CoinsHistoryHandle struct GNUNET_CURL_Job *job; /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. + * Function to call with the result. */ - struct TALER_CURL_PostContext post_ctx; + TALER_EXCHANGE_GetCoinsHistoryCallback cb; /** - * Function to call with the result. + * Closure for @e cb. */ - TALER_EXCHANGE_CoinsHistoryCallback cb; + TALER_EXCHANGE_GET_COINS_HISTORY_RESULT_CLOSURE *cb_cls; + + /** + * CURL context to use. + */ + struct GNUNET_CURL_Context *ctx; + + /** + * Private key of the coin (for signing in _start). + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; /** * Public key of the coin we are querying. @@ -67,9 +79,16 @@ struct TALER_EXCHANGE_CoinsHistoryHandle struct TALER_CoinSpendPublicKeyP coin_pub; /** - * Closure for @a cb. + * Options set for this request. */ - void *cb_cls; + struct + { + /** + * Only return entries with history_offset > this value. + * Default: 0 (return all entries). + */ + uint64_t start_off; + } options; }; @@ -244,8 +263,6 @@ help_melt (struct CoinHistoryParseContext *pc, &rh->details.melt.melt_fee), GNUNET_JSON_spec_fixed_auto ("rc", &rh->details.melt.rc), - // FIXME: also return refresh_seed? - // FIXME: also return blinding_seed? GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_fixed_auto ("h_age_commitment", &rh->details.melt.h_age_commitment), @@ -351,14 +368,6 @@ help_refund (struct CoinHistoryParseContext *pc, GNUNET_break_op (0); return GNUNET_SYSERR; } - /* NOTE: theoretically, we could also check that the given - merchant_pub and h_contract_terms appear in the - history under deposits. However, there is really no benefit - for the exchange to lie here, so not checking is probably OK - (an auditor ought to check, though). Then again, we similarly - had no reason to check the merchant's signature (other than a - well-formendess check). */ - /* check that refund fee matches our expectations from /keys! */ if ( (GNUNET_YES != TALER_amount_cmp_currency (&rh->details.refund.refund_fee, @@ -509,7 +518,7 @@ help_recoup_refresh (struct CoinHistoryParseContext *pc, /** * Handle old coin recoup entry in the coin's history. * This is the coin that was credited in a recoup, - * the value being credited to the this coin. + * the value being credited to this coin. * * @param[in,out] pc overall context * @param[out] rh history entry to initialize @@ -583,7 +592,6 @@ help_purse_deposit (struct CoinHistoryParseContext *pc, GNUNET_JSON_spec_fixed_auto ("h_age_commitment", &rh->details.purse_deposit.phac), NULL), - // FIXME: return deposit_fee? GNUNET_JSON_spec_fixed_auto ("purse_pub", &rh->details.purse_deposit.purse_pub), GNUNET_JSON_spec_bool ("refunded", @@ -808,7 +816,7 @@ TALER_EXCHANGE_parse_coin_history ( GNUNET_assert (GNUNET_OK == TALER_amount_set_zero (total_in->currency, total_out)); - for (size_t off = 0; off<len; off++) + for (size_t off = 0; off < len; off++) { struct TALER_EXCHANGE_CoinHistoryEntry *rh = &rhistory[off]; json_t *transaction = json_array_get (history, @@ -899,18 +907,17 @@ TALER_EXCHANGE_parse_coin_history ( /** - * We received an #MHD_HTTP_OK history code. Handle the JSON - * response. + * We received an #MHD_HTTP_OK response. Handle the JSON response. * - * @param rsh handle of the request + * @param gcsh handle of the request * @param j JSON response * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -handle_coins_history_ok (struct TALER_EXCHANGE_CoinsHistoryHandle *rsh, +handle_coins_history_ok (struct TALER_EXCHANGE_GetCoinsHistoryHandle *gcsh, const json_t *j) { - struct TALER_EXCHANGE_CoinHistory rs = { + struct TALER_EXCHANGE_GetCoinsHistoryResponse rs = { .hr.reply = j, .hr.http_status = MHD_HTTP_OK }; @@ -933,11 +940,11 @@ handle_coins_history_ok (struct TALER_EXCHANGE_CoinsHistoryHandle *rsh, GNUNET_break_op (0); return GNUNET_SYSERR; } - if (NULL != rsh->cb) + if (NULL != gcsh->cb) { - rsh->cb (rsh->cb_cls, - &rs); - rsh->cb = NULL; + gcsh->cb (gcsh->cb_cls, + &rs); + gcsh->cb = NULL; } GNUNET_JSON_parse_free (spec); return GNUNET_OK; @@ -946,9 +953,9 @@ handle_coins_history_ok (struct TALER_EXCHANGE_CoinsHistoryHandle *rsh, /** * Function called when we're done processing the - * HTTP /coins/$RID/history request. + * HTTP GET /coins/$COIN_PUB/history request. * - * @param cls the `struct TALER_EXCHANGE_CoinsHistoryHandle` + * @param cls the `struct TALER_EXCHANGE_GetCoinsHistoryHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -957,14 +964,14 @@ handle_coins_history_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_CoinsHistoryHandle *rsh = cls; + struct TALER_EXCHANGE_GetCoinsHistoryHandle *gcsh = cls; const json_t *j = response; - struct TALER_EXCHANGE_CoinHistory rs = { + struct TALER_EXCHANGE_GetCoinsHistoryResponse rs = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - rsh->job = NULL; + gcsh->job = NULL; switch (response_code) { case 0: @@ -972,7 +979,7 @@ handle_coins_history_finished (void *cls, break; case MHD_HTTP_OK: if (GNUNET_OK != - handle_coins_history_ok (rsh, + handle_coins_history_ok (gcsh, j)) { rs.hr.http_status = 0; @@ -994,8 +1001,6 @@ handle_coins_history_finished (void *cls, rs.hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_NOT_FOUND: - /* Nothing really to verify, this should never - happen, we should pass the JSON reply to the application */ rs.hr.ec = TALER_JSON_get_error_code (j); rs.hr.hint = TALER_JSON_get_error_hint (j); break; @@ -1016,83 +1021,113 @@ handle_coins_history_finished (void *cls, (int) rs.hr.ec); break; } - if (NULL != rsh->cb) + if (NULL != gcsh->cb) { - rsh->cb (rsh->cb_cls, - &rs); - rsh->cb = NULL; + gcsh->cb (gcsh->cb_cls, + &rs); + gcsh->cb = NULL; } - TALER_EXCHANGE_coins_history_cancel (rsh); + TALER_EXCHANGE_get_coins_history_cancel (gcsh); } -struct TALER_EXCHANGE_CoinsHistoryHandle * -TALER_EXCHANGE_coins_history ( +struct TALER_EXCHANGE_GetCoinsHistoryHandle * +TALER_EXCHANGE_get_coins_history_create ( struct GNUNET_CURL_Context *ctx, const char *url, - const struct TALER_CoinSpendPrivateKeyP *coin_priv, - uint64_t start_off, - TALER_EXCHANGE_CoinsHistoryCallback cb, - void *cb_cls) + const struct TALER_CoinSpendPrivateKeyP *coin_priv) +{ + struct TALER_EXCHANGE_GetCoinsHistoryHandle *gcsh; + + gcsh = GNUNET_new (struct TALER_EXCHANGE_GetCoinsHistoryHandle); + gcsh->ctx = ctx; + gcsh->base_url = GNUNET_strdup (url); + gcsh->coin_priv = *coin_priv; + GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, + &gcsh->coin_pub.eddsa_pub); + gcsh->options.start_off = 0; + return gcsh; +} + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_get_coins_history_set_options_ ( + struct TALER_EXCHANGE_GetCoinsHistoryHandle *gcsh, + unsigned int num_options, + const struct TALER_EXCHANGE_GetCoinsHistoryOptionValue *options) +{ + for (unsigned int i = 0; i < num_options; i++) + { + const struct TALER_EXCHANGE_GetCoinsHistoryOptionValue *opt = &options[i]; + + switch (opt->option) + { + case TALER_EXCHANGE_GET_COINS_HISTORY_OPTION_END: + return GNUNET_OK; + case TALER_EXCHANGE_GET_COINS_HISTORY_OPTION_START_OFF: + gcsh->options.start_off = opt->details.start_off; + break; + } + } + return GNUNET_OK; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_get_coins_history_start ( + struct TALER_EXCHANGE_GetCoinsHistoryHandle *gcsh, + TALER_EXCHANGE_GetCoinsHistoryCallback cb, + TALER_EXCHANGE_GET_COINS_HISTORY_RESULT_CLOSURE *cb_cls) { - struct TALER_EXCHANGE_CoinsHistoryHandle *rsh; - CURL *eh; char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 64]; struct curl_slist *job_headers; + CURL *eh; - rsh = GNUNET_new (struct TALER_EXCHANGE_CoinsHistoryHandle); - rsh->cb = cb; - rsh->cb_cls = cb_cls; - GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, - &rsh->coin_pub.eddsa_pub); + if (NULL != gcsh->job) + { + GNUNET_break (0); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + gcsh->cb = cb; + gcsh->cb_cls = cb_cls; { char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; char *end; end = GNUNET_STRINGS_data_to_string ( - &rsh->coin_pub, - sizeof (rsh->coin_pub), + &gcsh->coin_pub, + sizeof (gcsh->coin_pub), pub_str, sizeof (pub_str)); *end = '\0'; - if (0 != start_off) + if (0 != gcsh->options.start_off) GNUNET_snprintf (arg_str, sizeof (arg_str), "coins/%s/history?start=%llu", pub_str, - (unsigned long long) start_off); + (unsigned long long) gcsh->options.start_off); else GNUNET_snprintf (arg_str, sizeof (arg_str), "coins/%s/history", pub_str); } - rsh->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == rsh->url) - { - GNUNET_free (rsh); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (rsh->url); + gcsh->url = TALER_url_join (gcsh->base_url, + arg_str, + NULL); + if (NULL == gcsh->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + eh = TALER_EXCHANGE_curl_easy_get_ (gcsh->url); if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (rsh->url); - GNUNET_free (rsh); - return NULL; - } - + return TALER_EC_GENERIC_CONFIGURATION_INVALID; { struct TALER_CoinSpendSignatureP coin_sig; char *sig_hdr; char *hdr; - TALER_wallet_coin_history_sign (start_off, - coin_priv, + TALER_wallet_coin_history_sign (gcsh->options.start_off, + &gcsh->coin_priv, &coin_sig); - sig_hdr = GNUNET_STRINGS_data_to_string_alloc ( &coin_sig, sizeof (coin_sig)); @@ -1108,44 +1143,37 @@ TALER_EXCHANGE_coins_history ( { GNUNET_break (0); curl_easy_cleanup (eh); - return NULL; + GNUNET_free (gcsh->url); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } } - - rsh->job = GNUNET_CURL_job_add2 (ctx, - eh, - job_headers, - &handle_coins_history_finished, - rsh); + gcsh->job = GNUNET_CURL_job_add2 (gcsh->ctx, + eh, + job_headers, + &handle_coins_history_finished, + gcsh); curl_slist_free_all (job_headers); - return rsh; + if (NULL == gcsh->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_coins_history_cancel ( - struct TALER_EXCHANGE_CoinsHistoryHandle *rsh) +TALER_EXCHANGE_get_coins_history_cancel ( + struct TALER_EXCHANGE_GetCoinsHistoryHandle *gcsh) { - if (NULL != rsh->job) + if (NULL != gcsh->job) { - GNUNET_CURL_job_cancel (rsh->job); - rsh->job = NULL; + GNUNET_CURL_job_cancel (gcsh->job); + gcsh->job = NULL; } - TALER_curl_easy_post_finished (&rsh->post_ctx); - GNUNET_free (rsh->url); - GNUNET_free (rsh); + GNUNET_free (gcsh->url); + GNUNET_free (gcsh->base_url); + GNUNET_free (gcsh); } -/** - * Verify that @a coin_sig does NOT appear in the @a history of a coin's - * transactions and thus whatever transaction is authorized by @a coin_sig is - * a conflict with @a proof. - * - * @param history coin history to check - * @param coin_sig signature that must not be in @a history - * @return #GNUNET_OK if @a coin_sig is not in @a history - */ enum GNUNET_GenericReturnValue TALER_EXCHANGE_check_coin_signature_conflict ( const json_t *history, @@ -1232,4 +1260,4 @@ TALER_EXCHANGE_check_coin_conflict_ ( #endif -/* end of exchange_api_coins_history.c */ +/* end of exchange_api_get-coins-COIN_PUB-history.c */ diff --git a/src/lib/exchange_api_get-contracts-CONTRACT_PUB.c b/src/lib/exchange_api_get-contracts-CONTRACT_PUB.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -16,7 +16,7 @@ */ /** * @file lib/exchange_api_get-contracts-CONTRACT_PUB.c - * @brief Implementation of the /contracts/ GET request + * @brief Implementation of the GET /contracts/$CONTRACT_PUB request * @author Christian Grothoff */ #include "taler/platform.h" @@ -33,12 +33,17 @@ /** - * @brief A Contract Get Handle + * @brief A GET /contracts/$CONTRACT_PUB Handle */ -struct TALER_EXCHANGE_ContractsGetHandle +struct TALER_EXCHANGE_GetContractsHandle { /** + * Base URL of the exchange. + */ + char *base_url; + + /** * The url for this request. */ char *url; @@ -51,12 +56,17 @@ struct TALER_EXCHANGE_ContractsGetHandle /** * Function to call with the result. */ - TALER_EXCHANGE_ContractGetCallback cb; + TALER_EXCHANGE_GetContractsCallback cb; + + /** + * Closure for @e cb. + */ + TALER_EXCHANGE_GET_CONTRACTS_RESULT_CLOSURE *cb_cls; /** - * Closure for @a cb. + * CURL context to use. */ - void *cb_cls; + struct GNUNET_CURL_Context *ctx; /** * Private key needed to decrypt the contract. @@ -73,9 +83,9 @@ struct TALER_EXCHANGE_ContractsGetHandle /** * Function called when we're done processing the - * HTTP /track/transaction request. + * HTTP GET /contracts/$CONTRACT_PUB request. * - * @param cls the `struct TALER_EXCHANGE_ContractsGetHandle` + * @param cls the `struct TALER_EXCHANGE_GetContractsHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -84,14 +94,14 @@ handle_contract_get_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_ContractsGetHandle *cgh = cls; + struct TALER_EXCHANGE_GetContractsHandle *gch = cls; const json_t *j = response; - struct TALER_EXCHANGE_ContractGetResponse dr = { + struct TALER_EXCHANGE_GetContractsResponse dr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - cgh->job = NULL; + gch->job = NULL; switch (response_code) { case 0: @@ -127,7 +137,7 @@ handle_contract_get_finished (void *cls, TALER_wallet_econtract_upload_verify ( econtract, econtract_size, - &cgh->cpub, + &gch->cpub, &dr.details.ok.purse_pub, &econtract_sig)) { @@ -139,10 +149,11 @@ handle_contract_get_finished (void *cls, } dr.details.ok.econtract = econtract; dr.details.ok.econtract_size = econtract_size; - cgh->cb (cgh->cb_cls, + gch->cb (gch->cb_cls, &dr); + gch->cb = NULL; GNUNET_JSON_parse_free (spec); - TALER_EXCHANGE_contract_get_cancel (cgh); + TALER_EXCHANGE_get_contracts_cancel (gch); return; } case MHD_HTTP_BAD_REQUEST: @@ -181,35 +192,53 @@ handle_contract_get_finished (void *cls, GNUNET_break_op (0); break; } - cgh->cb (cgh->cb_cls, - &dr); - TALER_EXCHANGE_contract_get_cancel (cgh); + if (NULL != gch->cb) + gch->cb (gch->cb_cls, + &dr); + TALER_EXCHANGE_get_contracts_cancel (gch); } -struct TALER_EXCHANGE_ContractsGetHandle * -TALER_EXCHANGE_contract_get ( +struct TALER_EXCHANGE_GetContractsHandle * +TALER_EXCHANGE_get_contracts_create ( struct GNUNET_CURL_Context *ctx, const char *url, - const struct TALER_ContractDiffiePrivateP *contract_priv, - TALER_EXCHANGE_ContractGetCallback cb, - void *cb_cls) + const struct TALER_ContractDiffiePrivateP *contract_priv) { - struct TALER_EXCHANGE_ContractsGetHandle *cgh; - CURL *eh; - char arg_str[sizeof (cgh->cpub) * 2 + 48]; + struct TALER_EXCHANGE_GetContractsHandle *gch; - cgh = GNUNET_new (struct TALER_EXCHANGE_ContractsGetHandle); - cgh->cb = cb; - cgh->cb_cls = cb_cls; + gch = GNUNET_new (struct TALER_EXCHANGE_GetContractsHandle); + gch->ctx = ctx; + gch->base_url = GNUNET_strdup (url); + gch->contract_priv = *contract_priv; GNUNET_CRYPTO_ecdhe_key_get_public (&contract_priv->ecdhe_priv, - &cgh->cpub.ecdhe_pub); + &gch->cpub.ecdhe_pub); + return gch; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_get_contracts_start ( + struct TALER_EXCHANGE_GetContractsHandle *gch, + TALER_EXCHANGE_GetContractsCallback cb, + TALER_EXCHANGE_GET_CONTRACTS_RESULT_CLOSURE *cb_cls) +{ + char arg_str[sizeof (gch->cpub) * 2 + 48]; + CURL *eh; + + if (NULL != gch->job) + { + GNUNET_break (0); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + gch->cb = cb; + gch->cb_cls = cb_cls; { - char cpub_str[sizeof (cgh->cpub) * 2]; + char cpub_str[sizeof (gch->cpub) * 2]; char *end; - end = GNUNET_STRINGS_data_to_string (&cgh->cpub, - sizeof (cgh->cpub), + end = GNUNET_STRINGS_data_to_string (&gch->cpub, + sizeof (gch->cpub), cpub_str, sizeof (cpub_str)); *end = '\0'; @@ -218,45 +247,40 @@ TALER_EXCHANGE_contract_get ( "contracts/%s", cpub_str); } - - cgh->url = TALER_url_join (url, + gch->url = TALER_url_join (gch->base_url, arg_str, NULL); - if (NULL == cgh->url) - { - GNUNET_free (cgh); - return NULL; - } - cgh->contract_priv = *contract_priv; - - eh = TALER_EXCHANGE_curl_easy_get_ (cgh->url); + if (NULL == gch->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + eh = TALER_EXCHANGE_curl_easy_get_ (gch->url); if (NULL == eh) { - GNUNET_break (0); - GNUNET_free (cgh->url); - GNUNET_free (cgh); - return NULL; + GNUNET_free (gch->url); + return TALER_EC_GENERIC_CONFIGURATION_INVALID; } - cgh->job = GNUNET_CURL_job_add (ctx, + gch->job = GNUNET_CURL_job_add (gch->ctx, eh, &handle_contract_get_finished, - cgh); - return cgh; + gch); + if (NULL == gch->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_contract_get_cancel ( - struct TALER_EXCHANGE_ContractsGetHandle *cgh) +TALER_EXCHANGE_get_contracts_cancel ( + struct TALER_EXCHANGE_GetContractsHandle *gch) { - if (NULL != cgh->job) + if (NULL != gch->job) { - GNUNET_CURL_job_cancel (cgh->job); - cgh->job = NULL; + GNUNET_CURL_job_cancel (gch->job); + gch->job = NULL; } - GNUNET_free (cgh->url); - GNUNET_free (cgh); + GNUNET_free (gch->url); + GNUNET_free (gch->base_url); + GNUNET_free (gch); } -/* end of exchange_api_contracts_get.c */ +/* end of exchange_api_get-contracts-CONTRACT_PUB.c */ diff --git a/src/lib/exchange_api_get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.c b/src/lib/exchange_api_get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA + Copyright (C) 2014-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -16,7 +16,7 @@ */ /** * @file lib/exchange_api_get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.c - * @brief Implementation of the /deposits/ GET request + * @brief Implementation of the GET /deposits/... request * @author Christian Grothoff */ #include "taler/platform.h" @@ -33,15 +33,15 @@ /** - * @brief A Deposit Get Handle + * @brief A GET /deposits/... Handle */ -struct TALER_EXCHANGE_DepositGetHandle +struct TALER_EXCHANGE_GetDepositsHandle { /** - * The keys of the this request handle will use + * Base URL of the exchange. */ - struct TALER_EXCHANGE_Keys *keys; + char *base_url; /** * The url for this request. @@ -49,10 +49,9 @@ struct TALER_EXCHANGE_DepositGetHandle char *url; /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. + * The keys of this request handle will use. */ - struct TALER_CURL_PostContext ctx; + struct TALER_EXCHANGE_Keys *keys; /** * Handle for the request. @@ -62,12 +61,22 @@ struct TALER_EXCHANGE_DepositGetHandle /** * Function to call with the result. */ - TALER_EXCHANGE_DepositGetCallback cb; + TALER_EXCHANGE_GetDepositsCallback cb; + + /** + * Closure for @e cb. + */ + TALER_EXCHANGE_GET_DEPOSITS_RESULT_CLOSURE *cb_cls; /** - * Closure for @a cb. + * CURL context to use. */ - void *cb_cls; + struct GNUNET_CURL_Context *ctx; + + /** + * Private key of the merchant. + */ + struct TALER_MerchantPrivateKeyP merchant_priv; /** * Hash over the wiring information of the merchant. @@ -80,19 +89,30 @@ struct TALER_EXCHANGE_DepositGetHandle struct TALER_PrivateContractHashP h_contract_terms; /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. + * The coin's public key. */ struct TALER_CoinSpendPublicKeyP coin_pub; + /** + * Options set for this request. + */ + struct + { + /** + * How long to wait for the wire transfer, enabling long polling. + * Default: zero (no long polling). + */ + struct GNUNET_TIME_Relative timeout; + } options; + }; /** * Function called when we're done processing the - * HTTP /track/transaction request. + * HTTP GET /deposits/... request. * - * @param cls the `struct TALER_EXCHANGE_DepositGetHandle` + * @param cls the `struct TALER_EXCHANGE_GetDepositsHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -101,14 +121,14 @@ handle_deposit_wtid_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_DepositGetHandle *dwh = cls; + struct TALER_EXCHANGE_GetDepositsHandle *gdh = cls; const json_t *j = response; - struct TALER_EXCHANGE_GetDepositResponse dr = { + struct TALER_EXCHANGE_GetDepositsResponse dr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - dwh->job = NULL; + gdh->job = NULL; switch (response_code) { case 0: @@ -134,10 +154,8 @@ handle_deposit_wtid_finished (void *cls, &dr.details.ok.exchange_pub), GNUNET_JSON_spec_end () }; - const struct TALER_EXCHANGE_Keys *key_state; - key_state = dwh->keys; - GNUNET_assert (NULL != key_state); + GNUNET_assert (NULL != gdh->keys); if (GNUNET_OK != GNUNET_JSON_parse (j, spec, @@ -149,7 +167,7 @@ handle_deposit_wtid_finished (void *cls, break; } if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, + TALER_EXCHANGE_test_signing_key (gdh->keys, &dr.details.ok.exchange_pub)) { GNUNET_break_op (0); @@ -159,10 +177,10 @@ handle_deposit_wtid_finished (void *cls, } if (GNUNET_OK != TALER_exchange_online_confirm_wire_verify ( - &dwh->h_wire, - &dwh->h_contract_terms, + &gdh->h_wire, + &gdh->h_contract_terms, &dr.details.ok.wtid, - &dwh->coin_pub, + &gdh->coin_pub, dr.details.ok.execution_time, &dr.details.ok.coin_contribution, &dr.details.ok.exchange_pub, @@ -173,9 +191,10 @@ handle_deposit_wtid_finished (void *cls, dr.hr.ec = TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_SIGNATURE_BY_EXCHANGE; break; } - dwh->cb (dwh->cb_cls, + gdh->cb (gdh->cb_cls, &dr); - TALER_EXCHANGE_deposits_get_cancel (dwh); + gdh->cb = NULL; + TALER_EXCHANGE_get_deposits_cancel (gdh); return; } case MHD_HTTP_ACCEPTED: @@ -214,9 +233,10 @@ handle_deposit_wtid_finished (void *cls, } if (no_legi) dr.details.accepted.requirement_row = 0; - dwh->cb (dwh->cb_cls, + gdh->cb (gdh->cb_cls, &dr); - TALER_EXCHANGE_deposits_get_cancel (dwh); + gdh->cb = NULL; + TALER_EXCHANGE_get_deposits_cancel (gdh); return; } case MHD_HTTP_BAD_REQUEST: @@ -255,44 +275,94 @@ handle_deposit_wtid_finished (void *cls, GNUNET_break_op (0); break; } - dwh->cb (dwh->cb_cls, - &dr); - TALER_EXCHANGE_deposits_get_cancel (dwh); + if (NULL != gdh->cb) + gdh->cb (gdh->cb_cls, + &dr); + TALER_EXCHANGE_get_deposits_cancel (gdh); } -struct TALER_EXCHANGE_DepositGetHandle * -TALER_EXCHANGE_deposits_get ( +struct TALER_EXCHANGE_GetDepositsHandle * +TALER_EXCHANGE_get_deposits_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, const struct TALER_MerchantPrivateKeyP *merchant_priv, const struct TALER_MerchantWireHashP *h_wire, const struct TALER_PrivateContractHashP *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct GNUNET_TIME_Relative timeout, - TALER_EXCHANGE_DepositGetCallback cb, - void *cb_cls) + const struct TALER_CoinSpendPublicKeyP *coin_pub) +{ + struct TALER_EXCHANGE_GetDepositsHandle *gdh; + struct TALER_MerchantPublicKeyP merchant; + + gdh = GNUNET_new (struct TALER_EXCHANGE_GetDepositsHandle); + gdh->ctx = ctx; + gdh->base_url = GNUNET_strdup (url); + gdh->keys = TALER_EXCHANGE_keys_incref (keys); + gdh->merchant_priv = *merchant_priv; + gdh->h_wire = *h_wire; + gdh->h_contract_terms = *h_contract_terms; + GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv, + &merchant.eddsa_pub); + gdh->coin_pub = *coin_pub; + return gdh; +} + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_get_deposits_set_options_ ( + struct TALER_EXCHANGE_GetDepositsHandle *gdh, + unsigned int num_options, + const struct TALER_EXCHANGE_GetDepositsOptionValue *options) +{ + for (unsigned int i = 0; i < num_options; i++) + { + const struct TALER_EXCHANGE_GetDepositsOptionValue *opt = &options[i]; + + switch (opt->option) + { + case TALER_EXCHANGE_GET_DEPOSITS_OPTION_END: + return GNUNET_OK; + case TALER_EXCHANGE_GET_DEPOSITS_OPTION_TIMEOUT: + gdh->options.timeout = opt->details.timeout; + break; + } + } + return GNUNET_OK; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_get_deposits_start ( + struct TALER_EXCHANGE_GetDepositsHandle *gdh, + TALER_EXCHANGE_GetDepositsCallback cb, + TALER_EXCHANGE_GET_DEPOSITS_RESULT_CLOSURE *cb_cls) { struct TALER_MerchantPublicKeyP merchant; struct TALER_MerchantSignatureP merchant_sig; - struct TALER_EXCHANGE_DepositGetHandle *dwh; - CURL *eh; char arg_str[(sizeof (struct TALER_CoinSpendPublicKeyP) + sizeof (struct TALER_MerchantWireHashP) + sizeof (struct TALER_MerchantPublicKeyP) + sizeof (struct TALER_PrivateContractHashP) + sizeof (struct TALER_MerchantSignatureP)) * 2 + 48]; - unsigned int tms - = (unsigned int) timeout.rel_value_us - / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us; + unsigned int tms; + CURL *eh; - GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv, + if (NULL != gdh->job) + { + GNUNET_break (0); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + gdh->cb = cb; + gdh->cb_cls = cb_cls; + tms = (unsigned int) gdh->options.timeout.rel_value_us + / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us; + GNUNET_CRYPTO_eddsa_key_get_public (&gdh->merchant_priv.eddsa_priv, &merchant.eddsa_pub); - TALER_merchant_deposit_sign (h_contract_terms, - h_wire, - coin_pub, - merchant_priv, + TALER_merchant_deposit_sign (&gdh->h_contract_terms, + &gdh->h_wire, + &gdh->coin_pub, + &gdh->merchant_priv, &merchant_sig); { char cpub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; @@ -303,8 +373,8 @@ TALER_EXCHANGE_deposits_get ( char timeout_str[24]; char *end; - end = GNUNET_STRINGS_data_to_string (h_wire, - sizeof (*h_wire), + end = GNUNET_STRINGS_data_to_string (&gdh->h_wire, + sizeof (gdh->h_wire), whash_str, sizeof (whash_str)); *end = '\0'; @@ -313,13 +383,13 @@ TALER_EXCHANGE_deposits_get ( mpub_str, sizeof (mpub_str)); *end = '\0'; - end = GNUNET_STRINGS_data_to_string (h_contract_terms, - sizeof (*h_contract_terms), + end = GNUNET_STRINGS_data_to_string (&gdh->h_contract_terms, + sizeof (gdh->h_contract_terms), chash_str, sizeof (chash_str)); *end = '\0'; - end = GNUNET_STRINGS_data_to_string (coin_pub, - sizeof (*coin_pub), + end = GNUNET_STRINGS_data_to_string (&gdh->coin_pub, + sizeof (gdh->coin_pub), cpub_str, sizeof (cpub_str)); *end = '\0'; @@ -328,7 +398,7 @@ TALER_EXCHANGE_deposits_get ( msig_str, sizeof (msig_str)); *end = '\0'; - if (GNUNET_TIME_relative_is_zero (timeout)) + if (0 == tms) { timeout_str[0] = '\0'; } @@ -340,7 +410,6 @@ TALER_EXCHANGE_deposits_get ( "%u", tms); } - GNUNET_snprintf (arg_str, sizeof (arg_str), "deposits/%s/%s/%s/%s?merchant_sig=%s%s%s", @@ -354,29 +423,14 @@ TALER_EXCHANGE_deposits_get ( : "&timeout_ms=", timeout_str); } - - dwh = GNUNET_new (struct TALER_EXCHANGE_DepositGetHandle); - dwh->cb = cb; - dwh->cb_cls = cb_cls; - dwh->url = TALER_url_join (url, + gdh->url = TALER_url_join (gdh->base_url, arg_str, NULL); - if (NULL == dwh->url) - { - GNUNET_free (dwh); - return NULL; - } - dwh->h_wire = *h_wire; - dwh->h_contract_terms = *h_contract_terms; - dwh->coin_pub = *coin_pub; - eh = TALER_EXCHANGE_curl_easy_get_ (dwh->url); + if (NULL == gdh->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + eh = TALER_EXCHANGE_curl_easy_get_ (gdh->url); if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (dwh->url); - GNUNET_free (dwh); - return NULL; - } + return TALER_EC_GENERIC_CONFIGURATION_INVALID; if (0 != tms) { GNUNET_break (CURLE_OK == @@ -384,28 +438,30 @@ TALER_EXCHANGE_deposits_get ( CURLOPT_TIMEOUT_MS, (long) (tms + 100L))); } - dwh->job = GNUNET_CURL_job_add (ctx, + gdh->job = GNUNET_CURL_job_add (gdh->ctx, eh, &handle_deposit_wtid_finished, - dwh); - dwh->keys = TALER_EXCHANGE_keys_incref (keys); - return dwh; + gdh); + if (NULL == gdh->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_deposits_get_cancel (struct TALER_EXCHANGE_DepositGetHandle *dwh) +TALER_EXCHANGE_get_deposits_cancel ( + struct TALER_EXCHANGE_GetDepositsHandle *gdh) { - if (NULL != dwh->job) + if (NULL != gdh->job) { - GNUNET_CURL_job_cancel (dwh->job); - dwh->job = NULL; + GNUNET_CURL_job_cancel (gdh->job); + gdh->job = NULL; } - GNUNET_free (dwh->url); - TALER_curl_easy_post_finished (&dwh->ctx); - TALER_EXCHANGE_keys_decref (dwh->keys); - GNUNET_free (dwh); + GNUNET_free (gdh->url); + GNUNET_free (gdh->base_url); + TALER_EXCHANGE_keys_decref (gdh->keys); + GNUNET_free (gdh); } -/* end of exchange_api_deposits_get.c */ +/* end of exchange_api_get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.c */ diff --git a/src/lib/exchange_api_get-purses-PURSE_PUB-merge.c b/src/lib/exchange_api_get-purses-PURSE_PUB-merge.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022-2023 Taler Systems SA + Copyright (C) 2022-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -33,15 +33,15 @@ /** - * @brief A Contract Get Handle + * @brief A GET /purses/$PURSE_PUB/merge Handle */ -struct TALER_EXCHANGE_PurseGetHandle +struct TALER_EXCHANGE_GetPursesHandle { /** - * The keys of the exchange this request handle will use + * Base URL of the exchange. */ - struct TALER_EXCHANGE_Keys *keys; + char *base_url; /** * The url for this request. @@ -49,6 +49,11 @@ struct TALER_EXCHANGE_PurseGetHandle char *url; /** + * The keys of the exchange this request handle will use. + */ + struct TALER_EXCHANGE_Keys *keys; + + /** * Handle for the request. */ struct GNUNET_CURL_Job *job; @@ -56,12 +61,38 @@ struct TALER_EXCHANGE_PurseGetHandle /** * Function to call with the result. */ - TALER_EXCHANGE_PurseGetCallback cb; + TALER_EXCHANGE_GetPursesCallback cb; /** - * Closure for @a cb. + * Closure for @e cb. */ - void *cb_cls; + TALER_EXCHANGE_GET_PURSES_RESULT_CLOSURE *cb_cls; + + /** + * CURL context to use. + */ + struct GNUNET_CURL_Context *ctx; + + /** + * Public key of the purse being queried. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Options for the request. + */ + struct + { + /** + * How long to wait for a change to happen. + */ + struct GNUNET_TIME_Relative timeout; + + /** + * True to wait for a merge event, false to wait for a deposit event. + */ + bool wait_for_merge; + } options; }; @@ -70,7 +101,7 @@ struct TALER_EXCHANGE_PurseGetHandle * Function called when we're done processing the * HTTP /purses/$PID GET request. * - * @param cls the `struct TALER_EXCHANGE_PurseGetHandle` + * @param cls the `struct TALER_EXCHANGE_GetPursesHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -79,14 +110,14 @@ handle_purse_get_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_PurseGetHandle *pgh = cls; + struct TALER_EXCHANGE_GetPursesHandle *gph = cls; const json_t *j = response; - struct TALER_EXCHANGE_PurseGetResponse dr = { + struct TALER_EXCHANGE_GetPursesResponse dr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - pgh->job = NULL; + gph->job = NULL; switch (response_code) { case 0: @@ -128,9 +159,8 @@ handle_purse_get_finished (void *cls, dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (pgh->keys, + TALER_EXCHANGE_test_signing_key (gph->keys, &exchange_pub)) { GNUNET_break_op (0); @@ -151,9 +181,9 @@ handle_purse_get_finished (void *cls, dr.hr.ec = TALER_EC_EXCHANGE_PURSES_GET_INVALID_SIGNATURE_BY_EXCHANGE; break; } - pgh->cb (pgh->cb_cls, + gph->cb (gph->cb_cls, &dr); - TALER_EXCHANGE_purse_get_cancel (pgh); + TALER_EXCHANGE_get_purses_cancel (gph); return; } case MHD_HTTP_BAD_REQUEST: @@ -197,40 +227,83 @@ handle_purse_get_finished (void *cls, GNUNET_break_op (0); break; } - pgh->cb (pgh->cb_cls, + gph->cb (gph->cb_cls, &dr); - TALER_EXCHANGE_purse_get_cancel (pgh); + TALER_EXCHANGE_get_purses_cancel (gph); } -struct TALER_EXCHANGE_PurseGetHandle * -TALER_EXCHANGE_purse_get ( +struct TALER_EXCHANGE_GetPursesHandle * +TALER_EXCHANGE_get_purses_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, - const struct TALER_PurseContractPublicKeyP *purse_pub, - struct GNUNET_TIME_Relative timeout, - bool wait_for_merge, - TALER_EXCHANGE_PurseGetCallback cb, - void *cb_cls) + const struct TALER_PurseContractPublicKeyP *purse_pub) +{ + struct TALER_EXCHANGE_GetPursesHandle *gph; + + gph = GNUNET_new (struct TALER_EXCHANGE_GetPursesHandle); + gph->ctx = ctx; + gph->base_url = GNUNET_strdup (url); + gph->keys = TALER_EXCHANGE_keys_incref (keys); + gph->purse_pub = *purse_pub; + return gph; +} + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_get_purses_set_options_ ( + struct TALER_EXCHANGE_GetPursesHandle *gph, + unsigned int num_options, + const struct TALER_EXCHANGE_GetPursesOptionValue *options) { - struct TALER_EXCHANGE_PurseGetHandle *pgh; + for (unsigned int i = 0; i < num_options; i++) + { + switch (options[i].option) + { + case TALER_EXCHANGE_GET_PURSES_OPTION_END: + return GNUNET_OK; + case TALER_EXCHANGE_GET_PURSES_OPTION_TIMEOUT: + gph->options.timeout = options[i].details.timeout; + break; + case TALER_EXCHANGE_GET_PURSES_OPTION_WAIT_FOR_MERGE: + gph->options.wait_for_merge = options[i].details.wait_for_merge; + break; + default: + GNUNET_break (0); + return GNUNET_SYSERR; + } + } + return GNUNET_OK; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_get_purses_start ( + struct TALER_EXCHANGE_GetPursesHandle *gph, + TALER_EXCHANGE_GetPursesCallback cb, + TALER_EXCHANGE_GET_PURSES_RESULT_CLOSURE *cb_cls) +{ + char arg_str[sizeof (gph->purse_pub) * 2 + 64]; CURL *eh; - char arg_str[sizeof (*purse_pub) * 2 + 64]; unsigned int tms - = (unsigned int) timeout.rel_value_us + = (unsigned int) gph->options.timeout.rel_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us; - pgh = GNUNET_new (struct TALER_EXCHANGE_PurseGetHandle); - pgh->cb = cb; - pgh->cb_cls = cb_cls; + if (NULL != gph->job) { - char cpub_str[sizeof (*purse_pub) * 2]; + GNUNET_break (0); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + gph->cb = cb; + gph->cb_cls = cb_cls; + { + char cpub_str[sizeof (gph->purse_pub) * 2]; char *end; char timeout_str[32]; - end = GNUNET_STRINGS_data_to_string (purse_pub, - sizeof (*purse_pub), + end = GNUNET_STRINGS_data_to_string (&gph->purse_pub, + sizeof (gph->purse_pub), cpub_str, sizeof (cpub_str)); *end = '\0'; @@ -242,30 +315,22 @@ TALER_EXCHANGE_purse_get ( sizeof (arg_str), "purses/%s/%s", cpub_str, - wait_for_merge + gph->options.wait_for_merge ? "merge" : "deposit"); - pgh->url = TALER_url_join (url, + gph->url = TALER_url_join (gph->base_url, arg_str, "timeout_ms", (0 == tms) - ? NULL - : timeout_str, + ? NULL + : timeout_str, NULL); } - if (NULL == pgh->url) - { - GNUNET_free (pgh); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (pgh->url); + if (NULL == gph->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + eh = TALER_EXCHANGE_curl_easy_get_ (gph->url); if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (pgh->url); - GNUNET_free (pgh); - return NULL; - } + return TALER_EC_GENERIC_CONFIGURATION_INVALID; if (0 != tms) { GNUNET_break (CURLE_OK == @@ -273,28 +338,30 @@ TALER_EXCHANGE_purse_get ( CURLOPT_TIMEOUT_MS, (long) (tms + 100L))); } - pgh->job = GNUNET_CURL_job_add (ctx, + gph->job = GNUNET_CURL_job_add (gph->ctx, eh, &handle_purse_get_finished, - pgh); - pgh->keys = TALER_EXCHANGE_keys_incref (keys); - return pgh; + gph); + if (NULL == gph->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_purse_get_cancel ( - struct TALER_EXCHANGE_PurseGetHandle *pgh) +TALER_EXCHANGE_get_purses_cancel ( + struct TALER_EXCHANGE_GetPursesHandle *gph) { - if (NULL != pgh->job) + if (NULL != gph->job) { - GNUNET_CURL_job_cancel (pgh->job); - pgh->job = NULL; + GNUNET_CURL_job_cancel (gph->job); + gph->job = NULL; } - GNUNET_free (pgh->url); - TALER_EXCHANGE_keys_decref (pgh->keys); - GNUNET_free (pgh); + GNUNET_free (gph->url); + GNUNET_free (gph->base_url); + TALER_EXCHANGE_keys_decref (gph->keys); + GNUNET_free (gph); } -/* end of exchange_api_purses_get.c */ +/* end of exchange_api_get-purses-PURSE_PUB-merge.c */ diff --git a/src/lib/exchange_api_get-reserves-RESERVE_PUB-history.c b/src/lib/exchange_api_get-reserves-RESERVE_PUB-history.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA + Copyright (C) 2014-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -16,7 +16,7 @@ */ /** * @file lib/exchange_api_get-reserves-RESERVE_PUB-history.c - * @brief Implementation of the POST /reserves/$RESERVE_PUB/history requests + * @brief Implementation of the GET /reserves/$RESERVE_PUB/history requests * @author Christian Grothoff */ #include "taler/platform.h" @@ -33,15 +33,15 @@ /** - * @brief A /reserves/$RID/history Handle + * @brief A GET /reserves/$RESERVE_PUB/history Handle */ -struct TALER_EXCHANGE_ReservesHistoryHandle +struct TALER_EXCHANGE_GetReservesHistoryHandle { /** - * The keys of the exchange this request handle will use + * Base URL of the exchange. */ - struct TALER_EXCHANGE_Keys *keys; + char *base_url; /** * The url for this request. @@ -49,36 +49,56 @@ struct TALER_EXCHANGE_ReservesHistoryHandle char *url; /** + * The keys of the exchange this request handle will use. + */ + struct TALER_EXCHANGE_Keys *keys; + + /** * Handle for the request. */ struct GNUNET_CURL_Job *job; /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. + * Function to call with the result. + */ + TALER_EXCHANGE_GetReservesHistoryCallback cb; + + /** + * Closure for @e cb. */ - struct TALER_CURL_PostContext post_ctx; + TALER_EXCHANGE_GET_RESERVES_HISTORY_RESULT_CLOSURE *cb_cls; /** - * Function to call with the result. + * CURL context to use. */ - TALER_EXCHANGE_ReservesHistoryCallback cb; + struct GNUNET_CURL_Context *ctx; /** - * Public key of the reserve we are querying. + * Private key of the reserve we are querying. */ - struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReservePrivateKeyP reserve_priv; /** - * Closure for @a cb. + * Public key of the reserve we are querying. */ - void *cb_cls; + struct TALER_ReservePublicKeyP reserve_pub; /** * Where to store the etag (if any). */ uint64_t etag; + /** + * Options for the request. + */ + struct + { + /** + * Only return entries with offset strictly greater than this value. + */ + uint64_t start_off; + } options; + }; @@ -793,8 +813,7 @@ free_reserve_history ( /** - * Parse history given in JSON format and return it in binary - * format. + * Parse history given in JSON format and return it in binary format. * * @param keys exchange keys * @param history JSON array with the history @@ -920,7 +939,7 @@ parse_reserve_history ( * @param buffer one line of HTTP header data * @param size size of an item * @param nitems number of items passed - * @param userdata our `struct TALER_EXCHANGE_ReservesHistoryHandle *` + * @param userdata our `struct TALER_EXCHANGE_GetReservesHistoryHandle *` * @return `size * nitems` */ static size_t @@ -929,7 +948,7 @@ handle_header (char *buffer, size_t nitems, void *userdata) { - struct TALER_EXCHANGE_ReservesHistoryHandle *rhh = userdata; + struct TALER_EXCHANGE_GetReservesHistoryHandle *grhh = userdata; size_t total = size * nitems; char *ndup; const char *hdr_type; @@ -972,7 +991,7 @@ handle_header (char *buffer, GNUNET_free (ndup); return 0; } - rhh->etag = (uint64_t) tval; + grhh->etag = (uint64_t) tval; } GNUNET_free (ndup); return total; @@ -980,23 +999,23 @@ handle_header (char *buffer, /** - * We received an #MHD_HTTP_OK history code. Handle the JSON - * response. + * We received an #MHD_HTTP_OK status code. Handle the JSON response. * - * @param rsh handle of the request + * @param grhh handle of the request * @param j JSON response * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -handle_reserves_history_ok (struct TALER_EXCHANGE_ReservesHistoryHandle *rsh, - const json_t *j) +handle_reserves_history_ok ( + struct TALER_EXCHANGE_GetReservesHistoryHandle *grhh, + const json_t *j) { const json_t *history; unsigned int len; - struct TALER_EXCHANGE_ReserveHistory rs = { + struct TALER_EXCHANGE_GetReservesHistoryResponse rs = { .hr.reply = j, .hr.http_status = MHD_HTTP_OK, - .details.ok.etag = rsh->etag + .details.ok.etag = grhh->etag }; struct GNUNET_JSON_Specification spec[] = { TALER_JSON_spec_amount_any ("balance", @@ -1022,9 +1041,9 @@ handle_reserves_history_ok (struct TALER_EXCHANGE_ReservesHistoryHandle *rsh, rhistory = GNUNET_new_array (len, struct TALER_EXCHANGE_ReserveHistoryEntry); if (GNUNET_OK != - parse_reserve_history (rsh->keys, + parse_reserve_history (grhh->keys, history, - &rsh->reserve_pub, + &grhh->reserve_pub, rs.details.ok.balance.currency, &rs.details.ok.total_in, &rs.details.ok.total_out, @@ -1037,13 +1056,13 @@ handle_reserves_history_ok (struct TALER_EXCHANGE_ReservesHistoryHandle *rsh, GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } - if (NULL != rsh->cb) + if (NULL != grhh->cb) { rs.details.ok.history = rhistory; rs.details.ok.history_len = len; - rsh->cb (rsh->cb_cls, - &rs); - rsh->cb = NULL; + grhh->cb (grhh->cb_cls, + &rs); + grhh->cb = NULL; } free_reserve_history (len, rhistory); @@ -1054,9 +1073,9 @@ handle_reserves_history_ok (struct TALER_EXCHANGE_ReservesHistoryHandle *rsh, /** * Function called when we're done processing the - * HTTP /reserves/$RID/history request. + * HTTP GET /reserves/$RESERVE_PUB/history request. * - * @param cls the `struct TALER_EXCHANGE_ReservesHistoryHandle` + * @param cls the `struct TALER_EXCHANGE_GetReservesHistoryHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -1065,14 +1084,14 @@ handle_reserves_history_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_ReservesHistoryHandle *rsh = cls; + struct TALER_EXCHANGE_GetReservesHistoryHandle *grhh = cls; const json_t *j = response; - struct TALER_EXCHANGE_ReserveHistory rs = { + struct TALER_EXCHANGE_GetReservesHistoryResponse rs = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - rsh->job = NULL; + grhh->job = NULL; switch (response_code) { case 0: @@ -1080,7 +1099,7 @@ handle_reserves_history_finished (void *cls, break; case MHD_HTTP_OK: if (GNUNET_OK != - handle_reserves_history_ok (rsh, + handle_reserves_history_ok (grhh, j)) { rs.hr.http_status = 0; @@ -1124,73 +1143,111 @@ handle_reserves_history_finished (void *cls, (int) rs.hr.ec); break; } - if (NULL != rsh->cb) + if (NULL != grhh->cb) { - rsh->cb (rsh->cb_cls, - &rs); - rsh->cb = NULL; + grhh->cb (grhh->cb_cls, + &rs); + grhh->cb = NULL; } - TALER_EXCHANGE_reserves_history_cancel (rsh); + TALER_EXCHANGE_get_reserves_history_cancel (grhh); } -struct TALER_EXCHANGE_ReservesHistoryHandle * -TALER_EXCHANGE_reserves_history ( +struct TALER_EXCHANGE_GetReservesHistoryHandle * +TALER_EXCHANGE_get_reserves_history_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, - const struct TALER_ReservePrivateKeyP *reserve_priv, - uint64_t start_off, - TALER_EXCHANGE_ReservesHistoryCallback cb, - void *cb_cls) + const struct TALER_ReservePrivateKeyP *reserve_priv) { - struct TALER_EXCHANGE_ReservesHistoryHandle *rsh; - CURL *eh; - char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 64]; - struct curl_slist *job_headers; + struct TALER_EXCHANGE_GetReservesHistoryHandle *grhh; - rsh = GNUNET_new (struct TALER_EXCHANGE_ReservesHistoryHandle); - rsh->cb = cb; - rsh->cb_cls = cb_cls; + grhh = GNUNET_new (struct TALER_EXCHANGE_GetReservesHistoryHandle); + grhh->ctx = ctx; + grhh->base_url = GNUNET_strdup (url); + grhh->keys = TALER_EXCHANGE_keys_incref (keys); + grhh->reserve_priv = *reserve_priv; GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, - &rsh->reserve_pub.eddsa_pub); + &grhh->reserve_pub.eddsa_pub); + return grhh; +} + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_get_reserves_history_set_options_ ( + struct TALER_EXCHANGE_GetReservesHistoryHandle *grhh, + unsigned int num_options, + const struct TALER_EXCHANGE_GetReservesHistoryOptionValue *options) +{ + for (unsigned int i = 0; i < num_options; i++) + { + switch (options[i].option) + { + case TALER_EXCHANGE_GET_RESERVES_HISTORY_OPTION_END: + return GNUNET_OK; + case TALER_EXCHANGE_GET_RESERVES_HISTORY_OPTION_START_OFF: + grhh->options.start_off = options[i].details.start_off; + break; + default: + GNUNET_break (0); + return GNUNET_SYSERR; + } + } + return GNUNET_OK; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_get_reserves_history_start ( + struct TALER_EXCHANGE_GetReservesHistoryHandle *grhh, + TALER_EXCHANGE_GetReservesHistoryCallback cb, + TALER_EXCHANGE_GET_RESERVES_HISTORY_RESULT_CLOSURE *cb_cls) +{ + char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; + struct curl_slist *job_headers; + CURL *eh; + + if (NULL != grhh->job) + { + GNUNET_break (0); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + grhh->cb = cb; + grhh->cb_cls = cb_cls; { char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2]; char *end; + char start_off_str[32]; end = GNUNET_STRINGS_data_to_string ( - &rsh->reserve_pub, - sizeof (rsh->reserve_pub), + &grhh->reserve_pub, + sizeof (grhh->reserve_pub), pub_str, sizeof (pub_str)); *end = '\0'; - if (0 != start_off) - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "reserves/%s/history?start=%llu", - pub_str, - (unsigned long long) start_off); - else - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "reserves/%s/history", - pub_str); + GNUNET_snprintf (arg_str, + sizeof (arg_str), + "reserves/%s/history", + pub_str); + GNUNET_snprintf (start_off_str, + sizeof (start_off_str), + "%llu", + (unsigned long long) grhh->options.start_off); + grhh->url = TALER_url_join (grhh->base_url, + arg_str, + "start", + (0 != grhh->options.start_off) + ? start_off_str + : NULL, + NULL); } - rsh->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == rsh->url) - { - GNUNET_free (rsh); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (rsh->url); + if (NULL == grhh->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + eh = TALER_EXCHANGE_curl_easy_get_ (grhh->url); if (NULL == eh) { - GNUNET_break (0); - GNUNET_free (rsh->url); - GNUNET_free (rsh); - return NULL; + GNUNET_free (grhh->url); + return TALER_EC_GENERIC_CONFIGURATION_INVALID; } GNUNET_assert (CURLE_OK == curl_easy_setopt (eh, @@ -1199,16 +1256,15 @@ TALER_EXCHANGE_reserves_history ( GNUNET_assert (CURLE_OK == curl_easy_setopt (eh, CURLOPT_HEADERDATA, - rsh)); + grhh)); { struct TALER_ReserveSignatureP reserve_sig; char *sig_hdr; char *hdr; - TALER_wallet_reserve_history_sign (start_off, - reserve_priv, + TALER_wallet_reserve_history_sign (grhh->options.start_off, + &grhh->reserve_priv, &reserve_sig); - sig_hdr = GNUNET_STRINGS_data_to_string_alloc ( &reserve_sig, sizeof (reserve_sig)); @@ -1224,35 +1280,35 @@ TALER_EXCHANGE_reserves_history ( { GNUNET_break (0); curl_easy_cleanup (eh); - return NULL; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } } - - rsh->keys = TALER_EXCHANGE_keys_incref (keys); - rsh->job = GNUNET_CURL_job_add2 (ctx, - eh, - job_headers, - &handle_reserves_history_finished, - rsh); + grhh->job = GNUNET_CURL_job_add2 (grhh->ctx, + eh, + job_headers, + &handle_reserves_history_finished, + grhh); curl_slist_free_all (job_headers); - return rsh; + if (NULL == grhh->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_reserves_history_cancel ( - struct TALER_EXCHANGE_ReservesHistoryHandle *rsh) +TALER_EXCHANGE_get_reserves_history_cancel ( + struct TALER_EXCHANGE_GetReservesHistoryHandle *grhh) { - if (NULL != rsh->job) + if (NULL != grhh->job) { - GNUNET_CURL_job_cancel (rsh->job); - rsh->job = NULL; + GNUNET_CURL_job_cancel (grhh->job); + grhh->job = NULL; } - TALER_curl_easy_post_finished (&rsh->post_ctx); - GNUNET_free (rsh->url); - TALER_EXCHANGE_keys_decref (rsh->keys); - GNUNET_free (rsh); + GNUNET_free (grhh->url); + GNUNET_free (grhh->base_url); + TALER_EXCHANGE_keys_decref (grhh->keys); + GNUNET_free (grhh); } -/* end of exchange_api_reserves_history.c */ +/* end of exchange_api_get-reserves-RESERVE_PUB-history.c */ diff --git a/src/lib/exchange_api_get-reserves-RESERVE_PUB.c b/src/lib/exchange_api_get-reserves-RESERVE_PUB.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA + Copyright (C) 2014-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -33,17 +33,27 @@ /** - * @brief A /reserves/ GET Handle + * @brief A GET /reserves/$RESERVE_PUB Handle */ -struct TALER_EXCHANGE_ReservesGetHandle +struct TALER_EXCHANGE_GetReservesHandle { /** + * Base URL of the exchange. + */ + char *base_url; + + /** * The url for this request. */ char *url; /** + * CURL context to use. + */ + struct GNUNET_CURL_Context *ctx; + + /** * Handle for the request. */ struct GNUNET_CURL_Job *job; @@ -51,7 +61,12 @@ struct TALER_EXCHANGE_ReservesGetHandle /** * Function to call with the result. */ - TALER_EXCHANGE_ReservesGetCallback cb; + TALER_EXCHANGE_GetReservesCallback cb; + + /** + * Closure for @e cb. + */ + TALER_EXCHANGE_GET_RESERVES_RESULT_CLOSURE *cb_cls; /** * Public key of the reserve we are querying. @@ -59,26 +74,31 @@ struct TALER_EXCHANGE_ReservesGetHandle struct TALER_ReservePublicKeyP reserve_pub; /** - * Closure for @a cb. + * Options for the request. */ - void *cb_cls; + struct + { + /** + * How long to wait for an answer (enables long polling). + */ + struct GNUNET_TIME_Relative timeout; + } options; }; /** - * We received an #MHD_HTTP_OK status code. Handle the JSON - * response. + * We received an #MHD_HTTP_OK status code. Handle the JSON response. * - * @param rgh handle of the request + * @param grh handle of the request * @param j JSON response * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -handle_reserves_get_ok (struct TALER_EXCHANGE_ReservesGetHandle *rgh, +handle_reserves_get_ok (struct TALER_EXCHANGE_GetReservesHandle *grh, const json_t *j) { - struct TALER_EXCHANGE_ReserveSummary rs = { + struct TALER_EXCHANGE_GetReservesResponse rs = { .hr.reply = j, .hr.http_status = MHD_HTTP_OK }; @@ -102,18 +122,18 @@ handle_reserves_get_ok (struct TALER_EXCHANGE_ReservesGetHandle *rgh, GNUNET_break_op (0); return GNUNET_SYSERR; } - rgh->cb (rgh->cb_cls, + grh->cb (grh->cb_cls, &rs); - rgh->cb = NULL; + grh->cb = NULL; return GNUNET_OK; } /** * Function called when we're done processing the - * HTTP /reserves/ GET request. + * HTTP GET /reserves/$RESERVE_PUB request. * - * @param cls the `struct TALER_EXCHANGE_ReservesGetHandle` + * @param cls the `struct TALER_EXCHANGE_GetReservesHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -122,14 +142,14 @@ handle_reserves_get_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_ReservesGetHandle *rgh = cls; + struct TALER_EXCHANGE_GetReservesHandle *grh = cls; const json_t *j = response; - struct TALER_EXCHANGE_ReserveSummary rs = { + struct TALER_EXCHANGE_GetReservesResponse rs = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - rgh->job = NULL; + grh->job = NULL; switch (response_code) { case 0: @@ -137,7 +157,7 @@ handle_reserves_get_finished (void *cls, break; case MHD_HTTP_OK: if (GNUNET_OK != - handle_reserves_get_ok (rgh, + handle_reserves_get_ok (grh, j)) { rs.hr.http_status = 0; @@ -171,82 +191,110 @@ handle_reserves_get_finished (void *cls, "Unexpected response code %u/%d for GET %s\n", (unsigned int) response_code, (int) rs.hr.ec, - rgh->url); + grh->url); break; } - if (NULL != rgh->cb) + if (NULL != grh->cb) { - rgh->cb (rgh->cb_cls, + grh->cb (grh->cb_cls, &rs); - rgh->cb = NULL; + grh->cb = NULL; } - TALER_EXCHANGE_reserves_get_cancel (rgh); + TALER_EXCHANGE_get_reserves_cancel (grh); } -struct TALER_EXCHANGE_ReservesGetHandle * -TALER_EXCHANGE_reserves_get ( +struct TALER_EXCHANGE_GetReservesHandle * +TALER_EXCHANGE_get_reserves_create ( struct GNUNET_CURL_Context *ctx, const char *url, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct GNUNET_TIME_Relative timeout, - TALER_EXCHANGE_ReservesGetCallback cb, - void *cb_cls) + const struct TALER_ReservePublicKeyP *reserve_pub) +{ + struct TALER_EXCHANGE_GetReservesHandle *grh; + + grh = GNUNET_new (struct TALER_EXCHANGE_GetReservesHandle); + grh->ctx = ctx; + grh->base_url = GNUNET_strdup (url); + grh->reserve_pub = *reserve_pub; + return grh; +} + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_get_reserves_set_options_ ( + struct TALER_EXCHANGE_GetReservesHandle *grh, + unsigned int num_options, + const struct TALER_EXCHANGE_GetReservesOptionValue *options) +{ + for (unsigned int i = 0; i < num_options; i++) + { + switch (options[i].option) + { + case TALER_EXCHANGE_GET_RESERVES_OPTION_END: + return GNUNET_OK; + case TALER_EXCHANGE_GET_RESERVES_OPTION_TIMEOUT: + grh->options.timeout = options[i].details.timeout; + break; + default: + GNUNET_break (0); + return GNUNET_SYSERR; + } + } + return GNUNET_OK; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_get_reserves_start ( + struct TALER_EXCHANGE_GetReservesHandle *grh, + TALER_EXCHANGE_GetReservesCallback cb, + TALER_EXCHANGE_GET_RESERVES_RESULT_CLOSURE *cb_cls) { - struct TALER_EXCHANGE_ReservesGetHandle *rgh; + char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 16]; CURL *eh; - char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 16 + 32]; unsigned int tms - = (unsigned int) timeout.rel_value_us + = (unsigned int) grh->options.timeout.rel_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us; + if (NULL != grh->job) + { + GNUNET_break (0); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + grh->cb = cb; + grh->cb_cls = cb_cls; { char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2]; char *end; char timeout_str[32]; end = GNUNET_STRINGS_data_to_string ( - reserve_pub, - sizeof (*reserve_pub), + &grh->reserve_pub, + sizeof (grh->reserve_pub), pub_str, sizeof (pub_str)); *end = '\0'; + GNUNET_snprintf (arg_str, + sizeof (arg_str), + "reserves/%s", + pub_str); GNUNET_snprintf (timeout_str, sizeof (timeout_str), "%u", tms); - if (0 == tms) - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "reserves/%s", - pub_str); - else - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "reserves/%s?timeout_ms=%s", - pub_str, - timeout_str); - } - rgh = GNUNET_new (struct TALER_EXCHANGE_ReservesGetHandle); - rgh->cb = cb; - rgh->cb_cls = cb_cls; - rgh->reserve_pub = *reserve_pub; - rgh->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == rgh->url) - { - GNUNET_free (rgh); - return NULL; + grh->url = TALER_url_join (grh->base_url, + arg_str, + "timeout_ms", + (0 == tms) + ? NULL + : timeout_str, + NULL); } - eh = TALER_EXCHANGE_curl_easy_get_ (rgh->url); + if (NULL == grh->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + eh = TALER_EXCHANGE_curl_easy_get_ (grh->url); if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (rgh->url); - GNUNET_free (rgh); - return NULL; - } + return TALER_EC_GENERIC_CONFIGURATION_INVALID; if (0 != tms) { GNUNET_break (CURLE_OK == @@ -254,26 +302,29 @@ TALER_EXCHANGE_reserves_get ( CURLOPT_TIMEOUT_MS, (long) (tms + 100L))); } - rgh->job = GNUNET_CURL_job_add (ctx, + grh->job = GNUNET_CURL_job_add (grh->ctx, eh, &handle_reserves_get_finished, - rgh); - return rgh; + grh); + if (NULL == grh->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_reserves_get_cancel ( - struct TALER_EXCHANGE_ReservesGetHandle *rgh) +TALER_EXCHANGE_get_reserves_cancel ( + struct TALER_EXCHANGE_GetReservesHandle *grh) { - if (NULL != rgh->job) + if (NULL != grh->job) { - GNUNET_CURL_job_cancel (rgh->job); - rgh->job = NULL; + GNUNET_CURL_job_cancel (grh->job); + grh->job = NULL; } - GNUNET_free (rgh->url); - GNUNET_free (rgh); + GNUNET_free (grh->url); + GNUNET_free (grh->base_url); + GNUNET_free (grh); } -/* end of exchange_api_reserves_get.c */ +/* end of exchange_api_get-reserves-RESERVE_PUB.c */ diff --git a/src/lib/exchange_api_get-reserves-attest-RESERVE_PUB.c b/src/lib/exchange_api_get-reserves-attest-RESERVE_PUB.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA + Copyright (C) 2014-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -16,7 +16,7 @@ */ /** * @file lib/exchange_api_get-reserves-attest-RESERVE_PUB.c - * @brief Implementation of the GET_ATTESTABLE /reserves/$RESERVE_PUB requests + * @brief Implementation of the GET /reserves/$RESERVE_PUB/attest request * @author Christian Grothoff */ #include "taler/platform.h" @@ -33,17 +33,27 @@ /** - * @brief A /reserves/ GET_ATTESTABLE Handle + * @brief A GET /reserves/$RESERVE_PUB/attest Handle */ -struct TALER_EXCHANGE_ReservesGetAttestHandle +struct TALER_EXCHANGE_GetReservesAttestHandle { /** + * Base URL of the exchange. + */ + char *base_url; + + /** * The url for this request. */ char *url; /** + * CURL context to use. + */ + struct GNUNET_CURL_Context *ctx; + + /** * Handle for the request. */ struct GNUNET_CURL_Job *job; @@ -51,35 +61,34 @@ struct TALER_EXCHANGE_ReservesGetAttestHandle /** * Function to call with the result. */ - TALER_EXCHANGE_ReservesGetAttestCallback cb; + TALER_EXCHANGE_GetReservesAttestCallback cb; /** - * Public key of the reserve we are querying. + * Closure for @e cb. */ - struct TALER_ReservePublicKeyP reserve_pub; + TALER_EXCHANGE_GET_RESERVES_ATTEST_RESULT_CLOSURE *cb_cls; /** - * Closure for @a cb. + * Public key of the reserve we are querying. */ - void *cb_cls; + struct TALER_ReservePublicKeyP reserve_pub; }; /** - * We received an #MHD_HTTP_OK status code. Handle the JSON - * response. + * We received an #MHD_HTTP_OK status code. Handle the JSON response. * - * @param rgah handle of the request + * @param grah handle of the request * @param j JSON response * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue handle_reserves_get_attestable_ok ( - struct TALER_EXCHANGE_ReservesGetAttestHandle *rgah, + struct TALER_EXCHANGE_GetReservesAttestHandle *grah, const json_t *j) { - struct TALER_EXCHANGE_ReserveGetAttestResult rs = { + struct TALER_EXCHANGE_GetReservesAttestResponse rs = { .hr.reply = j, .hr.http_status = MHD_HTTP_OK }; @@ -100,10 +109,10 @@ handle_reserves_get_attestable_ok ( return GNUNET_SYSERR; } { - unsigned int dlen = json_array_size (details); + size_t dlen = json_array_size (details); const char *attributes[GNUNET_NZL (dlen)]; - for (unsigned int i = 0; i<dlen; i++) + for (unsigned int i = 0; i < dlen; i++) { json_t *detail = json_array_get (details, i); @@ -116,9 +125,9 @@ handle_reserves_get_attestable_ok ( } rs.details.ok.attributes_length = dlen; rs.details.ok.attributes = attributes; - rgah->cb (rgah->cb_cls, + grah->cb (grah->cb_cls, &rs); - rgah->cb = NULL; + grah->cb = NULL; } return GNUNET_OK; } @@ -126,9 +135,9 @@ handle_reserves_get_attestable_ok ( /** * Function called when we're done processing the - * HTTP GET /reserves-attest/$RID request. + * HTTP GET /reserves/$RESERVE_PUB/attest request. * - * @param cls the `struct TALER_EXCHANGE_ReservesGetAttestableHandle` + * @param cls the `struct TALER_EXCHANGE_GetReservesAttestHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -137,14 +146,14 @@ handle_reserves_get_attestable_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_ReservesGetAttestHandle *rgah = cls; + struct TALER_EXCHANGE_GetReservesAttestHandle *grah = cls; const json_t *j = response; - struct TALER_EXCHANGE_ReserveGetAttestResult rs = { + struct TALER_EXCHANGE_GetReservesAttestResponse rs = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - rgah->job = NULL; + grah->job = NULL; switch (response_code) { case 0: @@ -152,7 +161,7 @@ handle_reserves_get_attestable_finished (void *cls, break; case MHD_HTTP_OK: if (GNUNET_OK != - handle_reserves_get_attestable_ok (rgah, + handle_reserves_get_attestable_ok (grah, j)) { rs.hr.http_status = 0; @@ -194,35 +203,55 @@ handle_reserves_get_attestable_finished (void *cls, (int) rs.hr.ec); break; } - if (NULL != rgah->cb) + if (NULL != grah->cb) { - rgah->cb (rgah->cb_cls, + grah->cb (grah->cb_cls, &rs); - rgah->cb = NULL; + grah->cb = NULL; } - TALER_EXCHANGE_reserves_get_attestable_cancel (rgah); + TALER_EXCHANGE_get_reserves_attest_cancel (grah); } -struct TALER_EXCHANGE_ReservesGetAttestHandle * -TALER_EXCHANGE_reserves_get_attestable ( +struct TALER_EXCHANGE_GetReservesAttestHandle * +TALER_EXCHANGE_get_reserves_attest_create ( struct GNUNET_CURL_Context *ctx, const char *url, - const struct TALER_ReservePublicKeyP *reserve_pub, - TALER_EXCHANGE_ReservesGetAttestCallback cb, - void *cb_cls) + const struct TALER_ReservePublicKeyP *reserve_pub) +{ + struct TALER_EXCHANGE_GetReservesAttestHandle *grah; + + grah = GNUNET_new (struct TALER_EXCHANGE_GetReservesAttestHandle); + grah->ctx = ctx; + grah->base_url = GNUNET_strdup (url); + grah->reserve_pub = *reserve_pub; + return grah; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_get_reserves_attest_start ( + struct TALER_EXCHANGE_GetReservesAttestHandle *grah, + TALER_EXCHANGE_GetReservesAttestCallback cb, + TALER_EXCHANGE_GET_RESERVES_ATTEST_RESULT_CLOSURE *cb_cls) { - struct TALER_EXCHANGE_ReservesGetAttestHandle *rgah; - CURL *eh; char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; + CURL *eh; + if (NULL != grah->job) + { + GNUNET_break (0); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + grah->cb = cb; + grah->cb_cls = cb_cls; { char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2]; char *end; end = GNUNET_STRINGS_data_to_string ( - reserve_pub, - sizeof (*reserve_pub), + &grah->reserve_pub, + sizeof (grah->reserve_pub), pub_str, sizeof (pub_str)); *end = '\0'; @@ -231,46 +260,37 @@ TALER_EXCHANGE_reserves_get_attestable ( "reserves-attest/%s", pub_str); } - rgah = GNUNET_new (struct TALER_EXCHANGE_ReservesGetAttestHandle); - rgah->cb = cb; - rgah->cb_cls = cb_cls; - rgah->reserve_pub = *reserve_pub; - rgah->url = TALER_url_join (url, + grah->url = TALER_url_join (grah->base_url, arg_str, NULL); - if (NULL == rgah->url) - { - GNUNET_free (rgah); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (rgah->url); + if (NULL == grah->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + eh = TALER_EXCHANGE_curl_easy_get_ (grah->url); if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (rgah->url); - GNUNET_free (rgah); - return NULL; - } - rgah->job = GNUNET_CURL_job_add (ctx, + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + grah->job = GNUNET_CURL_job_add (grah->ctx, eh, &handle_reserves_get_attestable_finished, - rgah); - return rgah; + grah); + if (NULL == grah->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_reserves_get_attestable_cancel ( - struct TALER_EXCHANGE_ReservesGetAttestHandle *rgah) +TALER_EXCHANGE_get_reserves_attest_cancel ( + struct TALER_EXCHANGE_GetReservesAttestHandle *grah) { - if (NULL != rgah->job) + if (NULL != grah->job) { - GNUNET_CURL_job_cancel (rgah->job); - rgah->job = NULL; + GNUNET_CURL_job_cancel (grah->job); + grah->job = NULL; } - GNUNET_free (rgah->url); - GNUNET_free (rgah); + GNUNET_free (grah->url); + GNUNET_free (grah->base_url); + GNUNET_free (grah); } -/* end of exchange_api_reserves_get_attestable.c */ +/* end of exchange_api_get-reserves-attest-RESERVE_PUB.c */ diff --git a/src/lib/exchange_api_get-transfers-WTID.c b/src/lib/exchange_api_get-transfers-WTID.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA + Copyright (C) 2014-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -16,7 +16,7 @@ */ /** * @file lib/exchange_api_get-transfers-WTID.c - * @brief Implementation of the GET /transfers/ request + * @brief Implementation of the GET /transfers/$WTID request * @author Christian Grothoff */ #include "taler/platform.h" @@ -32,15 +32,15 @@ /** - * @brief A /transfers/ GET Handle + * @brief A GET /transfers/$WTID Handle */ -struct TALER_EXCHANGE_TransfersGetHandle +struct TALER_EXCHANGE_GetTransfersHandle { /** - * The keys of the exchange this request handle will use + * Base URL of the exchange. */ - struct TALER_EXCHANGE_Keys *keys; + char *base_url; /** * The url for this request. @@ -55,18 +55,33 @@ struct TALER_EXCHANGE_TransfersGetHandle /** * Function to call with the result. */ - TALER_EXCHANGE_TransfersGetCallback cb; + TALER_EXCHANGE_GetTransfersCallback cb; + + /** + * Closure for @e cb. + */ + TALER_EXCHANGE_GET_TRANSFERS_RESULT_CLOSURE *cb_cls; + + /** + * CURL context to use. + */ + struct GNUNET_CURL_Context *ctx; + + /** + * The keys of the exchange this request handle will use. + */ + struct TALER_EXCHANGE_Keys *keys; /** - * Closure for @a cb. + * Wire transfer identifier to look up. */ - void *cb_cls; + struct TALER_WireTransferIdentifierRawP wtid; }; /** - * We got a #MHD_HTTP_OK response for the /transfers/ request. + * We got a #MHD_HTTP_OK response for the /transfers/$WTID request. * Check that the response is well-formed and if it is, call the * callback. If not, return an error code. * @@ -74,20 +89,20 @@ struct TALER_EXCHANGE_TransfersGetHandle * merchant_api_track_transfer.c::check_transfers_get_response_ok. * Any changes should likely be reflected there as well. * - * @param wdh handle to the operation + * @param gth handle to the operation * @param json response we got * @return #GNUNET_OK if we are done and all is well, * #GNUNET_SYSERR if the response was bogus */ static enum GNUNET_GenericReturnValue check_transfers_get_response_ok ( - struct TALER_EXCHANGE_TransfersGetHandle *wdh, + struct TALER_EXCHANGE_GetTransfersHandle *gth, const json_t *json) { const json_t *details_j; struct TALER_Amount total_expected; struct TALER_MerchantPublicKeyP merchant_pub; - struct TALER_EXCHANGE_TransfersGetResponse tgr = { + struct TALER_EXCHANGE_GetTransfersResponse tgr = { .hr.reply = json, .hr.http_status = MHD_HTTP_OK }; @@ -130,7 +145,7 @@ check_transfers_get_response_ok ( } if (GNUNET_OK != TALER_EXCHANGE_test_signing_key ( - wdh->keys, + gth->keys, &td->exchange_pub)) { GNUNET_break_op (0); @@ -145,7 +160,7 @@ check_transfers_get_response_ok ( struct TALER_TrackTransferDetails); td->details = details; hash_context = GNUNET_CRYPTO_hash_context_start (); - for (unsigned int i = 0; i<td->details_length; i++) + for (unsigned int i = 0; i < td->details_length; i++) { struct TALER_TrackTransferDetails *detail = &details[i]; struct json_t *detail_j = json_array_get (details_j, i); @@ -231,8 +246,9 @@ check_transfers_get_response_ok ( GNUNET_free (details); return GNUNET_SYSERR; } - wdh->cb (wdh->cb_cls, + gth->cb (gth->cb_cls, &tgr); + gth->cb = NULL; GNUNET_free (details); } return GNUNET_OK; @@ -241,9 +257,9 @@ check_transfers_get_response_ok ( /** * Function called when we're done processing the - * HTTP /transfers/ request. + * HTTP GET /transfers/$WTID request. * - * @param cls the `struct TALER_EXCHANGE_TransfersGetHandle` + * @param cls the `struct TALER_EXCHANGE_GetTransfersHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -252,14 +268,14 @@ handle_transfers_get_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_TransfersGetHandle *wdh = cls; + struct TALER_EXCHANGE_GetTransfersHandle *gth = cls; const json_t *j = response; - struct TALER_EXCHANGE_TransfersGetResponse tgr = { + struct TALER_EXCHANGE_GetTransfersResponse tgr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - wdh->job = NULL; + gth->job = NULL; switch (response_code) { case 0: @@ -267,10 +283,11 @@ handle_transfers_get_finished (void *cls, break; case MHD_HTTP_OK: if (GNUNET_OK == - check_transfers_get_response_ok (wdh, + check_transfers_get_response_ok (gth, j)) { - TALER_EXCHANGE_transfers_get_cancel (wdh); + GNUNET_assert (NULL == gth->cb); + TALER_EXCHANGE_get_transfers_cancel (gth); return; } GNUNET_break_op (0); @@ -313,36 +330,53 @@ handle_transfers_get_finished (void *cls, (int) tgr.hr.ec); break; } - wdh->cb (wdh->cb_cls, - &tgr); - TALER_EXCHANGE_transfers_get_cancel (wdh); + if (NULL != gth->cb) + gth->cb (gth->cb_cls, + &tgr); + TALER_EXCHANGE_get_transfers_cancel (gth); } -struct TALER_EXCHANGE_TransfersGetHandle * -TALER_EXCHANGE_transfers_get ( +struct TALER_EXCHANGE_GetTransfersHandle * +TALER_EXCHANGE_get_transfers_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, - const struct TALER_WireTransferIdentifierRawP *wtid, - TALER_EXCHANGE_TransfersGetCallback cb, - void *cb_cls) + const struct TALER_WireTransferIdentifierRawP *wtid) { - struct TALER_EXCHANGE_TransfersGetHandle *wdh; - CURL *eh; - char arg_str[sizeof (struct TALER_WireTransferIdentifierRawP) * 2 + 32]; + struct TALER_EXCHANGE_GetTransfersHandle *gth; + + gth = GNUNET_new (struct TALER_EXCHANGE_GetTransfersHandle); + gth->ctx = ctx; + gth->base_url = GNUNET_strdup (url); + gth->keys = TALER_EXCHANGE_keys_incref (keys); + gth->wtid = *wtid; + return gth; +} - wdh = GNUNET_new (struct TALER_EXCHANGE_TransfersGetHandle); - wdh->cb = cb; - wdh->cb_cls = cb_cls; +enum TALER_ErrorCode +TALER_EXCHANGE_get_transfers_start ( + struct TALER_EXCHANGE_GetTransfersHandle *gth, + TALER_EXCHANGE_GetTransfersCallback cb, + TALER_EXCHANGE_GET_TRANSFERS_RESULT_CLOSURE *cb_cls) +{ + char arg_str[sizeof (struct TALER_WireTransferIdentifierRawP) * 2 + 32]; + CURL *eh; + + if (NULL != gth->job) + { + GNUNET_break (0); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + gth->cb = cb; + gth->cb_cls = cb_cls; { char wtid_str[sizeof (struct TALER_WireTransferIdentifierRawP) * 2]; char *end; - end = GNUNET_STRINGS_data_to_string (wtid, - sizeof (struct - TALER_WireTransferIdentifierRawP), + end = GNUNET_STRINGS_data_to_string (&gth->wtid, + sizeof (gth->wtid), wtid_str, sizeof (wtid_str)); *end = '\0'; @@ -351,50 +385,38 @@ TALER_EXCHANGE_transfers_get ( "transfers/%s", wtid_str); } - wdh->url = TALER_url_join (url, + gth->url = TALER_url_join (gth->base_url, arg_str, NULL); - if (NULL == wdh->url) - { - GNUNET_free (wdh); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (wdh->url); + if (NULL == gth->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + eh = TALER_EXCHANGE_curl_easy_get_ (gth->url); if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (wdh->url); - GNUNET_free (wdh); - return NULL; - } - wdh->keys = TALER_EXCHANGE_keys_incref (keys); - wdh->job = GNUNET_CURL_job_add_with_ct_json (ctx, + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + gth->job = GNUNET_CURL_job_add_with_ct_json (gth->ctx, eh, &handle_transfers_get_finished, - wdh); - return wdh; + gth); + if (NULL == gth->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } -/** - * Cancel wire deposits request. This function cannot be used on a request - * handle if a response is already served for it. - * - * @param wdh the wire deposits request handle - */ void -TALER_EXCHANGE_transfers_get_cancel ( - struct TALER_EXCHANGE_TransfersGetHandle *wdh) +TALER_EXCHANGE_get_transfers_cancel ( + struct TALER_EXCHANGE_GetTransfersHandle *gth) { - if (NULL != wdh->job) + if (NULL != gth->job) { - GNUNET_CURL_job_cancel (wdh->job); - wdh->job = NULL; + GNUNET_CURL_job_cancel (gth->job); + gth->job = NULL; } - GNUNET_free (wdh->url); - TALER_EXCHANGE_keys_decref (wdh->keys); - GNUNET_free (wdh); + GNUNET_free (gth->url); + GNUNET_free (gth->base_url); + TALER_EXCHANGE_keys_decref (gth->keys); + GNUNET_free (gth); } -/* end of exchange_api_transfers_get.c */ +/* end of exchange_api_get-transfers-WTID.c */ diff --git a/src/lib/exchange_api_post-auditors-AUDITOR_PUB-H_DENOM_PUB.c b/src/lib/exchange_api_post-auditors-AUDITOR_PUB-H_DENOM_PUB.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015-2021 Taler Systems SA + Copyright (C) 2015-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -24,17 +24,22 @@ #include <gnunet/gnunet_curl_lib.h> #include <microhttpd.h> #include "taler/taler_exchange_service.h" +#include "taler/taler-exchange/post-auditors-AUDITOR_PUB-H_DENOM_PUB.h" #include "auditor_api_curl_defaults.h" #include "taler/taler_signatures.h" #include "taler/taler_curl_lib.h" -#include "taler/taler_json_lib.h" -struct TALER_EXCHANGE_AuditorAddDenominationHandle +struct TALER_EXCHANGE_PostAuditorsHandle { /** - * The url for this request. + * The base URL for this request. + */ + char *base_url; + + /** + * The full URL for this request, set during _start. */ char *url; @@ -51,17 +56,33 @@ struct TALER_EXCHANGE_AuditorAddDenominationHandle /** * Function to call with the result. */ - TALER_EXCHANGE_AuditorAddDenominationCallback cb; + TALER_EXCHANGE_PostAuditorsCallback cb; /** * Closure for @a cb. */ - void *cb_cls; + TALER_EXCHANGE_POST_AUDITORS_RESULT_CLOSURE *cb_cls; /** * Reference to the execution context. */ struct GNUNET_CURL_Context *ctx; + + /** + * Hash of the denomination public key. + */ + struct TALER_DenominationHashP h_denom_pub; + + /** + * The auditor's public key. + */ + struct TALER_AuditorPublicKeyP auditor_pub; + + /** + * The auditor's signature. + */ + struct TALER_AuditorSignatureP auditor_sig; + }; @@ -69,7 +90,7 @@ struct TALER_EXCHANGE_AuditorAddDenominationHandle * Function called when we're done processing the * HTTP POST /auditor/$AUDITOR_PUB/$H_DENOM_PUB request. * - * @param cls the `struct TALER_EXCHANGE_AuditorAddDenominationHandle *` + * @param cls the `struct TALER_EXCHANGE_PostAuditorsHandle *` * @param response_code HTTP response code, 0 on error * @param response response body, NULL if not in JSON */ @@ -78,9 +99,9 @@ handle_auditor_add_denomination_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_AuditorAddDenominationHandle *ah = cls; + struct TALER_EXCHANGE_PostAuditorsHandle *ah = cls; const json_t *json = response; - struct TALER_EXCHANGE_AuditorAddDenominationResponse adr = { + struct TALER_EXCHANGE_PostAuditorsResponse adr = { .hr.http_status = (unsigned int) response_code, .hr.reply = json }; @@ -135,41 +156,54 @@ handle_auditor_add_denomination_finished (void *cls, &adr); ah->cb = NULL; } - TALER_EXCHANGE_add_auditor_denomination_cancel (ah); + TALER_EXCHANGE_post_auditors_cancel (ah); } -struct TALER_EXCHANGE_AuditorAddDenominationHandle * -TALER_EXCHANGE_add_auditor_denomination ( +struct TALER_EXCHANGE_PostAuditorsHandle * +TALER_EXCHANGE_post_auditors_create ( struct GNUNET_CURL_Context *ctx, const char *url, const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_AuditorPublicKeyP *auditor_pub, - const struct TALER_AuditorSignatureP *auditor_sig, - TALER_EXCHANGE_AuditorAddDenominationCallback cb, - void *cb_cls) + const struct TALER_AuditorSignatureP *auditor_sig) +{ + struct TALER_EXCHANGE_PostAuditorsHandle *ah; + + ah = GNUNET_new (struct TALER_EXCHANGE_PostAuditorsHandle); + ah->ctx = ctx; + ah->base_url = GNUNET_strdup (url); + ah->h_denom_pub = *h_denom_pub; + ah->auditor_pub = *auditor_pub; + ah->auditor_sig = *auditor_sig; + return ah; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_auditors_start ( + struct TALER_EXCHANGE_PostAuditorsHandle *ah, + TALER_EXCHANGE_PostAuditorsCallback cb, + TALER_EXCHANGE_POST_AUDITORS_RESULT_CLOSURE *cb_cls) { - struct TALER_EXCHANGE_AuditorAddDenominationHandle *ah; CURL *eh; json_t *body; - ah = GNUNET_new (struct TALER_EXCHANGE_AuditorAddDenominationHandle); ah->cb = cb; ah->cb_cls = cb_cls; - ah->ctx = ctx; { - char apub_str[sizeof (*auditor_pub) * 2]; - char denom_str[sizeof (*h_denom_pub) * 2]; + char apub_str[sizeof (ah->auditor_pub) * 2]; + char denom_str[sizeof (ah->h_denom_pub) * 2]; char arg_str[sizeof (apub_str) + sizeof (denom_str) + 32]; char *end; - end = GNUNET_STRINGS_data_to_string (auditor_pub, - sizeof (*auditor_pub), + end = GNUNET_STRINGS_data_to_string (&ah->auditor_pub, + sizeof (ah->auditor_pub), apub_str, sizeof (apub_str)); *end = '\0'; - end = GNUNET_STRINGS_data_to_string (h_denom_pub, - sizeof (*h_denom_pub), + end = GNUNET_STRINGS_data_to_string (&ah->h_denom_pub, + sizeof (ah->h_denom_pub), denom_str, sizeof (denom_str)); *end = '\0'; @@ -178,7 +212,7 @@ TALER_EXCHANGE_add_auditor_denomination ( "auditors/%s/%s", apub_str, denom_str); - ah->url = TALER_url_join (url, + ah->url = TALER_url_join (ah->base_url, arg_str, NULL); } @@ -186,12 +220,11 @@ TALER_EXCHANGE_add_auditor_denomination ( { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not construct request URL.\n"); - GNUNET_free (ah); - return NULL; + return TALER_EC_GENERIC_CONFIGURATION_INVALID; } body = GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("auditor_sig", - auditor_sig)); + &ah->auditor_sig)); eh = TALER_AUDITOR_curl_easy_get_ (ah->url); if ( (NULL == eh) || (GNUNET_OK != @@ -203,30 +236,26 @@ TALER_EXCHANGE_add_auditor_denomination ( if (NULL != eh) curl_easy_cleanup (eh); json_decref (body); - GNUNET_free (ah->url); - return NULL; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } json_decref (body); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting URL '%s'\n", ah->url); - ah->job = GNUNET_CURL_job_add2 (ctx, + ah->job = GNUNET_CURL_job_add2 (ah->ctx, eh, ah->post_ctx.headers, &handle_auditor_add_denomination_finished, ah); if (NULL == ah->job) - { - TALER_EXCHANGE_add_auditor_denomination_cancel (ah); - return NULL; - } - return ah; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_add_auditor_denomination_cancel ( - struct TALER_EXCHANGE_AuditorAddDenominationHandle *ah) +TALER_EXCHANGE_post_auditors_cancel ( + struct TALER_EXCHANGE_PostAuditorsHandle *ah) { if (NULL != ah->job) { @@ -235,5 +264,9 @@ TALER_EXCHANGE_add_auditor_denomination_cancel ( } TALER_curl_easy_post_finished (&ah->post_ctx); GNUNET_free (ah->url); + GNUNET_free (ah->base_url); GNUNET_free (ah); } + + +/* end of exchange_api_post-auditors-AUDITOR_PUB-H_DENOM_PUB.c */ diff --git a/src/lib/exchange_api_post-batch-deposit.c b/src/lib/exchange_api_post-batch-deposit.c @@ -1,19 +1,19 @@ /* - This file is part of TALER - Copyright (C) 2014-2024 Taler Systems SA + This file is part of TALER + Copyright (C) 2014-2024 Taler Systems SA - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - <http://www.gnu.org/licenses/> - */ + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ /** * @file lib/exchange_api_post-batch-deposit.c * @brief Implementation of the /batch-deposit request of the exchange's HTTP API @@ -73,14 +73,14 @@ struct TEAH_AuditorInteractionEntry /** * Batch deposit this is for. */ - struct TALER_EXCHANGE_BatchDepositHandle *dh; + struct TALER_EXCHANGE_PostBatchDepositHandle *dh; }; /** - * @brief A Deposit Handle + * @brief A Batch Deposit Handle */ -struct TALER_EXCHANGE_BatchDepositHandle +struct TALER_EXCHANGE_PostBatchDepositHandle { /** @@ -94,7 +94,12 @@ struct TALER_EXCHANGE_BatchDepositHandle struct GNUNET_CURL_Context *ctx; /** - * The url for this request. + * The base URL of the exchange (used to build the endpoint URL in _start). + */ + char *base_url; + + /** + * The full endpoint URL for this request (built in _start). */ char *url; @@ -112,7 +117,7 @@ struct TALER_EXCHANGE_BatchDepositHandle /** * Function to call with the result. */ - TALER_EXCHANGE_BatchDepositResultCallback cb; + TALER_EXCHANGE_PostBatchDepositCallback cb; /** * Closure for @a cb. @@ -163,7 +168,7 @@ struct TALER_EXCHANGE_BatchDepositHandle /** * Result to return to the application once @e ai_head is empty. */ - struct TALER_EXCHANGE_BatchDepositResult dr; + struct TALER_EXCHANGE_PostBatchDepositResponse dr; /** * Exchange signing public key, set for #auditor_cb. @@ -181,6 +186,11 @@ struct TALER_EXCHANGE_BatchDepositHandle json_t *response; /** + * The JSON body to POST (built during _create, used during _start). + */ + json_t *deposit_obj; + + /** * Chance that we will inform the auditor about the deposit * is 1:n, where the value of this field is "n". */ @@ -200,11 +210,11 @@ struct TALER_EXCHANGE_BatchDepositHandle * @param[in] dh handle to finished batch deposit operation */ static void -finish_dh (struct TALER_EXCHANGE_BatchDepositHandle *dh) +finish_dh (struct TALER_EXCHANGE_PostBatchDepositHandle *dh) { dh->cb (dh->cb_cls, &dh->dr); - TALER_EXCHANGE_batch_deposit_cancel (dh); + TALER_EXCHANGE_post_batch_deposit_cancel (dh); } @@ -221,7 +231,7 @@ acc_confirmation_cb ( const struct TALER_AUDITOR_DepositConfirmationResponse *dcr) { struct TEAH_AuditorInteractionEntry *aie = cls; - struct TALER_EXCHANGE_BatchDepositHandle *dh = aie->dh; + struct TALER_EXCHANGE_PostBatchDepositHandle *dh = aie->dh; if (MHD_HTTP_OK != dcr->hr.http_status) { @@ -253,7 +263,7 @@ auditor_cb (void *cls, const char *auditor_url, const struct TALER_AuditorPublicKeyP *auditor_pub) { - struct TALER_EXCHANGE_BatchDepositHandle *dh = cls; + struct TALER_EXCHANGE_PostBatchDepositHandle *dh = cls; const struct TALER_EXCHANGE_SigningPublicKey *spk; struct TEAH_AuditorInteractionEntry *aie; const struct TALER_CoinSpendSignatureP *csigs[GNUNET_NZL ( @@ -321,9 +331,9 @@ auditor_cb (void *cls, /** * Function called when we're done processing the - * HTTP /deposit request. + * HTTP /batch-deposit request. * - * @param cls the `struct TALER_EXCHANGE_BatchDepositHandle` + * @param cls the `struct TALER_EXCHANGE_PostBatchDepositHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -332,9 +342,9 @@ handle_deposit_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_BatchDepositHandle *dh = cls; + struct TALER_EXCHANGE_PostBatchDepositHandle *dh = cls; const json_t *j = response; - struct TALER_EXCHANGE_BatchDepositResult *dr = &dh->dr; + struct TALER_EXCHANGE_PostBatchDepositResponse *dr = &dh->dr; dh->job = NULL; dh->response = json_incref ((json_t*) j); @@ -572,27 +582,24 @@ handle_deposit_finished (void *cls, } -struct TALER_EXCHANGE_BatchDepositHandle * -TALER_EXCHANGE_batch_deposit ( +struct TALER_EXCHANGE_PostBatchDepositHandle * +TALER_EXCHANGE_post_batch_deposit_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_DepositContractDetail *dcd, unsigned int num_cdds, const struct TALER_EXCHANGE_CoinDepositDetail cdds[static num_cdds], - TALER_EXCHANGE_BatchDepositResultCallback cb, - void *cb_cls, enum TALER_ErrorCode *ec) { - struct TALER_EXCHANGE_BatchDepositHandle *dh; - json_t *deposit_obj; + struct TALER_EXCHANGE_PostBatchDepositHandle *dh; json_t *deposits; - CURL *eh; const struct GNUNET_HashCode *wallet_data_hashp; if (0 == num_cdds) { GNUNET_break (0); + *ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; return NULL; } if (GNUNET_TIME_timestamp_cmp (dcd->refund_deadline, @@ -603,10 +610,10 @@ TALER_EXCHANGE_batch_deposit ( *ec = TALER_EC_EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE; return NULL; } - dh = GNUNET_new (struct TALER_EXCHANGE_BatchDepositHandle); + dh = GNUNET_new (struct TALER_EXCHANGE_PostBatchDepositHandle); dh->auditor_chance = AUDITOR_CHANCE; - dh->cb = cb; - dh->cb_cls = cb_cls; + dh->ctx = ctx; + dh->base_url = GNUNET_strdup (url); dh->cdds = GNUNET_memdup (cdds, num_cdds * sizeof (*cdds)); dh->num_cdds = num_cdds; @@ -636,6 +643,9 @@ TALER_EXCHANGE_batch_deposit ( *ec = TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN; GNUNET_break_op (0); json_decref (deposits); + GNUNET_free (dh->base_url); + GNUNET_free (dh->cdds); + GNUNET_free (dh); return NULL; } if (0 > @@ -645,9 +655,10 @@ TALER_EXCHANGE_batch_deposit ( { *ec = TALER_EC_EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT; GNUNET_break_op (0); + json_decref (deposits); + GNUNET_free (dh->base_url); GNUNET_free (dh->cdds); GNUNET_free (dh); - json_decref (deposits); return NULL; } GNUNET_assert (0 <= @@ -663,9 +674,10 @@ TALER_EXCHANGE_batch_deposit ( { *ec = TALER_EC_EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID; GNUNET_break_op (0); + json_decref (deposits); + GNUNET_free (dh->base_url); GNUNET_free (dh->cdds); GNUNET_free (dh); - json_decref (deposits); return NULL; } if (! GNUNET_is_zero (&dcd->merchant_sig)) @@ -696,26 +708,13 @@ TALER_EXCHANGE_batch_deposit ( &cdd->coin_sig) ))); } - dh->url = TALER_url_join (url, - "batch-deposit", - NULL); - if (NULL == dh->url) - { - GNUNET_break (0); - *ec = TALER_EC_GENERIC_ALLOCATION_FAILURE; - GNUNET_free (dh->url); - GNUNET_free (dh->cdds); - GNUNET_free (dh); - json_decref (deposits); - return NULL; - } if (GNUNET_is_zero (&dcd->wallet_data_hash)) wallet_data_hashp = NULL; else wallet_data_hashp = &dcd->wallet_data_hash; - deposit_obj = GNUNET_JSON_PACK ( + dh->deposit_obj = GNUNET_JSON_PACK ( TALER_JSON_pack_full_payto ("merchant_payto_uri", dcd->merchant_payto_uri), GNUNET_JSON_pack_allow_null ( @@ -744,77 +743,108 @@ TALER_EXCHANGE_batch_deposit ( dcd->refund_deadline)), GNUNET_JSON_pack_timestamp ("wire_transfer_deadline", dcd->wire_deadline)); - GNUNET_assert (NULL != deposit_obj); - eh = TALER_EXCHANGE_curl_easy_get_ (dh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&dh->post_ctx, - eh, - deposit_obj)) ) + if (NULL == dh->deposit_obj) { - *ec = TALER_EC_GENERIC_CURL_ALLOCATION_FAILURE; GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (deposit_obj); + *ec = TALER_EC_GENERIC_ALLOCATION_FAILURE; + GNUNET_free (dh->base_url); GNUNET_free (dh->cdds); - GNUNET_free (dh->url); GNUNET_free (dh); return NULL; } - json_decref (deposit_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for deposit: `%s'\n", - dh->url); - dh->ctx = ctx; dh->keys = TALER_EXCHANGE_keys_incref (keys); - dh->job = GNUNET_CURL_job_add2 (ctx, - eh, - dh->post_ctx.headers, - &handle_deposit_finished, - dh); + *ec = TALER_EC_NONE; return dh; } void -TALER_EXCHANGE_batch_deposit_force_dc ( - struct TALER_EXCHANGE_BatchDepositHandle *deposit) +TALER_EXCHANGE_post_batch_deposit_force_dc ( + struct TALER_EXCHANGE_PostBatchDepositHandle *pbdh) { - deposit->auditor_chance = 1; + // FIXME: turn this into an option! + pbdh->auditor_chance = 1; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_batch_deposit_start ( + struct TALER_EXCHANGE_PostBatchDepositHandle *pbdh, + TALER_EXCHANGE_PostBatchDepositCallback cb, + TALER_EXCHANGE_POST_BATCH_DEPOSIT_RESULT_CLOSURE *cb_cls) +{ + CURL *eh; + + pbdh->cb = cb; + pbdh->cb_cls = cb_cls; + pbdh->url = TALER_url_join (pbdh->base_url, + "batch-deposit", + NULL); + if (NULL == pbdh->url) + { + GNUNET_break (0); + return TALER_EC_GENERIC_ALLOCATION_FAILURE; + } + eh = TALER_EXCHANGE_curl_easy_get_ (pbdh->url); + if ( (NULL == eh) || + (GNUNET_OK != + TALER_curl_easy_post (&pbdh->post_ctx, + eh, + pbdh->deposit_obj)) ) + { + GNUNET_break (0); + if (NULL != eh) + curl_easy_cleanup (eh); + return TALER_EC_GENERIC_CURL_ALLOCATION_FAILURE; + } + json_decref (pbdh->deposit_obj); + pbdh->deposit_obj = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "URL for batch-deposit: `%s'\n", + pbdh->url); + pbdh->job = GNUNET_CURL_job_add2 (pbdh->ctx, + eh, + pbdh->post_ctx.headers, + &handle_deposit_finished, + pbdh); + if (NULL == pbdh->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_batch_deposit_cancel ( - struct TALER_EXCHANGE_BatchDepositHandle *deposit) +TALER_EXCHANGE_post_batch_deposit_cancel ( + struct TALER_EXCHANGE_PostBatchDepositHandle *pbdh) { struct TEAH_AuditorInteractionEntry *aie; - while (NULL != (aie = deposit->ai_head)) + while (NULL != (aie = pbdh->ai_head)) { - GNUNET_assert (aie->dh == deposit); + GNUNET_assert (aie->dh == pbdh); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Not sending deposit confirmation to auditor `%s' due to cancellation\n", aie->auditor_url); TALER_AUDITOR_deposit_confirmation_cancel (aie->dch); - GNUNET_CONTAINER_DLL_remove (deposit->ai_head, - deposit->ai_tail, + GNUNET_CONTAINER_DLL_remove (pbdh->ai_head, + pbdh->ai_tail, aie); GNUNET_free (aie); } - if (NULL != deposit->job) + if (NULL != pbdh->job) { - GNUNET_CURL_job_cancel (deposit->job); - deposit->job = NULL; + GNUNET_CURL_job_cancel (pbdh->job); + pbdh->job = NULL; } - TALER_EXCHANGE_keys_decref (deposit->keys); - GNUNET_free (deposit->url); - GNUNET_free (deposit->cdds); - TALER_curl_easy_post_finished (&deposit->post_ctx); - json_decref (deposit->response); - GNUNET_free (deposit); + TALER_EXCHANGE_keys_decref (pbdh->keys); + GNUNET_free (pbdh->base_url); + GNUNET_free (pbdh->url); + GNUNET_free (pbdh->cdds); + TALER_curl_easy_post_finished (&pbdh->post_ctx); + json_decref (pbdh->deposit_obj); + json_decref (pbdh->response); + GNUNET_free (pbdh); } -/* end of exchange_api_batch_deposit.c */ +/* end of exchange_api_post-batch-deposit.c */ diff --git a/src/lib/exchange_api_post-blinding-prepare.c b/src/lib/exchange_api_post-blinding-prepare.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2025 Taler Systems SA + Copyright (C) 2025-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -18,6 +18,7 @@ * @file lib/exchange_api_post-blinding-prepare.c * @brief Implementation of /blinding-prepare requests * @author Özgür Kesim + * @author Christian Grothoff */ #include "taler/platform.h" @@ -41,10 +42,10 @@ /** * A /blinding-prepare request-handle */ -struct TALER_EXCHANGE_BlindingPrepareHandle +struct TALER_EXCHANGE_PostBlindingPrepareHandle { /** - * number of elements to prepare + * Number of elements to prepare. */ size_t num; @@ -59,7 +60,17 @@ struct TALER_EXCHANGE_BlindingPrepareHandle const struct TALER_BlindingMasterSeedP *seed; /** - * The url for this request. + * Copy of the nonce_keys array passed to _create. + */ + struct TALER_EXCHANGE_NonceKey *nonce_keys; + + /** + * The exchange base URL. + */ + char *exchange_url; + + /** + * The url for this request (built in _start). */ char *url; @@ -79,12 +90,12 @@ struct TALER_EXCHANGE_BlindingPrepareHandle struct TALER_CURL_PostContext post_ctx; /** - * Function to call with withdraw response results. + * Function to call with response results. */ - TALER_EXCHANGE_BlindingPrepareCallback callback; + TALER_EXCHANGE_PostBlindingPrepareCallback callback; /** - * Closure for @e callback + * Closure for @e callback. */ void *callback_cls; @@ -93,15 +104,16 @@ struct TALER_EXCHANGE_BlindingPrepareHandle /** * We got a 200 OK response for the /blinding-prepare operation. - * Extract the r_pub values and return them to the caller via the callback + * Extract the r_pub values and return them to the caller via the callback. * * @param handle operation handle * @param response response details * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors */ static enum GNUNET_GenericReturnValue -blinding_prepare_ok (struct TALER_EXCHANGE_BlindingPrepareHandle *handle, - struct TALER_EXCHANGE_BlindingPrepareResponse *response) +blinding_prepare_ok ( + struct TALER_EXCHANGE_PostBlindingPrepareHandle *handle, + struct TALER_EXCHANGE_PostBlindingPrepareResponse *response) { const json_t *j_r_pubs; const char *cipher; @@ -202,9 +214,10 @@ blinding_prepare_ok (struct TALER_EXCHANGE_BlindingPrepareHandle *handle, /** - * Function called when we're done processing the HTTP /blinding-prepare request. + * Function called when we're done processing the HTTP /blinding-prepare + * request. * - * @param cls the `struct TALER_EXCHANGE_BlindingPrepareHandle` + * @param cls the `struct TALER_EXCHANGE_PostBlindingPrepareHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -213,9 +226,9 @@ handle_blinding_prepare_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_BlindingPrepareHandle *handle = cls; + struct TALER_EXCHANGE_PostBlindingPrepareHandle *handle = cls; const json_t *j_response = response; - struct TALER_EXCHANGE_BlindingPrepareResponse bpr = { + struct TALER_EXCHANGE_PostBlindingPrepareResponse bpr = { .hr = { .reply = j_response, .http_status = (unsigned int) response_code @@ -242,7 +255,7 @@ handle_blinding_prepare_finished (void *cls, break; } } - TALER_EXCHANGE_blinding_prepare_cancel (handle); + TALER_EXCHANGE_post_blinding_prepare_cancel (handle); return; case MHD_HTTP_BAD_REQUEST: @@ -263,9 +276,6 @@ handle_blinding_prepare_finished (void *cls, case MHD_HTTP_GONE: /* could happen if denomination was revoked */ - /* Note: one might want to check /keys for revocation - signature here, alas tricky in case our /keys - is outdated => left to clients */ bpr.hr.ec = TALER_JSON_get_error_code (j_response); bpr.hr.hint = TALER_JSON_get_error_hint (j_response); break; @@ -293,118 +303,133 @@ handle_blinding_prepare_finished (void *cls, handle->callback (handle->callback_cls, &bpr); handle->callback = NULL; - TALER_EXCHANGE_blinding_prepare_cancel (handle); + TALER_EXCHANGE_post_blinding_prepare_cancel (handle); } -struct TALER_EXCHANGE_BlindingPrepareHandle * -TALER_EXCHANGE_blinding_prepare ( +struct TALER_EXCHANGE_PostBlindingPrepareHandle * +TALER_EXCHANGE_post_blinding_prepare_create ( struct GNUNET_CURL_Context *curl_ctx, const char *exchange_url, const struct TALER_BlindingMasterSeedP *seed, bool for_melt, size_t num, - const struct TALER_EXCHANGE_NonceKey nonce_keys[static num], - TALER_EXCHANGE_BlindingPrepareCallback callback, - void *callback_cls) + const struct TALER_EXCHANGE_NonceKey nonce_keys[static num]) { - struct TALER_EXCHANGE_BlindingPrepareHandle *bph; + struct TALER_EXCHANGE_PostBlindingPrepareHandle *bph; if (0 == num) { GNUNET_break (0); return NULL; } - for (unsigned int i = 0; i<num; i++) + for (unsigned int i = 0; i < num; i++) if (GNUNET_CRYPTO_BSA_CS != nonce_keys[i].pk->key.bsign_pub_key->cipher) { GNUNET_break (0); return NULL; } - bph = GNUNET_new (struct TALER_EXCHANGE_BlindingPrepareHandle); + bph = GNUNET_new (struct TALER_EXCHANGE_PostBlindingPrepareHandle); bph->num = num; - bph->callback = callback; bph->for_melt = for_melt; - bph->callback_cls = callback_cls; - bph->url = TALER_url_join (exchange_url, + bph->seed = seed; + bph->curl_ctx = curl_ctx; + bph->exchange_url = GNUNET_strdup (exchange_url); + bph->nonce_keys = GNUNET_new_array (num, + struct TALER_EXCHANGE_NonceKey); + memcpy (bph->nonce_keys, + nonce_keys, + num * sizeof (struct TALER_EXCHANGE_NonceKey)); + return bph; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_blinding_prepare_start ( + struct TALER_EXCHANGE_PostBlindingPrepareHandle *bph, + TALER_EXCHANGE_PostBlindingPrepareCallback cb, + TALER_EXCHANGE_POST_BLINDING_PREPARE_RESULT_CLOSURE *cb_cls) +{ + CURL *eh; + json_t *j_nks; + json_t *j_request; + + bph->callback = cb; + bph->callback_cls = cb_cls; + + bph->url = TALER_url_join (bph->exchange_url, "blinding-prepare", NULL); if (NULL == bph->url) { GNUNET_break (0); - GNUNET_free (bph); - return NULL; + return TALER_EC_GENERIC_CONFIGURATION_INVALID; } + + j_request = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("cipher", + "CS"), + GNUNET_JSON_pack_string ("operation", + bph->for_melt ? "melt" : "withdraw"), + GNUNET_JSON_pack_data_auto ("seed", + bph->seed)); + GNUNET_assert (NULL != j_request); + + j_nks = json_array (); + GNUNET_assert (NULL != j_nks); + + for (size_t i = 0; i < bph->num; i++) { - CURL *eh; - json_t *j_nks; - json_t *j_request = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("cipher", - "CS"), - GNUNET_JSON_pack_string ("operation", - for_melt ? "melt" : "withdraw"), - GNUNET_JSON_pack_data_auto ("seed", - seed)); - GNUNET_assert (NULL != j_request); - - j_nks = json_array (); - GNUNET_assert (NULL != j_nks); - - for (size_t i = 0; i<num; i++) - { - const struct TALER_EXCHANGE_NonceKey *nk = &nonce_keys[i]; - json_t *j_entry = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_uint64 ("coin_offset", - nk->cnc_num), - GNUNET_JSON_pack_data_auto ("denom_pub_hash", - &nk->pk->h_key)); - - GNUNET_assert (NULL != j_entry); - GNUNET_assert (0 == - json_array_append_new (j_nks, - j_entry)); - } + const struct TALER_EXCHANGE_NonceKey *nk = &bph->nonce_keys[i]; + json_t *j_entry = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_uint64 ("coin_offset", + nk->cnc_num), + GNUNET_JSON_pack_data_auto ("denom_pub_hash", + &nk->pk->h_key)); + + GNUNET_assert (NULL != j_entry); GNUNET_assert (0 == - json_object_set_new (j_request, - "nks", - j_nks)); - eh = TALER_EXCHANGE_curl_easy_get_ (bph->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&bph->post_ctx, - eh, - j_request))) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (j_request); - GNUNET_free (bph->url); - GNUNET_free (bph); - return NULL; - } - + json_array_append_new (j_nks, + j_entry)); + } + GNUNET_assert (0 == + json_object_set_new (j_request, + "nks", + j_nks)); + + eh = TALER_EXCHANGE_curl_easy_get_ (bph->url); + if ( (NULL == eh) || + (GNUNET_OK != + TALER_curl_easy_post (&bph->post_ctx, + eh, + j_request))) + { + GNUNET_break (0); + if (NULL != eh) + curl_easy_cleanup (eh); json_decref (j_request); - bph->job = GNUNET_CURL_job_add2 (curl_ctx, - eh, - bph->post_ctx.headers, - &handle_blinding_prepare_finished, - bph); - if (NULL == bph->job) - { - GNUNET_break (0); - TALER_EXCHANGE_blinding_prepare_cancel (bph); - return NULL; - } + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } - return bph; + + json_decref (j_request); + bph->job = GNUNET_CURL_job_add2 (bph->curl_ctx, + eh, + bph->post_ctx.headers, + &handle_blinding_prepare_finished, + bph); + if (NULL == bph->job) + { + GNUNET_break (0); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + return TALER_EC_NONE; } void -TALER_EXCHANGE_blinding_prepare_cancel ( - struct TALER_EXCHANGE_BlindingPrepareHandle *bph) +TALER_EXCHANGE_post_blinding_prepare_cancel ( + struct TALER_EXCHANGE_PostBlindingPrepareHandle *bph) { if (NULL == bph) return; @@ -414,9 +439,11 @@ TALER_EXCHANGE_blinding_prepare_cancel ( bph->job = NULL; } GNUNET_free (bph->url); + GNUNET_free (bph->exchange_url); + GNUNET_free (bph->nonce_keys); TALER_curl_easy_post_finished (&bph->post_ctx); GNUNET_free (bph); } -/* end of lib/exchange_api_blinding_prepare.c */ +/* end of lib/exchange_api_post-blinding-prepare.c */ diff --git a/src/lib/exchange_api_post-coins-COIN_PUB-refund.c b/src/lib/exchange_api_post-coins-COIN_PUB-refund.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA + Copyright (C) 2014-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -27,15 +27,16 @@ #include <gnunet/gnunet_curl_lib.h> #include "taler/taler_json_lib.h" #include "taler/taler_exchange_service.h" +#include "taler/taler-exchange/post-coins-COIN_PUB-refund.h" #include "exchange_api_handle.h" #include "taler/taler_signatures.h" #include "exchange_api_curl_defaults.h" /** - * @brief A Refund Handle + * @brief A POST /coins/$COIN_PUB/refund Handle */ -struct TALER_EXCHANGE_RefundHandle +struct TALER_EXCHANGE_PostCoinsRefundHandle { /** @@ -44,15 +45,25 @@ struct TALER_EXCHANGE_RefundHandle struct TALER_EXCHANGE_Keys *keys; /** - * The url for this request. + * The exchange base URL. + */ + char *base_url; + + /** + * The full URL for this request, set during _start. */ char *url; /** + * Reference to the execution context. + */ + struct GNUNET_CURL_Context *ctx; + + /** * Context for #TEH_curl_easy_post(). Keeps the data that must * persist for Curl to make the upload. */ - struct TALER_CURL_PostContext ctx; + struct TALER_CURL_PostContext post_ctx; /** * Handle for the request. @@ -62,12 +73,12 @@ struct TALER_EXCHANGE_RefundHandle /** * Function to call with the result. */ - TALER_EXCHANGE_RefundCallback cb; + TALER_EXCHANGE_PostCoinsRefundCallback cb; /** - * Closure for @a cb. + * Closure for @e cb. */ - void *cb_cls; + TALER_EXCHANGE_POST_COINS_REFUND_RESULT_CLOSURE *cb_cls; /** * Hash over the proposal data to identify the contract @@ -82,10 +93,14 @@ struct TALER_EXCHANGE_RefundHandle struct TALER_CoinSpendPublicKeyP coin_pub; /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. + * The Merchant's public key. + */ + struct TALER_MerchantPublicKeyP merchant_pub; + + /** + * The merchant's private key (for signing). */ - struct TALER_MerchantPublicKeyP merchant; + struct TALER_MerchantPrivateKeyP merchant_priv; /** * Merchant-generated transaction ID for the refund. @@ -93,8 +108,7 @@ struct TALER_EXCHANGE_RefundHandle uint64_t rtransaction_id; /** - * Amount to be refunded, including refund fee charged by the - * exchange to the customer. + * Amount to be refunded. */ struct TALER_Amount refund_amount; @@ -112,7 +126,7 @@ struct TALER_EXCHANGE_RefundHandle * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not */ static enum GNUNET_GenericReturnValue -verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh, +verify_refund_signature_ok (struct TALER_EXCHANGE_PostCoinsRefundHandle *rh, const json_t *json, struct TALER_ExchangePublicKeyP *exchange_pub, struct TALER_ExchangeSignatureP *exchange_sig) @@ -144,7 +158,7 @@ verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh, TALER_exchange_online_refund_confirmation_verify ( &rh->h_contract_terms, &rh->coin_pub, - &rh->merchant, + &rh->merchant_pub, rh->rtransaction_id, &rh->refund_amount, exchange_pub, @@ -159,15 +173,14 @@ verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh, /** * Verify that the information on the "412 Dependency Failed" response - * from the exchange is valid and indeed shows that there is a refund - * transaction ID reuse going on. + * from the exchange is valid. * - * @param[in,out] rh refund handle (refund fee added) + * @param[in,out] rh refund handle * @param json json reply with the signature * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not */ static enum GNUNET_GenericReturnValue -verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, +verify_failed_dependency_ok (struct TALER_EXCHANGE_PostCoinsRefundHandle *rh, const json_t *json) { const json_t *h; @@ -240,7 +253,7 @@ verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, if ( (rtransaction_id != rh->rtransaction_id) || (0 != GNUNET_memcmp (&rh->h_contract_terms, &h_contract_terms)) || - (0 != GNUNET_memcmp (&rh->merchant, + (0 != GNUNET_memcmp (&rh->merchant_pub, &merchant_pub)) || (0 == TALER_amount_cmp (&rh->refund_amount, &amount)) ) @@ -257,7 +270,7 @@ verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, * Function called when we're done processing the * HTTP /refund request. * - * @param cls the `struct TALER_EXCHANGE_RefundHandle` + * @param cls the `struct TALER_EXCHANGE_PostCoinsRefundHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -266,9 +279,9 @@ handle_refund_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_RefundHandle *rh = cls; + struct TALER_EXCHANGE_PostCoinsRefundHandle *rh = cls; const json_t *j = response; - struct TALER_EXCHANGE_RefundResponse rr = { + struct TALER_EXCHANGE_PostCoinsRefundResponse rr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; @@ -360,14 +373,18 @@ handle_refund_finished (void *cls, rr.hr.ec); break; } - rh->cb (rh->cb_cls, - &rr); - TALER_EXCHANGE_refund_cancel (rh); + if (NULL != rh->cb) + { + rh->cb (rh->cb_cls, + &rr); + rh->cb = NULL; + } + TALER_EXCHANGE_post_coins_refund_cancel (rh); } -struct TALER_EXCHANGE_RefundHandle * -TALER_EXCHANGE_refund ( +struct TALER_EXCHANGE_PostCoinsRefundHandle * +TALER_EXCHANGE_post_coins_refund_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, @@ -375,31 +392,50 @@ TALER_EXCHANGE_refund ( const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_CoinSpendPublicKeyP *coin_pub, uint64_t rtransaction_id, - const struct TALER_MerchantPrivateKeyP *merchant_priv, - TALER_EXCHANGE_RefundCallback cb, - void *cb_cls) + const struct TALER_MerchantPrivateKeyP *merchant_priv) +{ + struct TALER_EXCHANGE_PostCoinsRefundHandle *rh; + + rh = GNUNET_new (struct TALER_EXCHANGE_PostCoinsRefundHandle); + rh->ctx = ctx; + rh->base_url = GNUNET_strdup (url); + rh->keys = TALER_EXCHANGE_keys_incref (keys); + rh->refund_amount = *amount; + rh->h_contract_terms = *h_contract_terms; + rh->coin_pub = *coin_pub; + rh->rtransaction_id = rtransaction_id; + rh->merchant_priv = *merchant_priv; + GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv, + &rh->merchant_pub.eddsa_pub); + return rh; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_coins_refund_start ( + struct TALER_EXCHANGE_PostCoinsRefundHandle *rh, + TALER_EXCHANGE_PostCoinsRefundCallback cb, + TALER_EXCHANGE_POST_COINS_REFUND_RESULT_CLOSURE *cb_cls) { - struct TALER_MerchantPublicKeyP merchant_pub; struct TALER_MerchantSignatureP merchant_sig; - struct TALER_EXCHANGE_RefundHandle *rh; json_t *refund_obj; CURL *eh; char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; - GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv, - &merchant_pub.eddsa_pub); - TALER_merchant_refund_sign (coin_pub, - h_contract_terms, - rtransaction_id, - amount, - merchant_priv, + rh->cb = cb; + rh->cb_cls = cb_cls; + TALER_merchant_refund_sign (&rh->coin_pub, + &rh->h_contract_terms, + rh->rtransaction_id, + &rh->refund_amount, + &rh->merchant_priv, &merchant_sig); { char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; char *end; end = GNUNET_STRINGS_data_to_string ( - coin_pub, + &rh->coin_pub, sizeof (struct TALER_CoinSpendPublicKeyP), pub_str, sizeof (pub_str)); @@ -411,36 +447,27 @@ TALER_EXCHANGE_refund ( } refund_obj = GNUNET_JSON_PACK ( TALER_JSON_pack_amount ("refund_amount", - amount), + &rh->refund_amount), GNUNET_JSON_pack_data_auto ("h_contract_terms", - h_contract_terms), + &rh->h_contract_terms), GNUNET_JSON_pack_uint64 ("rtransaction_id", - rtransaction_id), + rh->rtransaction_id), GNUNET_JSON_pack_data_auto ("merchant_pub", - &merchant_pub), + &rh->merchant_pub), GNUNET_JSON_pack_data_auto ("merchant_sig", &merchant_sig)); - rh = GNUNET_new (struct TALER_EXCHANGE_RefundHandle); - rh->cb = cb; - rh->cb_cls = cb_cls; - rh->url = TALER_url_join (url, + rh->url = TALER_url_join (rh->base_url, arg_str, NULL); if (NULL == rh->url) { json_decref (refund_obj); - GNUNET_free (rh); - return NULL; + return TALER_EC_GENERIC_CONFIGURATION_INVALID; } - rh->h_contract_terms = *h_contract_terms; - rh->coin_pub = *coin_pub; - rh->merchant = merchant_pub; - rh->rtransaction_id = rtransaction_id; - rh->refund_amount = *amount; eh = TALER_EXCHANGE_curl_easy_get_ (rh->url); if ( (NULL == eh) || (GNUNET_OK != - TALER_curl_easy_post (&rh->ctx, + TALER_curl_easy_post (&rh->post_ctx, eh, refund_obj)) ) { @@ -448,37 +475,38 @@ TALER_EXCHANGE_refund ( if (NULL != eh) curl_easy_cleanup (eh); json_decref (refund_obj); - GNUNET_free (rh->url); - GNUNET_free (rh); - return NULL; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } json_decref (refund_obj); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for refund: `%s'\n", rh->url); - rh->keys = TALER_EXCHANGE_keys_incref (keys); - rh->job = GNUNET_CURL_job_add2 (ctx, + rh->job = GNUNET_CURL_job_add2 (rh->ctx, eh, - rh->ctx.headers, + rh->post_ctx.headers, &handle_refund_finished, rh); - return rh; + if (NULL == rh->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund) +TALER_EXCHANGE_post_coins_refund_cancel ( + struct TALER_EXCHANGE_PostCoinsRefundHandle *rh) { - if (NULL != refund->job) + if (NULL != rh->job) { - GNUNET_CURL_job_cancel (refund->job); - refund->job = NULL; + GNUNET_CURL_job_cancel (rh->job); + rh->job = NULL; } - GNUNET_free (refund->url); - TALER_curl_easy_post_finished (&refund->ctx); - TALER_EXCHANGE_keys_decref (refund->keys); - GNUNET_free (refund); + GNUNET_free (rh->url); + GNUNET_free (rh->base_url); + TALER_curl_easy_post_finished (&rh->post_ctx); + TALER_EXCHANGE_keys_decref (rh->keys); + GNUNET_free (rh); } -/* end of exchange_api_refund.c */ +/* end of exchange_api_post-coins-COIN_PUB-refund.c */ diff --git a/src/lib/exchange_api_post-melt.c b/src/lib/exchange_api_post-melt.c @@ -37,7 +37,7 @@ /** * @brief A /melt Handle */ -struct TALER_EXCHANGE_MeltHandle +struct TALER_EXCHANGE_PostMeltHandle { /** @@ -74,7 +74,7 @@ struct TALER_EXCHANGE_MeltHandle /** * Function to call with refresh melt failure results. */ - TALER_EXCHANGE_MeltCallback melt_cb; + TALER_EXCHANGE_PostMeltCallback melt_cb; /** * Closure for @e result_cb and @e melt_failure_cb. @@ -117,7 +117,7 @@ struct TALER_EXCHANGE_MeltHandle /** * Handle for the preflight request, or NULL. */ - struct TALER_EXCHANGE_BlindingPrepareHandle *bpr; + struct TALER_EXCHANGE_PostBlindingPrepareHandle *bpr; /** * Public key of the coin being melted. @@ -152,7 +152,7 @@ struct TALER_EXCHANGE_MeltHandle * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not */ static enum GNUNET_GenericReturnValue -verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh, +verify_melt_signature_ok (struct TALER_EXCHANGE_PostMeltHandle *mh, const json_t *json, struct TALER_ExchangePublicKeyP *exchange_pub) { @@ -218,9 +218,9 @@ handle_melt_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_MeltHandle *mh = cls; + struct TALER_EXCHANGE_PostMeltHandle *mh = cls; const json_t *j = response; - struct TALER_EXCHANGE_MeltResponse mr = { + struct TALER_EXCHANGE_PostMeltResponse mr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; @@ -295,7 +295,7 @@ handle_melt_finished (void *cls, if (NULL != mh->melt_cb) mh->melt_cb (mh->melt_cb_cls, &mr); - TALER_EXCHANGE_melt_cancel (mh); + TALER_EXCHANGE_post_melt_cancel (mh); } @@ -307,7 +307,7 @@ handle_melt_finished (void *cls, * @return #GNUNET_OK if we could start the operation */ static enum GNUNET_GenericReturnValue -start_melt (struct TALER_EXCHANGE_MeltHandle *mh) +start_melt (struct TALER_EXCHANGE_PostMeltHandle *mh) { json_t *j_request_body; json_t *j_transfer_pubs; @@ -398,7 +398,8 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh) { json_t *j_coin = GNUNET_JSON_PACK ( TALER_JSON_pack_blinded_planchet (NULL, - &mh->md.kappa_blinded_planchets[k][i])); + &mh->md.kappa_blinded_planchets[k][i]) + ); GNUNET_assert (NULL != j_coin); GNUNET_assert (0 == json_array_append_new (j_envs, j_coin)); @@ -456,16 +457,16 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh) * @param ec error code to fail with */ static void -fail_mh (struct TALER_EXCHANGE_MeltHandle *mh, +fail_mh (struct TALER_EXCHANGE_PostMeltHandle *mh, enum TALER_ErrorCode ec) { - struct TALER_EXCHANGE_MeltResponse mr = { + struct TALER_EXCHANGE_PostMeltResponse mr = { .hr.ec = ec }; mh->melt_cb (mh->melt_cb_cls, &mr); - TALER_EXCHANGE_melt_cancel (mh); + TALER_EXCHANGE_post_melt_cancel (mh); } @@ -478,22 +479,23 @@ fail_mh (struct TALER_EXCHANGE_MeltHandle *mh, */ static void blinding_prepare_cb (void *cls, - const struct TALER_EXCHANGE_BlindingPrepareResponse *bpr) + const struct TALER_EXCHANGE_PostBlindingPrepareResponse * + bpr) { - struct TALER_EXCHANGE_MeltHandle *mh = cls; + struct TALER_EXCHANGE_PostMeltHandle *mh = cls; unsigned int nks_off = 0; mh->bpr = NULL; if (MHD_HTTP_OK != bpr->hr.http_status) { - struct TALER_EXCHANGE_MeltResponse mr = { + struct TALER_EXCHANGE_PostMeltResponse mr = { .hr = bpr->hr }; mr.hr.hint = "/blinding-prepare failed"; mh->melt_cb (mh->melt_cb_cls, &mr); - TALER_EXCHANGE_melt_cancel (mh); + TALER_EXCHANGE_post_melt_cancel (mh); return; } for (unsigned int i = 0; i<mh->rd->num_fresh_denom_pubs; i++) @@ -529,38 +531,32 @@ blinding_prepare_cb (void *cls, } -struct TALER_EXCHANGE_MeltHandle * -TALER_EXCHANGE_melt ( +struct TALER_EXCHANGE_PostMeltHandle * +TALER_EXCHANGE_post_melt_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, const struct TALER_PublicRefreshMasterSeedP *rms, - const struct TALER_EXCHANGE_MeltInput *rd, - TALER_EXCHANGE_MeltCallback melt_cb, - void *melt_cb_cls) + const struct TALER_EXCHANGE_MeltInput *rd) { - struct TALER_EXCHANGE_NonceKey nks[GNUNET_NZL (rd->num_fresh_denom_pubs)]; - unsigned int nks_off = 0; - struct TALER_EXCHANGE_MeltHandle *mh; + struct TALER_EXCHANGE_PostMeltHandle *mh; if (0 == rd->num_fresh_denom_pubs) { GNUNET_break (0); return NULL; } - mh = GNUNET_new (struct TALER_EXCHANGE_MeltHandle); + mh = GNUNET_new (struct TALER_EXCHANGE_PostMeltHandle); mh->noreveal_index = TALER_CNC_KAPPA; /* invalid value */ mh->cctx = ctx; mh->exchange_url = GNUNET_strdup (url); mh->rd = rd; mh->rms = *rms; - mh->melt_cb = melt_cb; - mh->melt_cb_cls = melt_cb_cls; mh->no_blinding_seed = true; mh->melt_blinding_values = GNUNET_new_array (rd->num_fresh_denom_pubs, struct TALER_ExchangeBlindingValues); - for (unsigned int i = 0; i<rd->num_fresh_denom_pubs; i++) + for (unsigned int i = 0; i < rd->num_fresh_denom_pubs; i++) { const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = &rd->fresh_denom_pubs[i]; @@ -570,6 +566,7 @@ TALER_EXCHANGE_melt ( case GNUNET_CRYPTO_BSA_INVALID: GNUNET_break (0); GNUNET_free (mh->melt_blinding_values); + GNUNET_free (mh->exchange_url); GNUNET_free (mh); return NULL; case GNUNET_CRYPTO_BSA_RSA: @@ -577,50 +574,88 @@ TALER_EXCHANGE_melt ( TALER_denom_ewv_rsa_singleton ()); break; case GNUNET_CRYPTO_BSA_CS: - nks[nks_off].pk = fresh_pk; - nks[nks_off].cnc_num = i; - nks_off++; + mh->no_blinding_seed = false; break; } } mh->keys = TALER_EXCHANGE_keys_incref (keys); - if (0 != nks_off) + return mh; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_melt_start ( + struct TALER_EXCHANGE_PostMeltHandle *mh, + TALER_EXCHANGE_PostMeltCallback melt_cb, + TALER_EXCHANGE_POST_MELT_RESULT_CLOSURE *melt_cb_cls) +{ + mh->melt_cb = melt_cb; + mh->melt_cb_cls = melt_cb_cls; + + if (! mh->no_blinding_seed) { - mh->no_blinding_seed = false; + struct TALER_EXCHANGE_NonceKey nks[GNUNET_NZL ( + mh->rd->num_fresh_denom_pubs)]; + unsigned int nks_off = 0; + + for (unsigned int i = 0; i < mh->rd->num_fresh_denom_pubs; i++) + { + const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = + &mh->rd->fresh_denom_pubs[i]; + + if (GNUNET_CRYPTO_BSA_CS == + fresh_pk->key.bsign_pub_key->cipher) + { + nks[nks_off].pk = fresh_pk; + nks[nks_off].cnc_num = i; + nks_off++; + } + } TALER_cs_refresh_seed_to_blinding_seed ( - rms, + &mh->rms, &mh->md.melted_coin.coin_priv, &mh->blinding_seed); - mh->bpr = TALER_EXCHANGE_blinding_prepare_for_melt (ctx, - url, - &mh->blinding_seed, - nks_off, - nks, - &blinding_prepare_cb, - mh); + mh->bpr = TALER_EXCHANGE_post_blinding_prepare_for_melt_create ( + mh->cctx, + mh->exchange_url, + &mh->blinding_seed, + nks_off, + nks); if (NULL == mh->bpr) { GNUNET_break (0); - TALER_EXCHANGE_melt_cancel (mh); - return NULL; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } - return mh; + { + enum TALER_ErrorCode ec; + + ec = TALER_EXCHANGE_post_blinding_prepare_start (mh->bpr, + &blinding_prepare_cb, + mh); + if (TALER_EC_NONE != ec) + { + GNUNET_break (0); + TALER_EXCHANGE_post_blinding_prepare_cancel (mh->bpr); + mh->bpr = NULL; + return ec; + } + } + return TALER_EC_NONE; } if (GNUNET_OK != start_melt (mh)) { GNUNET_break (0); - TALER_EXCHANGE_melt_cancel (mh); - return NULL; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } - return mh; + return TALER_EC_NONE; } void -TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh) +TALER_EXCHANGE_post_melt_cancel (struct TALER_EXCHANGE_PostMeltHandle *mh) { - for (unsigned int i = 0; i<mh->rd->num_fresh_denom_pubs; i++) + for (unsigned int i = 0; i < mh->rd->num_fresh_denom_pubs; i++) TALER_denom_ewv_free (&mh->melt_blinding_values[i]); if (NULL != mh->job) { @@ -629,7 +664,7 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh) } if (NULL != mh->bpr) { - TALER_EXCHANGE_blinding_prepare_cancel (mh->bpr); + TALER_EXCHANGE_post_blinding_prepare_cancel (mh->bpr); mh->bpr = NULL; } TALER_EXCHANGE_free_melt_data (&mh->md); /* does not free 'md' itself */ diff --git a/src/lib/exchange_api_post-purses-PURSE_PUB-create.c b/src/lib/exchange_api_post-purses-PURSE_PUB-create.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022-2023 Taler Systems SA + Copyright (C) 2022-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -55,6 +55,11 @@ struct Deposit struct TALER_DenominationHashP h_denom_pub; /** + * Signature proving the validity of the coin. + */ + struct TALER_DenominationSignature denom_sig; + + /** * Age restriction hash for the coin. */ struct TALER_AgeCommitmentHashP ahac; @@ -63,35 +68,51 @@ struct Deposit * How much did we say the coin contributed. */ struct TALER_Amount contribution; + + /** + * Age attestation for this coin. Valid if @e have_age. + */ + struct TALER_AgeAttestationP attest; + + /** + * True if this coin uses age attestation. + */ + bool have_age; + }; /** * @brief A purse create with deposit handle */ -struct TALER_EXCHANGE_PurseCreateDepositHandle +struct TALER_EXCHANGE_PostPursesCreateHandle { /** - * The keys of the exchange this request handle will use + * The curl context for this request. */ - struct TALER_EXCHANGE_Keys *keys; + struct GNUNET_CURL_Context *ctx; /** - * The url for this request. + * The base URL of the exchange. */ - char *url; + char *base_url; /** - * The base URL of the exchange. + * The keys of the exchange this request handle will use + */ + struct TALER_EXCHANGE_Keys *keys; + + /** + * The url for this request, set during _start. */ - char *exchange_url; + char *url; /** * Context for #TEH_curl_easy_post(). Keeps the data that must * persist for Curl to make the upload. */ - struct TALER_CURL_PostContext ctx; + struct TALER_CURL_PostContext post_ctx; /** * Handle for the request. @@ -101,12 +122,12 @@ struct TALER_EXCHANGE_PurseCreateDepositHandle /** * Function to call with the result. */ - TALER_EXCHANGE_PurseCreateDepositCallback cb; + TALER_EXCHANGE_PostPursesCreateCallback cb; /** * Closure for @a cb. */ - void *cb_cls; + TALER_EXCHANGE_POST_PURSES_CREATE_RESULT_CLOSURE *cb_cls; /** * Expected value in the purse after fees. @@ -124,12 +145,37 @@ struct TALER_EXCHANGE_PurseCreateDepositHandle struct TALER_PurseMergePublicKeyP merge_pub; /** + * Private key of the purse which we are creating. + */ + struct TALER_PurseContractPrivateKeyP purse_priv; + + /** + * Private key for the merge operation. + */ + struct TALER_PurseMergePrivateKeyP merge_priv; + + /** + * Private key to decrypt the contract. + */ + struct TALER_ContractDiffiePrivateP contract_priv; + + /** + * Contract terms for the payment. + */ + json_t *contract_terms; + + /** + * Minimum age, as per @e contract_terms. + */ + uint32_t min_age; + + /** * Public key of the purse. */ struct TALER_PurseContractPublicKeyP purse_pub; /** - * Signature with the purse key on the request. + * Signature for purse creation. */ struct TALER_PurseContractSignatureP purse_sig; @@ -153,14 +199,24 @@ struct TALER_EXCHANGE_PurseCreateDepositHandle */ unsigned int num_deposits; + struct + { + + /** + * Whether we are uploading a contract. + */ + bool upload_contract; + + } options; + }; /** * Function called when we're done processing the - * HTTP /deposit request. + * HTTP /purses/$PID/create request. * - * @param cls the `struct TALER_EXCHANGE_DepositHandle` + * @param cls the `struct TALER_EXCHANGE_PostPursesCreateHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -169,9 +225,9 @@ handle_purse_create_deposit_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_PurseCreateDepositHandle *pch = cls; + struct TALER_EXCHANGE_PostPursesCreateHandle *pch = cls; const json_t *j = response; - struct TALER_EXCHANGE_PurseCreateDepositResponse dr = { + struct TALER_EXCHANGE_PostPursesCreateResponse dr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; @@ -237,6 +293,8 @@ handle_purse_create_deposit_finished (void *cls, dr.hr.ec = TALER_EC_EXCHANGE_PURSE_CREATE_EXCHANGE_SIGNATURE_INVALID; break; } + dr.details.ok.exchange_pub = exchange_pub; + dr.details.ok.exchange_sig = exchange_sig; } break; case MHD_HTTP_BAD_REQUEST: @@ -281,7 +339,7 @@ handle_purse_create_deposit_finished (void *cls, checked in the GET /coins/$COIN_PUB handler */ break; case TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY: - // FIXME #7267: write check (add to exchange_api_common! */ + // FIXME #7267: write check (add to exchange_api_common!) */ break; case TALER_EC_EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA: { @@ -294,7 +352,7 @@ handle_purse_create_deposit_finished (void *cls, if (GNUNET_OK != TALER_EXCHANGE_check_purse_coin_conflict_ ( &pch->purse_pub, - pch->exchange_url, + pch->base_url, j, &h_denom_pub, &phac, @@ -347,6 +405,7 @@ handle_purse_create_deposit_finished (void *cls, break; } } + /* fall-through */ case TALER_EC_EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA: if (GNUNET_OK != TALER_EXCHANGE_check_purse_econtract_conflict_ ( @@ -362,7 +421,7 @@ handle_purse_create_deposit_finished (void *cls, break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected error code %d for conflcting deposit\n", + "Unexpected error code %d for conflicting deposit\n", dr.hr.ec); GNUNET_break_op (0); dr.hr.http_status = 0; @@ -395,14 +454,18 @@ handle_purse_create_deposit_finished (void *cls, GNUNET_break_op (0); break; } - pch->cb (pch->cb_cls, - &dr); - TALER_EXCHANGE_purse_create_with_deposit_cancel (pch); + if (NULL != pch->cb) + { + pch->cb (pch->cb_cls, + &dr); + pch->cb = NULL; + } + TALER_EXCHANGE_post_purses_create_cancel (pch); } -struct TALER_EXCHANGE_PurseCreateDepositHandle * -TALER_EXCHANGE_purse_create_with_deposit ( +struct TALER_EXCHANGE_PostPursesCreateHandle * +TALER_EXCHANGE_post_purses_create_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, @@ -411,21 +474,17 @@ TALER_EXCHANGE_purse_create_with_deposit ( const struct TALER_ContractDiffiePrivateP *contract_priv, const json_t *contract_terms, unsigned int num_deposits, - const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits], - bool upload_contract, - TALER_EXCHANGE_PurseCreateDepositCallback cb, - void *cb_cls) + const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits]) { - struct TALER_EXCHANGE_PurseCreateDepositHandle *pch; - json_t *create_obj; - json_t *deposit_arr; - CURL *eh; - char arg_str[sizeof (pch->purse_pub) * 2 + 32]; - uint32_t min_age = 0; - - pch = GNUNET_new (struct TALER_EXCHANGE_PurseCreateDepositHandle); - pch->cb = cb; - pch->cb_cls = cb_cls; + struct TALER_EXCHANGE_PostPursesCreateHandle *pch; + + pch = GNUNET_new (struct TALER_EXCHANGE_PostPursesCreateHandle); + pch->ctx = ctx; + pch->base_url = GNUNET_strdup (url); + pch->purse_priv = *purse_priv; + pch->merge_priv = *merge_priv; + pch->contract_priv = *contract_priv; + pch->contract_terms = json_incref ((json_t *) contract_terms); { struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_timestamp ("pay_deadline", @@ -434,7 +493,7 @@ TALER_EXCHANGE_purse_create_with_deposit ( &pch->purse_value_after_fees), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_uint32 ("minimum_age", - &min_age), + &pch->min_age), NULL), GNUNET_JSON_spec_end () }; @@ -445,6 +504,8 @@ TALER_EXCHANGE_purse_create_with_deposit ( NULL, NULL)) { GNUNET_break (0); + GNUNET_free (pch->base_url); + GNUNET_free (pch); return NULL; } } @@ -453,41 +514,17 @@ TALER_EXCHANGE_purse_create_with_deposit ( &pch->h_contract_terms)) { GNUNET_break (0); + GNUNET_free (pch->base_url); + GNUNET_free (pch); return NULL; } GNUNET_CRYPTO_eddsa_key_get_public (&purse_priv->eddsa_priv, &pch->purse_pub.eddsa_pub); - { - char pub_str[sizeof (pch->purse_pub) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &pch->purse_pub, - sizeof (pch->purse_pub), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "purses/%s/create", - pub_str); - } GNUNET_CRYPTO_eddsa_key_get_public (&merge_priv->eddsa_priv, &pch->merge_pub.eddsa_pub); - pch->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == pch->url) - { - GNUNET_break (0); - GNUNET_free (pch); - return NULL; - } pch->num_deposits = num_deposits; pch->deposits = GNUNET_new_array (num_deposits, struct Deposit); - deposit_arr = json_array (); - GNUNET_assert (NULL != deposit_arr); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Signing with URL `%s'\n", url); @@ -496,33 +533,30 @@ TALER_EXCHANGE_purse_create_with_deposit ( const struct TALER_EXCHANGE_PurseDeposit *deposit = &deposits[i]; const struct TALER_AgeCommitmentProof *acp = deposit->age_commitment_proof; struct Deposit *d = &pch->deposits[i]; - json_t *jdeposit; - struct TALER_AgeCommitmentHashP *aghp = NULL; - struct TALER_AgeAttestationP attest; - struct TALER_AgeAttestationP *attestp = NULL; if (NULL != acp) { TALER_age_commitment_hash (&acp->commitment, &d->ahac); - aghp = &d->ahac; + d->have_age = true; if (GNUNET_OK != TALER_age_commitment_attest (acp, - min_age, - &attest)) + pch->min_age, + &d->attest)) { GNUNET_break (0); GNUNET_array_grow (pch->deposits, pch->num_deposits, 0); - GNUNET_free (pch->url); - json_decref (deposit_arr); + GNUNET_free (pch->base_url); GNUNET_free (pch); return NULL; } } d->contribution = deposit->amount; d->h_denom_pub = deposit->h_denom_pub; + TALER_denom_sig_copy (&d->denom_sig, + &deposit->denom_sig); GNUNET_CRYPTO_eddsa_key_get_public (&deposit->coin_priv.eddsa_priv, &d->coin_pub.eddsa_pub); TALER_wallet_purse_deposit_sign ( @@ -533,6 +567,63 @@ TALER_EXCHANGE_purse_create_with_deposit ( &d->ahac, &deposit->coin_priv, &d->coin_sig); + } + pch->keys = TALER_EXCHANGE_keys_incref (keys); + return pch; +} + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_post_purses_create_set_options_ ( + struct TALER_EXCHANGE_PostPursesCreateHandle *ppch, + unsigned int num_options, + const struct TALER_EXCHANGE_PostPursesCreateOptionValue options[]) +{ + for (unsigned int i = 0; i < num_options; i++) + { + const struct TALER_EXCHANGE_PostPursesCreateOptionValue *opt = &options[i]; + + switch (opt->option) + { + case TALER_EXCHANGE_POST_PURSES_CREATE_OPTION_END: + return GNUNET_OK; + case TALER_EXCHANGE_POST_PURSES_CREATE_OPTION_UPLOAD_CONTRACT: + ppch->options.upload_contract = true; + break; + } + } + return GNUNET_OK; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_purses_create_start ( + struct TALER_EXCHANGE_PostPursesCreateHandle *pch, + TALER_EXCHANGE_PostPursesCreateCallback cb, + TALER_EXCHANGE_POST_PURSES_CREATE_RESULT_CLOSURE *cb_cls) +{ + char arg_str[sizeof (pch->purse_pub) * 2 + 32]; + CURL *eh; + json_t *deposit_arr; + json_t *body; + + pch->cb = cb; + pch->cb_cls = cb_cls; + deposit_arr = json_array (); + GNUNET_assert (NULL != deposit_arr); + + for (unsigned int i = 0; i<pch->num_deposits; i++) + { + struct Deposit *d = &pch->deposits[i]; + struct TALER_AgeCommitmentHashP *aghp = NULL; + struct TALER_AgeAttestationP *attestp = NULL; + json_t *jdeposit; + + if (d->have_age) + { + aghp = &d->ahac; + attestp = &d->attest; + } jdeposit = GNUNET_JSON_PACK ( GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_data_auto ("h_age_commitment", @@ -541,11 +632,11 @@ TALER_EXCHANGE_purse_create_with_deposit ( GNUNET_JSON_pack_data_auto ("age_attestation", attestp)), TALER_JSON_pack_amount ("amount", - &deposit->amount), + &d->contribution), GNUNET_JSON_pack_data_auto ("denom_pub_hash", - &deposit->h_denom_pub), + &d->h_denom_pub), TALER_JSON_pack_denom_sig ("ub_sig", - &deposit->denom_sig), + &d->denom_sig), GNUNET_JSON_pack_data_auto ("coin_sig", &d->coin_sig), GNUNET_JSON_pack_data_auto ("coin_pub", @@ -553,38 +644,44 @@ TALER_EXCHANGE_purse_create_with_deposit ( GNUNET_assert (0 == json_array_append_new (deposit_arr, jdeposit)); + + } + + if (pch->options.upload_contract) + { + TALER_CRYPTO_contract_encrypt_for_merge ( + &pch->purse_pub, + &pch->contract_priv, + &pch->merge_priv, + pch->contract_terms, + &pch->econtract.econtract, + &pch->econtract.econtract_size); + GNUNET_CRYPTO_ecdhe_key_get_public ( + &pch->contract_priv.ecdhe_priv, + &pch->econtract.contract_pub.ecdhe_pub); + TALER_wallet_econtract_upload_sign ( + pch->econtract.econtract, + pch->econtract.econtract_size, + &pch->econtract.contract_pub, + &pch->purse_priv, + &pch->econtract.econtract_sig); } TALER_wallet_purse_create_sign (pch->purse_expiration, &pch->h_contract_terms, &pch->merge_pub, - min_age, + pch->min_age, &pch->purse_value_after_fees, - purse_priv, + &pch->purse_priv, &pch->purse_sig); - if (upload_contract) - { - TALER_CRYPTO_contract_encrypt_for_merge (&pch->purse_pub, - contract_priv, - merge_priv, - contract_terms, - &pch->econtract.econtract, - &pch->econtract.econtract_size); - GNUNET_CRYPTO_ecdhe_key_get_public (&contract_priv->ecdhe_priv, - &pch->econtract.contract_pub.ecdhe_pub); - TALER_wallet_econtract_upload_sign (pch->econtract.econtract, - pch->econtract.econtract_size, - &pch->econtract.contract_pub, - purse_priv, - &pch->econtract.econtract_sig); - } - create_obj = GNUNET_JSON_PACK ( + + body = GNUNET_JSON_PACK ( TALER_JSON_pack_amount ("amount", &pch->purse_value_after_fees), GNUNET_JSON_pack_uint64 ("min_age", - min_age), + pch->min_age), GNUNET_JSON_pack_allow_null ( TALER_JSON_pack_econtract ("econtract", - upload_contract + pch->options.upload_contract ? &pch->econtract : NULL)), GNUNET_JSON_pack_data_auto ("purse_sig", @@ -597,60 +694,90 @@ TALER_EXCHANGE_purse_create_with_deposit ( pch->purse_expiration), GNUNET_JSON_pack_array_steal ("deposits", deposit_arr)); - GNUNET_assert (NULL != create_obj); + if (NULL == body) + { + GNUNET_break (0); + return TALER_EC_GENERIC_CURL_ALLOCATION_FAILURE; + } + + { + char pub_str[sizeof (pch->purse_pub) * 2]; + char *end; + + end = GNUNET_STRINGS_data_to_string ( + &pch->purse_pub, + sizeof (pch->purse_pub), + pub_str, + sizeof (pub_str)); + *end = '\0'; + GNUNET_snprintf (arg_str, + sizeof (arg_str), + "purses/%s/create", + pub_str); + } + pch->url = TALER_url_join (pch->base_url, + arg_str, + NULL); + if (NULL == pch->url) + { + GNUNET_break (0); + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "URL for purse create with deposit: `%s'\n", + pch->url); eh = TALER_EXCHANGE_curl_easy_get_ (pch->url); if ( (NULL == eh) || (GNUNET_OK != - TALER_curl_easy_post (&pch->ctx, + TALER_curl_easy_post (&pch->post_ctx, eh, - create_obj)) ) + body)) ) { GNUNET_break (0); if (NULL != eh) curl_easy_cleanup (eh); - json_decref (create_obj); - GNUNET_free (pch->econtract.econtract); - GNUNET_array_grow (pch->deposits, - pch->num_deposits, - 0); - GNUNET_free (pch->url); - GNUNET_free (pch); - return NULL; + json_decref (body); + return TALER_EC_GENERIC_CURL_ALLOCATION_FAILURE; } - json_decref (create_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for purse create with deposit: `%s'\n", - pch->url); - pch->keys = TALER_EXCHANGE_keys_incref (keys); - pch->exchange_url = GNUNET_strdup (url); - pch->job = GNUNET_CURL_job_add2 (ctx, + json_decref (body); + pch->job = GNUNET_CURL_job_add2 (pch->ctx, eh, - pch->ctx.headers, + pch->post_ctx.headers, &handle_purse_create_deposit_finished, pch); - return pch; + if (NULL == pch->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_purse_create_with_deposit_cancel ( - struct TALER_EXCHANGE_PurseCreateDepositHandle *pch) +TALER_EXCHANGE_post_purses_create_cancel ( + struct TALER_EXCHANGE_PostPursesCreateHandle *pch) { if (NULL != pch->job) { GNUNET_CURL_job_cancel (pch->job); pch->job = NULL; } + json_decref (pch->contract_terms); GNUNET_free (pch->econtract.econtract); - GNUNET_free (pch->exchange_url); + GNUNET_free (pch->base_url); GNUNET_free (pch->url); + + for (unsigned int i = 0; i<pch->num_deposits; i++) + { + struct Deposit *d = &pch->deposits[i]; + + TALER_denom_sig_free (&d->denom_sig); + } GNUNET_array_grow (pch->deposits, pch->num_deposits, 0); TALER_EXCHANGE_keys_decref (pch->keys); - TALER_curl_easy_post_finished (&pch->ctx); + TALER_curl_easy_post_finished (&pch->post_ctx); GNUNET_free (pch); } -/* end of exchange_api_purse_create_with_deposit.c */ +/* end of exchange_api_post-purses-PURSE_PUB-create.c */ diff --git a/src/lib/exchange_api_post-purses-PURSE_PUB-deposit.c b/src/lib/exchange_api_post-purses-PURSE_PUB-deposit.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022-2023 Taler Systems SA + Copyright (C) 2022-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -67,31 +67,30 @@ struct Coin /** - * @brief A purse create with deposit handle + * @brief A purse deposit handle */ -struct TALER_EXCHANGE_PurseDepositHandle +struct TALER_EXCHANGE_PostPursesDepositHandle { /** - * The keys of the exchange this request handle will use + * Reference to the execution context. */ - struct TALER_EXCHANGE_Keys *keys; + struct GNUNET_CURL_Context *ctx; /** - * The url for this request. + * The base url of the exchange we are talking to. */ - char *url; + char *base_url; /** - * The base url of the exchange we are talking to. + * The full URL for this request, set during _start. */ - char *base_url; + char *url; /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. + * Minor context that holds body and headers. */ - struct TALER_CURL_PostContext ctx; + struct TALER_CURL_PostContext post_ctx; /** * Handle for the request. @@ -101,12 +100,17 @@ struct TALER_EXCHANGE_PurseDepositHandle /** * Function to call with the result. */ - TALER_EXCHANGE_PurseDepositCallback cb; + TALER_EXCHANGE_PostPursesDepositCallback cb; /** * Closure for @a cb. */ - void *cb_cls; + TALER_EXCHANGE_POST_PURSES_DEPOSIT_RESULT_CLOSURE *cb_cls; + + /** + * The keys of the exchange this request handle will use. + */ + struct TALER_EXCHANGE_Keys *keys; /** * Public key of the purse. @@ -122,6 +126,12 @@ struct TALER_EXCHANGE_PurseDepositHandle * Number of coins we are depositing. */ unsigned int num_deposits; + + /** + * Pre-built request body. + */ + json_t *body; + }; @@ -129,7 +139,7 @@ struct TALER_EXCHANGE_PurseDepositHandle * Function called when we're done processing the * HTTP /purses/$PID/deposit request. * - * @param cls the `struct TALER_EXCHANGE_PurseDepositHandle` + * @param cls the `struct TALER_EXCHANGE_PostPursesDepositHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -138,9 +148,9 @@ handle_purse_deposit_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_PurseDepositHandle *pch = cls; + struct TALER_EXCHANGE_PostPursesDepositHandle *pch = cls; const json_t *j = response; - struct TALER_EXCHANGE_PurseDepositResponse dr = { + struct TALER_EXCHANGE_PostPursesDepositResponse dr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; @@ -337,12 +347,12 @@ handle_purse_deposit_finished (void *cls, dr.hr.hint = TALER_ErrorCode_get_hint (dr.hr.ec); pch->cb (pch->cb_cls, &dr); - TALER_EXCHANGE_purse_deposit_cancel (pch); + TALER_EXCHANGE_post_purses_deposit_cancel (pch); } -struct TALER_EXCHANGE_PurseDepositHandle * -TALER_EXCHANGE_purse_deposit ( +struct TALER_EXCHANGE_PostPursesDepositHandle * +TALER_EXCHANGE_post_purses_deposit_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, @@ -350,15 +360,10 @@ TALER_EXCHANGE_purse_deposit ( const struct TALER_PurseContractPublicKeyP *purse_pub, uint8_t min_age, unsigned int num_deposits, - const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits], - TALER_EXCHANGE_PurseDepositCallback cb, - void *cb_cls) + const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits]) { - struct TALER_EXCHANGE_PurseDepositHandle *pch; - json_t *create_obj; + struct TALER_EXCHANGE_PostPursesDepositHandle *pch; json_t *deposit_arr; - CURL *eh; - char arg_str[sizeof (pch->purse_pub) * 2 + 32]; // FIXME: use purse_exchange_url for wad transfers (#7271) (void) purse_exchange_url; @@ -367,40 +372,17 @@ TALER_EXCHANGE_purse_deposit ( GNUNET_break (0); return NULL; } - pch = GNUNET_new (struct TALER_EXCHANGE_PurseDepositHandle); - pch->purse_pub = *purse_pub; - pch->cb = cb; - pch->cb_cls = cb_cls; - { - char pub_str[sizeof (pch->purse_pub) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &pch->purse_pub, - sizeof (pch->purse_pub), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "purses/%s/deposit", - pub_str); - } - pch->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == pch->url) - { - GNUNET_break (0); - GNUNET_free (pch); - return NULL; - } - deposit_arr = json_array (); - GNUNET_assert (NULL != deposit_arr); + pch = GNUNET_new (struct TALER_EXCHANGE_PostPursesDepositHandle); + pch->ctx = ctx; pch->base_url = GNUNET_strdup (url); + pch->keys = TALER_EXCHANGE_keys_incref (keys); + pch->purse_pub = *purse_pub; pch->num_deposits = num_deposits; pch->coins = GNUNET_new_array (num_deposits, struct Coin); + // FIXME: move JSON construction into _start() function. + deposit_arr = json_array (); + GNUNET_assert (NULL != deposit_arr); for (unsigned int i = 0; i<num_deposits; i++) { const struct TALER_EXCHANGE_PurseDeposit *deposit = &deposits[i]; @@ -425,7 +407,7 @@ TALER_EXCHANGE_purse_deposit ( json_decref (deposit_arr); GNUNET_free (pch->base_url); GNUNET_free (pch->coins); - GNUNET_free (pch->url); + TALER_EXCHANGE_keys_decref (pch->keys); GNUNET_free (pch); return NULL; } @@ -464,57 +446,92 @@ TALER_EXCHANGE_purse_deposit ( json_array_append_new (deposit_arr, jdeposit)); } - create_obj = GNUNET_JSON_PACK ( + pch->body = GNUNET_JSON_PACK ( GNUNET_JSON_pack_array_steal ("deposits", deposit_arr)); - GNUNET_assert (NULL != create_obj); + GNUNET_assert (NULL != pch->body); + return pch; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_purses_deposit_start ( + struct TALER_EXCHANGE_PostPursesDepositHandle *pch, + TALER_EXCHANGE_PostPursesDepositCallback cb, + TALER_EXCHANGE_POST_PURSES_DEPOSIT_RESULT_CLOSURE *cb_cls) +{ + CURL *eh; + char arg_str[sizeof (pch->purse_pub) * 2 + 32]; + + pch->cb = cb; + pch->cb_cls = cb_cls; + { + char pub_str[sizeof (pch->purse_pub) * 2]; + char *end; + + end = GNUNET_STRINGS_data_to_string ( + &pch->purse_pub, + sizeof (pch->purse_pub), + pub_str, + sizeof (pub_str)); + *end = '\0'; + GNUNET_snprintf (arg_str, + sizeof (arg_str), + "purses/%s/deposit", + pub_str); + } + pch->url = TALER_url_join (pch->base_url, + arg_str, + NULL); + if (NULL == pch->url) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not construct request URL.\n"); + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "URL for purse deposit: `%s'\n", + pch->url); eh = TALER_EXCHANGE_curl_easy_get_ (pch->url); if ( (NULL == eh) || (GNUNET_OK != - TALER_curl_easy_post (&pch->ctx, + TALER_curl_easy_post (&pch->post_ctx, eh, - create_obj)) ) + pch->body)) ) { GNUNET_break (0); 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; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } - json_decref (create_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for purse deposit: `%s'\n", - pch->url); - pch->keys = TALER_EXCHANGE_keys_incref (keys); - pch->job = GNUNET_CURL_job_add2 (ctx, + pch->job = GNUNET_CURL_job_add2 (pch->ctx, eh, - pch->ctx.headers, + pch->post_ctx.headers, &handle_purse_deposit_finished, pch); - return pch; + if (NULL == pch->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_purse_deposit_cancel ( - struct TALER_EXCHANGE_PurseDepositHandle *pch) +TALER_EXCHANGE_post_purses_deposit_cancel ( + struct TALER_EXCHANGE_PostPursesDepositHandle *pch) { if (NULL != pch->job) { GNUNET_CURL_job_cancel (pch->job); pch->job = NULL; } + TALER_curl_easy_post_finished (&pch->post_ctx); GNUNET_free (pch->base_url); GNUNET_free (pch->url); GNUNET_free (pch->coins); + json_decref (pch->body); TALER_EXCHANGE_keys_decref (pch->keys); - TALER_curl_easy_post_finished (&pch->ctx); GNUNET_free (pch); } -/* end of exchange_api_purse_deposit.c */ +/* end of exchange_api_post-purses-PURSE_PUB-deposit.c */ diff --git a/src/lib/exchange_api_post-purses-PURSE_PUB-merge.c b/src/lib/exchange_api_post-purses-PURSE_PUB-merge.c @@ -37,16 +37,26 @@ /** * @brief A purse merge with deposit handle */ -struct TALER_EXCHANGE_AccountMergeHandle +struct TALER_EXCHANGE_PostPursesMergeHandle { /** + * The curl context for this request. + */ + struct GNUNET_CURL_Context *ctx; + + /** + * The base URL of the exchange. + */ + char *base_url; + + /** * The keys of the exchange this request handle will use */ struct TALER_EXCHANGE_Keys *keys; /** - * The url for this request. + * The url for this request, set during _start. */ char *url; @@ -54,7 +64,7 @@ struct TALER_EXCHANGE_AccountMergeHandle * Context for #TEH_curl_easy_post(). Keeps the data that must * persist for Curl to make the upload. */ - struct TALER_CURL_PostContext ctx; + struct TALER_CURL_PostContext post_ctx; /** * Handle for the request. @@ -64,12 +74,12 @@ struct TALER_EXCHANGE_AccountMergeHandle /** * Function to call with the result. */ - TALER_EXCHANGE_AccountMergeCallback cb; + TALER_EXCHANGE_PostPursesMergeCallback cb; /** * Closure for @a cb. */ - void *cb_cls; + TALER_EXCHANGE_POST_PURSES_MERGE_RESULT_CLOSURE *cb_cls; /** * Base URL of the provider hosting the @e reserve_pub. @@ -97,7 +107,7 @@ struct TALER_EXCHANGE_AccountMergeHandle struct TALER_PurseContractPublicKeyP purse_pub; /** - * Hash over the purse's contrac terms. + * Hash over the purse's contract terms. */ struct TALER_PrivateContractHashP h_contract_terms; @@ -116,6 +126,11 @@ struct TALER_EXCHANGE_AccountMergeHandle */ struct TALER_ReserveSignatureP reserve_sig; + /** + * The JSON body to post, built during _create and posted during _start. + */ + json_t *body; + }; @@ -123,7 +138,7 @@ struct TALER_EXCHANGE_AccountMergeHandle * Function called when we're done processing the * HTTP /purse/$PID/merge request. * - * @param cls the `struct TALER_EXCHANGE_AccountMergeHandle` + * @param cls the `struct TALER_EXCHANGE_PostPursesMergeHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -132,9 +147,9 @@ handle_purse_merge_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_AccountMergeHandle *pch = cls; + struct TALER_EXCHANGE_PostPursesMergeHandle *pch = cls; const json_t *j = response; - struct TALER_EXCHANGE_AccountMergeResponse dr = { + struct TALER_EXCHANGE_PostPursesMergeResponse dr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code, .reserve_sig = &pch->reserve_sig @@ -292,14 +307,18 @@ handle_purse_merge_finished (void *cls, GNUNET_break_op (0); break; } - pch->cb (pch->cb_cls, - &dr); - TALER_EXCHANGE_account_merge_cancel (pch); + if (NULL != pch->cb) + { + pch->cb (pch->cb_cls, + &dr); + pch->cb = NULL; + } + TALER_EXCHANGE_post_purses_merge_cancel (pch); } -struct TALER_EXCHANGE_AccountMergeHandle * -TALER_EXCHANGE_account_merge ( +struct TALER_EXCHANGE_PostPursesMergeHandle * +TALER_EXCHANGE_post_purses_merge_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, @@ -311,20 +330,15 @@ TALER_EXCHANGE_account_merge ( uint8_t min_age, const struct TALER_Amount *purse_value_after_fees, struct GNUNET_TIME_Timestamp purse_expiration, - struct GNUNET_TIME_Timestamp merge_timestamp, - TALER_EXCHANGE_AccountMergeCallback cb, - void *cb_cls) + struct GNUNET_TIME_Timestamp merge_timestamp) { - struct TALER_EXCHANGE_AccountMergeHandle *pch; - json_t *merge_obj; - CURL *eh; - char arg_str[sizeof (pch->purse_pub) * 2 + 32]; + struct TALER_EXCHANGE_PostPursesMergeHandle *pch; struct TALER_NormalizedPayto reserve_url; - pch = GNUNET_new (struct TALER_EXCHANGE_AccountMergeHandle); + pch = GNUNET_new (struct TALER_EXCHANGE_PostPursesMergeHandle); + pch->ctx = ctx; + pch->base_url = GNUNET_strdup (url); pch->merge_priv = *merge_priv; - pch->cb = cb; - pch->cb_cls = cb_cls; pch->purse_pub = *purse_pub; pch->h_contract_terms = *h_contract_terms; pch->purse_expiration = purse_expiration; @@ -336,38 +350,13 @@ TALER_EXCHANGE_account_merge ( GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, &pch->reserve_pub.eddsa_pub); - { - char pub_str[sizeof (*purse_pub) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - purse_pub, - sizeof (*purse_pub), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "purses/%s/merge", - pub_str); - } reserve_url = TALER_reserve_make_payto (pch->provider_url, &pch->reserve_pub); if (NULL == reserve_url.normalized_payto) { GNUNET_break (0); GNUNET_free (pch->provider_url); - GNUNET_free (pch); - return NULL; - } - pch->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == pch->url) - { - GNUNET_break (0); - GNUNET_free (reserve_url.normalized_payto); - GNUNET_free (pch->provider_url); + GNUNET_free (pch->base_url); GNUNET_free (pch); return NULL; } @@ -393,7 +382,8 @@ TALER_EXCHANGE_account_merge ( reserve_priv, &pch->reserve_sig); } - merge_obj = GNUNET_JSON_PACK ( + // FIXME: move JSON construction into _start() function + pch->body = GNUNET_JSON_PACK ( TALER_JSON_pack_normalized_payto ("payto_uri", reserve_url), GNUNET_JSON_pack_data_auto ("merge_sig", @@ -402,41 +392,84 @@ TALER_EXCHANGE_account_merge ( &pch->reserve_sig), GNUNET_JSON_pack_timestamp ("merge_timestamp", merge_timestamp)); - GNUNET_assert (NULL != merge_obj); GNUNET_free (reserve_url.normalized_payto); - eh = TALER_EXCHANGE_curl_easy_get_ (pch->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&pch->ctx, - eh, - merge_obj)) ) + if (NULL == pch->body) { GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (merge_obj); GNUNET_free (pch->provider_url); - GNUNET_free (pch->url); + GNUNET_free (pch->base_url); GNUNET_free (pch); return NULL; } - json_decref (merge_obj); + pch->keys = TALER_EXCHANGE_keys_incref (keys); + return pch; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_purses_merge_start ( + struct TALER_EXCHANGE_PostPursesMergeHandle *pch, + TALER_EXCHANGE_PostPursesMergeCallback cb, + TALER_EXCHANGE_POST_PURSES_MERGE_RESULT_CLOSURE *cb_cls) +{ + char arg_str[sizeof (pch->purse_pub) * 2 + 32]; + CURL *eh; + + pch->cb = cb; + pch->cb_cls = cb_cls; + + { + char pub_str[sizeof (pch->purse_pub) * 2]; + char *end; + + end = GNUNET_STRINGS_data_to_string ( + &pch->purse_pub, + sizeof (pch->purse_pub), + pub_str, + sizeof (pub_str)); + *end = '\0'; + GNUNET_snprintf (arg_str, + sizeof (arg_str), + "purses/%s/merge", + pub_str); + } + pch->url = TALER_url_join (pch->base_url, + arg_str, + NULL); + if (NULL == pch->url) + { + GNUNET_break (0); + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for purse merge: `%s'\n", pch->url); - pch->keys = TALER_EXCHANGE_keys_incref (keys); - pch->job = GNUNET_CURL_job_add2 (ctx, + eh = TALER_EXCHANGE_curl_easy_get_ (pch->url); + if ( (NULL == eh) || + (GNUNET_OK != + TALER_curl_easy_post (&pch->post_ctx, + eh, + pch->body)) ) + { + GNUNET_break (0); + if (NULL != eh) + curl_easy_cleanup (eh); + return TALER_EC_GENERIC_CURL_ALLOCATION_FAILURE; + } + pch->job = GNUNET_CURL_job_add2 (pch->ctx, eh, - pch->ctx.headers, + pch->post_ctx.headers, &handle_purse_merge_finished, pch); - return pch; + if (NULL == pch->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_account_merge_cancel ( - struct TALER_EXCHANGE_AccountMergeHandle *pch) +TALER_EXCHANGE_post_purses_merge_cancel ( + struct TALER_EXCHANGE_PostPursesMergeHandle *pch) { if (NULL != pch->job) { @@ -444,11 +477,13 @@ TALER_EXCHANGE_account_merge_cancel ( pch->job = NULL; } GNUNET_free (pch->url); + GNUNET_free (pch->base_url); GNUNET_free (pch->provider_url); - TALER_curl_easy_post_finished (&pch->ctx); + TALER_curl_easy_post_finished (&pch->post_ctx); TALER_EXCHANGE_keys_decref (pch->keys); + json_decref (pch->body); GNUNET_free (pch); } -/* end of exchange_api_purse_merge.c */ +/* end of exchange_api_post-purses-PURSE_PUB-merge.c */ diff --git a/src/lib/exchange_api_post-recoup-refresh.c b/src/lib/exchange_api_post-recoup-refresh.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2017-2023 Taler Systems SA + Copyright (C) 2017-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -34,31 +34,25 @@ /** - * @brief A Recoup Handle + * @brief A Recoup-Refresh Handle */ -struct TALER_EXCHANGE_RecoupRefreshHandle +struct TALER_EXCHANGE_PostRecoupRefreshHandle { /** - * The keys of the exchange this request handle will use + * The base URL for this request. */ - struct TALER_EXCHANGE_Keys *keys; + char *base_url; /** - * The url for this request. + * The full URL for this request, set during _start. */ char *url; /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. - */ - struct TALER_CURL_PostContext ctx; - - /** - * Denomination key of the coin. + * Minor context that holds body and headers. */ - struct TALER_EXCHANGE_DenomPublicKey pk; + struct TALER_CURL_PostContext post_ctx; /** * Handle for the request. @@ -68,12 +62,22 @@ struct TALER_EXCHANGE_RecoupRefreshHandle /** * Function to call with the result. */ - TALER_EXCHANGE_RecoupRefreshResultCallback cb; + TALER_EXCHANGE_PostRecoupRefreshCallback cb; /** * Closure for @a cb. */ - void *cb_cls; + TALER_EXCHANGE_POST_RECOUP_REFRESH_RESULT_CLOSURE *cb_cls; + + /** + * Reference to the execution context. + */ + struct GNUNET_CURL_Context *ctx; + + /** + * The keys of the exchange this request handle will use. + */ + struct TALER_EXCHANGE_Keys *keys; /** * Public key of the coin we are trying to get paid back. @@ -81,9 +85,9 @@ struct TALER_EXCHANGE_RecoupRefreshHandle struct TALER_CoinSpendPublicKeyP coin_pub; /** - * Signature affirming the recoup-refresh operation. + * Pre-built request body. */ - struct TALER_CoinSpendSignatureP coin_sig; + json_t *body; }; @@ -91,17 +95,17 @@ struct TALER_EXCHANGE_RecoupRefreshHandle /** * Parse a recoup-refresh response. If it is valid, call the callback. * - * @param ph recoup handle + * @param ph recoup-refresh handle * @param json json reply with the signature * @return #GNUNET_OK if the signature is valid and we called the callback; * #GNUNET_SYSERR if not (callback must still be called) */ static enum GNUNET_GenericReturnValue process_recoup_response ( - const struct TALER_EXCHANGE_RecoupRefreshHandle *ph, + const struct TALER_EXCHANGE_PostRecoupRefreshHandle *ph, const json_t *json) { - struct TALER_EXCHANGE_RecoupRefreshResponse rrr = { + struct TALER_EXCHANGE_PostRecoupRefreshResponse rrr = { .hr.reply = json, .hr.http_status = MHD_HTTP_OK }; @@ -129,7 +133,7 @@ process_recoup_response ( * Function called when we're done processing the * HTTP /recoup-refresh request. * - * @param cls the `struct TALER_EXCHANGE_RecoupRefreshHandle` + * @param cls the `struct TALER_EXCHANGE_PostRecoupRefreshHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -138,9 +142,9 @@ handle_recoup_refresh_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_RecoupRefreshHandle *ph = cls; + struct TALER_EXCHANGE_PostRecoupRefreshHandle *ph = cls; const json_t *j = response; - struct TALER_EXCHANGE_RecoupRefreshResponse rrr = { + struct TALER_EXCHANGE_PostRecoupRefreshResponse rrr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; @@ -161,7 +165,7 @@ handle_recoup_refresh_finished (void *cls, rrr.hr.http_status = 0; break; } - TALER_EXCHANGE_recoup_refresh_cancel (ph); + TALER_EXCHANGE_post_recoup_refresh_cancel (ph); return; case MHD_HTTP_BAD_REQUEST: /* This should never happen, either us or the exchange is buggy @@ -203,7 +207,7 @@ handle_recoup_refresh_finished (void *cls, rrr.hr.ec = TALER_JSON_get_error_code (j); rrr.hr.hint = TALER_JSON_get_error_hint (j); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange recoup\n", + "Unexpected response code %u/%d for exchange recoup-refresh\n", (unsigned int) response_code, (int) rrr.hr.ec); GNUNET_break (0); @@ -211,46 +215,39 @@ handle_recoup_refresh_finished (void *cls, } ph->cb (ph->cb_cls, &rrr); - TALER_EXCHANGE_recoup_refresh_cancel (ph); + TALER_EXCHANGE_post_recoup_refresh_cancel (ph); } -#pragma message "TODO[oec]: rewrite TALER_EXCHANGE_RecoupRefreshHandle" -struct TALER_EXCHANGE_RecoupRefreshHandle * -TALER_EXCHANGE_recoup_refresh ( +struct TALER_EXCHANGE_PostRecoupRefreshHandle * +TALER_EXCHANGE_post_recoup_refresh_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_DenomPublicKey *pk, const struct TALER_DenominationSignature *denom_sig, - const struct TALER_ExchangeBlindingValues *blinding_values, + const struct TALER_ExchangeBlindingValues *exchange_vals, const struct TALER_PublicRefreshMasterSeedP *rms, const struct TALER_PlanchetMasterSecretP *ps, - unsigned int idx, - TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb, - void *recoup_cb_cls) + unsigned int idx) { - struct TALER_EXCHANGE_RecoupRefreshHandle *ph; + struct TALER_EXCHANGE_PostRecoupRefreshHandle *ph; struct TALER_DenominationHashP h_denom_pub; - json_t *recoup_obj; - CURL *eh; - char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; struct TALER_CoinSpendPrivateKeyP coin_priv; union GNUNET_CRYPTO_BlindingSecretP bks; + struct TALER_CoinSpendSignatureP coin_sig; - GNUNET_assert (NULL != recoup_cb); - ph = GNUNET_new (struct TALER_EXCHANGE_RecoupRefreshHandle); - ph->pk = *pk; - memset (&ph->pk.key, - 0, - sizeof (ph->pk.key)); /* zero out, as lifetime cannot be warranted */ - ph->cb = recoup_cb; - ph->cb_cls = recoup_cb_cls; + (void) rms; // FIXME: why did we pass this again? + (void) idx; // FIXME: why did we pass this again? + ph = GNUNET_new (struct TALER_EXCHANGE_PostRecoupRefreshHandle); + ph->ctx = ctx; + ph->base_url = GNUNET_strdup (url); + ph->keys = TALER_EXCHANGE_keys_incref (keys); TALER_planchet_setup_coin_priv (ps, - blinding_values, + exchange_vals, &coin_priv); TALER_planchet_blinding_secret_create (ps, - blinding_values, + exchange_vals, &bks); GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv, &ph->coin_pub.eddsa_pub); @@ -259,35 +256,47 @@ TALER_EXCHANGE_recoup_refresh ( TALER_wallet_recoup_refresh_sign (&h_denom_pub, &bks, &coin_priv, - &ph->coin_sig); - recoup_obj = GNUNET_JSON_PACK ( + &coin_sig); + ph->body = GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("denom_pub_hash", &h_denom_pub), TALER_JSON_pack_denom_sig ("denom_sig", denom_sig), TALER_JSON_pack_exchange_blinding_values ("ewv", - blinding_values), + exchange_vals), GNUNET_JSON_pack_data_auto ("coin_sig", - &ph->coin_sig), + &coin_sig), GNUNET_JSON_pack_data_auto ("coin_blind_key_secret", &bks)); - switch (denom_sig->unblinded_sig->cipher) { case GNUNET_CRYPTO_BSA_INVALID: - json_decref (recoup_obj); - GNUNET_break (0); + json_decref (ph->body); + GNUNET_free (ph->base_url); + TALER_EXCHANGE_keys_decref (ph->keys); GNUNET_free (ph); + GNUNET_break (0); return NULL; case GNUNET_CRYPTO_BSA_RSA: break; case GNUNET_CRYPTO_BSA_CS: - { - - } break; } + return ph; +} + +enum TALER_ErrorCode +TALER_EXCHANGE_post_recoup_refresh_start ( + struct TALER_EXCHANGE_PostRecoupRefreshHandle *ph, + TALER_EXCHANGE_PostRecoupRefreshCallback cb, + TALER_EXCHANGE_POST_RECOUP_REFRESH_RESULT_CLOSURE *cb_cls) +{ + CURL *eh; + char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; + + ph->cb = cb; + ph->cb_cls = cb_cls; { char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; char *end; @@ -303,59 +312,57 @@ TALER_EXCHANGE_recoup_refresh ( "coins/%s/recoup-refresh", pub_str); } - - ph->url = TALER_url_join (url, + ph->url = TALER_url_join (ph->base_url, arg_str, NULL); if (NULL == ph->url) { - json_decref (recoup_obj); - GNUNET_free (ph); - return NULL; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not construct request URL.\n"); + return TALER_EC_GENERIC_CONFIGURATION_INVALID; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "URL for recoup-refresh: `%s'\n", + ph->url); eh = TALER_EXCHANGE_curl_easy_get_ (ph->url); if ( (NULL == eh) || (GNUNET_OK != - TALER_curl_easy_post (&ph->ctx, + TALER_curl_easy_post (&ph->post_ctx, eh, - recoup_obj)) ) + ph->body)) ) { GNUNET_break (0); if (NULL != eh) curl_easy_cleanup (eh); - json_decref (recoup_obj); - GNUNET_free (ph->url); - GNUNET_free (ph); - return NULL; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } - json_decref (recoup_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for recoup-refresh: `%s'\n", - ph->url); - ph->keys = TALER_EXCHANGE_keys_incref (keys); - ph->job = GNUNET_CURL_job_add2 (ctx, + ph->job = GNUNET_CURL_job_add2 (ph->ctx, eh, - ph->ctx.headers, + ph->post_ctx.headers, &handle_recoup_refresh_finished, ph); - return ph; + if (NULL == ph->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_recoup_refresh_cancel ( - struct TALER_EXCHANGE_RecoupRefreshHandle *ph) +TALER_EXCHANGE_post_recoup_refresh_cancel ( + struct TALER_EXCHANGE_PostRecoupRefreshHandle *ph) { if (NULL != ph->job) { GNUNET_CURL_job_cancel (ph->job); ph->job = NULL; } + TALER_curl_easy_post_finished (&ph->post_ctx); GNUNET_free (ph->url); - TALER_curl_easy_post_finished (&ph->ctx); + GNUNET_free (ph->base_url); + json_decref (ph->body); TALER_EXCHANGE_keys_decref (ph->keys); GNUNET_free (ph); } -/* end of exchange_api_recoup_refresh.c */ +/* end of exchange_api_post-recoup-refresh.c */ diff --git a/src/lib/exchange_api_post-recoup-withdraw.c b/src/lib/exchange_api_post-recoup-withdraw.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2017-2023 Taler Systems SA + Copyright (C) 2017-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -36,55 +36,59 @@ /** * @brief A Recoup Handle */ -struct TALER_EXCHANGE_RecoupHandle +struct TALER_EXCHANGE_PostRecoupWithdrawHandle { /** - * The keys of the exchange this request handle will use + * The base URL for this request. */ - struct TALER_EXCHANGE_Keys *keys; + char *base_url; /** - * The url for this request. + * The full URL for this request, set during _start. */ char *url; /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. + * Minor context that holds body and headers. */ - struct TALER_CURL_PostContext ctx; + struct TALER_CURL_PostContext post_ctx; /** - * Denomination key of the coin. + * Handle for the request. */ - struct TALER_EXCHANGE_DenomPublicKey pk; + struct GNUNET_CURL_Job *job; /** - * Our signature requesting the recoup. + * Function to call with the result. */ - struct TALER_CoinSpendSignatureP coin_sig; + TALER_EXCHANGE_PostRecoupWithdrawCallback cb; /** - * Handle for the request. + * Closure for @a cb. */ - struct GNUNET_CURL_Job *job; + TALER_EXCHANGE_POST_RECOUP_WITHDRAW_RESULT_CLOSURE *cb_cls; /** - * Function to call with the result. + * Reference to the execution context. */ - TALER_EXCHANGE_RecoupResultCallback cb; + struct GNUNET_CURL_Context *ctx; /** - * Closure for @a cb. + * The keys of the exchange this request handle will use. */ - void *cb_cls; + struct TALER_EXCHANGE_Keys *keys; /** * Public key of the coin we are trying to get paid back. */ struct TALER_CoinSpendPublicKeyP coin_pub; + /** + * Pre-built request body. + */ + json_t *body; + }; @@ -97,10 +101,11 @@ struct TALER_EXCHANGE_RecoupHandle * #GNUNET_SYSERR if not (callback must still be called) */ static enum GNUNET_GenericReturnValue -process_recoup_response (const struct TALER_EXCHANGE_RecoupHandle *ph, - const json_t *json) +process_recoup_response ( + const struct TALER_EXCHANGE_PostRecoupWithdrawHandle *ph, + const json_t *json) { - struct TALER_EXCHANGE_RecoupResponse rr = { + struct TALER_EXCHANGE_PostRecoupWithdrawResponse rr = { .hr.reply = json, .hr.http_status = MHD_HTTP_OK }; @@ -128,7 +133,7 @@ process_recoup_response (const struct TALER_EXCHANGE_RecoupHandle *ph, * Function called when we're done processing the * HTTP /recoup request. * - * @param cls the `struct TALER_EXCHANGE_RecoupHandle` + * @param cls the `struct TALER_EXCHANGE_PostRecoupWithdrawHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -137,9 +142,9 @@ handle_recoup_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_RecoupHandle *ph = cls; + struct TALER_EXCHANGE_PostRecoupWithdrawHandle *ph = cls; const json_t *j = response; - struct TALER_EXCHANGE_RecoupResponse rr = { + struct TALER_EXCHANGE_PostRecoupWithdrawResponse rr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; @@ -160,7 +165,7 @@ handle_recoup_finished (void *cls, rr.hr.http_status = 0; break; } - TALER_EXCHANGE_recoup_cancel (ph); + TALER_EXCHANGE_post_recoup_withdraw_cancel (ph); return; case MHD_HTTP_BAD_REQUEST: /* This should never happen, either us or the exchange is buggy @@ -223,37 +228,36 @@ handle_recoup_finished (void *cls, } ph->cb (ph->cb_cls, &rr); - TALER_EXCHANGE_recoup_cancel (ph); + TALER_EXCHANGE_post_recoup_withdraw_cancel (ph); } -struct TALER_EXCHANGE_RecoupHandle * -TALER_EXCHANGE_recoup ( +struct TALER_EXCHANGE_PostRecoupWithdrawHandle * +TALER_EXCHANGE_post_recoup_withdraw_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_DenomPublicKey *pk, const struct TALER_DenominationSignature *denom_sig, - const struct TALER_ExchangeBlindingValues *blinding_values, + const struct TALER_ExchangeBlindingValues *exchange_vals, const struct TALER_PlanchetMasterSecretP *ps, - const struct TALER_HashBlindedPlanchetsP *h_planchets, - TALER_EXCHANGE_RecoupResultCallback recoup_cb, - void *recoup_cb_cls) + const struct TALER_HashBlindedPlanchetsP *h_planchets) { - struct TALER_EXCHANGE_RecoupHandle *ph; + struct TALER_EXCHANGE_PostRecoupWithdrawHandle *ph; struct TALER_DenominationHashP h_denom_pub; - json_t *recoup_obj; - CURL *eh; - char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; struct TALER_CoinSpendPrivateKeyP coin_priv; union GNUNET_CRYPTO_BlindingSecretP bks; + struct TALER_CoinSpendSignatureP coin_sig; - ph = GNUNET_new (struct TALER_EXCHANGE_RecoupHandle); + ph = GNUNET_new (struct TALER_EXCHANGE_PostRecoupWithdrawHandle); + ph->ctx = ctx; + ph->base_url = GNUNET_strdup (url); + ph->keys = TALER_EXCHANGE_keys_incref (keys); TALER_planchet_setup_coin_priv (ps, - blinding_values, + exchange_vals, &coin_priv); TALER_planchet_blinding_secret_create (ps, - blinding_values, + exchange_vals, &bks); GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv, &ph->coin_pub.eddsa_pub); @@ -262,16 +266,16 @@ TALER_EXCHANGE_recoup ( TALER_wallet_recoup_sign (&h_denom_pub, &bks, &coin_priv, - &ph->coin_sig); - recoup_obj = GNUNET_JSON_PACK ( + &coin_sig); + ph->body = GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("denom_pub_hash", &h_denom_pub), TALER_JSON_pack_denom_sig ("denom_sig", denom_sig), TALER_JSON_pack_exchange_blinding_values ("ewv", - blinding_values), + exchange_vals), GNUNET_JSON_pack_data_auto ("coin_sig", - &ph->coin_sig), + &coin_sig), GNUNET_JSON_pack_data_auto ("h_planchets", h_planchets), GNUNET_JSON_pack_data_auto ("coin_blind_key_secret", @@ -279,9 +283,11 @@ TALER_EXCHANGE_recoup ( switch (denom_sig->unblinded_sig->cipher) { case GNUNET_CRYPTO_BSA_INVALID: - json_decref (recoup_obj); - GNUNET_break (0); + json_decref (ph->body); + GNUNET_free (ph->base_url); + TALER_EXCHANGE_keys_decref (ph->keys); GNUNET_free (ph); + GNUNET_break (0); return NULL; case GNUNET_CRYPTO_BSA_RSA: break; @@ -297,13 +303,28 @@ TALER_EXCHANGE_recoup ( &nonce.cs_nonce); GNUNET_assert ( 0 == - json_object_set_new (recoup_obj, + json_object_set_new (ph->body, "nonce", GNUNET_JSON_from_data_auto ( &nonce))); } + break; } + return ph; +} + +enum TALER_ErrorCode +TALER_EXCHANGE_post_recoup_withdraw_start ( + struct TALER_EXCHANGE_PostRecoupWithdrawHandle *ph, + TALER_EXCHANGE_PostRecoupWithdrawCallback cb, + TALER_EXCHANGE_POST_RECOUP_WITHDRAW_RESULT_CLOSURE *cb_cls) +{ + CURL *eh; + char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; + + ph->cb = cb; + ph->cb_cls = cb_cls; { char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; char *end; @@ -319,64 +340,57 @@ TALER_EXCHANGE_recoup ( "coins/%s/recoup", pub_str); } - - ph->pk = *pk; - memset (&ph->pk.key, - 0, - sizeof (ph->pk.key)); /* zero out, as lifetime cannot be warranted */ - ph->cb = recoup_cb; - ph->cb_cls = recoup_cb_cls; - ph->url = TALER_url_join (url, + ph->url = TALER_url_join (ph->base_url, arg_str, NULL); if (NULL == ph->url) { - json_decref (recoup_obj); - GNUNET_free (ph); - return NULL; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not construct request URL.\n"); + return TALER_EC_GENERIC_CONFIGURATION_INVALID; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "URL for recoup: `%s'\n", + ph->url); eh = TALER_EXCHANGE_curl_easy_get_ (ph->url); if ( (NULL == eh) || (GNUNET_OK != - TALER_curl_easy_post (&ph->ctx, + TALER_curl_easy_post (&ph->post_ctx, eh, - recoup_obj)) ) + ph->body)) ) { GNUNET_break (0); if (NULL != eh) curl_easy_cleanup (eh); - json_decref (recoup_obj); - GNUNET_free (ph->url); - GNUNET_free (ph); - return NULL; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } - json_decref (recoup_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for recoup: `%s'\n", - ph->url); - ph->keys = TALER_EXCHANGE_keys_incref (keys); - ph->job = GNUNET_CURL_job_add2 (ctx, + ph->job = GNUNET_CURL_job_add2 (ph->ctx, eh, - ph->ctx.headers, + ph->post_ctx.headers, &handle_recoup_finished, ph); - return ph; + if (NULL == ph->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_recoup_cancel (struct TALER_EXCHANGE_RecoupHandle *ph) +TALER_EXCHANGE_post_recoup_withdraw_cancel ( + struct TALER_EXCHANGE_PostRecoupWithdrawHandle *ph) { if (NULL != ph->job) { GNUNET_CURL_job_cancel (ph->job); ph->job = NULL; } + TALER_curl_easy_post_finished (&ph->post_ctx); GNUNET_free (ph->url); - TALER_curl_easy_post_finished (&ph->ctx); + GNUNET_free (ph->base_url); + json_decref (ph->body); TALER_EXCHANGE_keys_decref (ph->keys); GNUNET_free (ph); } -/* end of exchange_api_recoup.c */ +/* end of exchange_api_post-recoup-withdraw.c */ diff --git a/src/lib/exchange_api_post-reserves-RESERVE_PUB-close.c b/src/lib/exchange_api_post-reserves-RESERVE_PUB-close.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA + Copyright (C) 2014-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -33,20 +33,25 @@ /** - * @brief A /reserves/$RID/close Handle + * @brief A POST /reserves/$RID/close Handle */ -struct TALER_EXCHANGE_ReservesCloseHandle +struct TALER_EXCHANGE_PostReservesCloseHandle { /** - * The url for this request. + * Reference to the execution context. */ - char *url; + struct GNUNET_CURL_Context *ctx; /** - * Handle for the request. + * Base URL of the exchange. */ - struct GNUNET_CURL_Job *job; + char *base_url; + + /** + * The url for this request, set during _start. + */ + char *url; /** * Context for #TEH_curl_easy_post(). Keeps the data that must @@ -55,14 +60,24 @@ struct TALER_EXCHANGE_ReservesCloseHandle struct TALER_CURL_PostContext post_ctx; /** + * Handle for the request. + */ + struct GNUNET_CURL_Job *job; + + /** * Function to call with the result. */ - TALER_EXCHANGE_ReservesCloseCallback cb; + TALER_EXCHANGE_PostReservesCloseCallback cb; /** * Closure for @a cb. */ - void *cb_cls; + TALER_EXCHANGE_POST_RESERVES_CLOSE_RESULT_CLOSURE *cb_cls; + + /** + * Private key of the reserve. + */ + struct TALER_ReservePrivateKeyP reserve_priv; /** * Public key of the reserve we are querying. @@ -70,9 +85,9 @@ struct TALER_EXCHANGE_ReservesCloseHandle struct TALER_ReservePublicKeyP reserve_pub; /** - * Our signature. + * Target payto URI to send the reserve balance to (optional). */ - struct TALER_ReserveSignatureP reserve_sig; + struct TALER_FullPayto target_payto_uri; /** * When did we make the request. @@ -86,15 +101,15 @@ struct TALER_EXCHANGE_ReservesCloseHandle * We received an #MHD_HTTP_OK close code. Handle the JSON * response. * - * @param rch handle of the request + * @param prch handle of the request * @param j JSON response * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -handle_reserves_close_ok (struct TALER_EXCHANGE_ReservesCloseHandle *rch, +handle_reserves_close_ok (struct TALER_EXCHANGE_PostReservesCloseHandle *prch, const json_t *j) { - struct TALER_EXCHANGE_ReserveCloseResult rs = { + struct TALER_EXCHANGE_PostReservesCloseResponse rs = { .hr.reply = j, .hr.http_status = MHD_HTTP_OK, }; @@ -113,9 +128,9 @@ handle_reserves_close_ok (struct TALER_EXCHANGE_ReservesCloseHandle *rch, GNUNET_break_op (0); return GNUNET_SYSERR; } - rch->cb (rch->cb_cls, - &rs); - rch->cb = NULL; + prch->cb (prch->cb_cls, + &rs); + prch->cb = NULL; GNUNET_JSON_parse_free (spec); return GNUNET_OK; } @@ -125,15 +140,15 @@ handle_reserves_close_ok (struct TALER_EXCHANGE_ReservesCloseHandle *rch, * We received an #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS close code. Handle the JSON * response. * - * @param rch handle of the request + * @param prch handle of the request * @param j JSON response * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -handle_reserves_close_kyc (struct TALER_EXCHANGE_ReservesCloseHandle *rch, +handle_reserves_close_kyc (struct TALER_EXCHANGE_PostReservesCloseHandle *prch, const json_t *j) { - struct TALER_EXCHANGE_ReserveCloseResult rs = { + struct TALER_EXCHANGE_PostReservesCloseResponse rs = { .hr.reply = j, .hr.http_status = MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, }; @@ -156,9 +171,9 @@ handle_reserves_close_kyc (struct TALER_EXCHANGE_ReservesCloseHandle *rch, GNUNET_break_op (0); return GNUNET_SYSERR; } - rch->cb (rch->cb_cls, - &rs); - rch->cb = NULL; + prch->cb (prch->cb_cls, + &rs); + prch->cb = NULL; GNUNET_JSON_parse_free (spec); return GNUNET_OK; } @@ -168,7 +183,7 @@ handle_reserves_close_kyc (struct TALER_EXCHANGE_ReservesCloseHandle *rch, * Function called when we're done processing the * HTTP /reserves/$RID/close request. * - * @param cls the `struct TALER_EXCHANGE_ReservesCloseHandle` + * @param cls the `struct TALER_EXCHANGE_PostReservesCloseHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -177,14 +192,14 @@ handle_reserves_close_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_ReservesCloseHandle *rch = cls; + struct TALER_EXCHANGE_PostReservesCloseHandle *prch = cls; const json_t *j = response; - struct TALER_EXCHANGE_ReserveCloseResult rs = { + struct TALER_EXCHANGE_PostReservesCloseResponse rs = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - rch->job = NULL; + prch->job = NULL; switch (response_code) { case 0: @@ -192,7 +207,7 @@ handle_reserves_close_finished (void *cls, break; case MHD_HTTP_OK: if (GNUNET_OK != - handle_reserves_close_ok (rch, + handle_reserves_close_ok (prch, j)) { GNUNET_break_op (0); @@ -227,7 +242,7 @@ handle_reserves_close_finished (void *cls, break; case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: if (GNUNET_OK != - handle_reserves_close_kyc (rch, + handle_reserves_close_kyc (prch, j)) { GNUNET_break_op (0); @@ -252,43 +267,82 @@ handle_reserves_close_finished (void *cls, (int) rs.hr.ec); break; } - if (NULL != rch->cb) + if (NULL != prch->cb) { - rch->cb (rch->cb_cls, - &rs); - rch->cb = NULL; + prch->cb (prch->cb_cls, + &rs); + prch->cb = NULL; } - TALER_EXCHANGE_reserves_close_cancel (rch); + TALER_EXCHANGE_post_reserves_close_cancel (prch); } -struct TALER_EXCHANGE_ReservesCloseHandle * -TALER_EXCHANGE_reserves_close ( +struct TALER_EXCHANGE_PostReservesCloseHandle * +TALER_EXCHANGE_post_reserves_close_create ( struct GNUNET_CURL_Context *ctx, const char *url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_FullPayto target_payto_uri, - TALER_EXCHANGE_ReservesCloseCallback cb, - void *cb_cls) + const struct TALER_ReservePrivateKeyP *reserve_priv) +{ + struct TALER_EXCHANGE_PostReservesCloseHandle *prch; + + prch = GNUNET_new (struct TALER_EXCHANGE_PostReservesCloseHandle); + prch->ctx = ctx; + prch->base_url = GNUNET_strdup (url); + prch->reserve_priv = *reserve_priv; + GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, + &prch->reserve_pub.eddsa_pub); + prch->target_payto_uri.full_payto = NULL; + return prch; +} + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_post_reserves_close_set_options_ ( + struct TALER_EXCHANGE_PostReservesCloseHandle *prch, + unsigned int num_options, + const struct TALER_EXCHANGE_PostReservesCloseOptionValue options[]) +{ + for (unsigned int i = 0; i < num_options; i++) + { + const struct TALER_EXCHANGE_PostReservesCloseOptionValue *opt = &options[i]; + + switch (opt->option) + { + case TALER_EXCHANGE_POST_RESERVES_CLOSE_OPTION_END: + return GNUNET_OK; + case TALER_EXCHANGE_POST_RESERVES_CLOSE_OPTION_PAYTO_URI: + GNUNET_free (prch->target_payto_uri.full_payto); + prch->target_payto_uri.full_payto + = GNUNET_strdup (opt->details.payto_uri.full_payto); + break; + } + } + return GNUNET_OK; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_reserves_close_start ( + struct TALER_EXCHANGE_PostReservesCloseHandle *prch, + TALER_EXCHANGE_PostReservesCloseCallback cb, + TALER_EXCHANGE_POST_RESERVES_CLOSE_RESULT_CLOSURE *cb_cls) { - struct TALER_EXCHANGE_ReservesCloseHandle *rch; CURL *eh; char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; + struct TALER_ReserveSignatureP reserve_sig; struct TALER_FullPaytoHashP h_payto; + json_t *close_obj; - rch = GNUNET_new (struct TALER_EXCHANGE_ReservesCloseHandle); - rch->cb = cb; - rch->cb_cls = cb_cls; - rch->ts = GNUNET_TIME_timestamp_get (); - GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, - &rch->reserve_pub.eddsa_pub); + prch->cb = cb; + prch->cb_cls = cb_cls; + prch->ts = GNUNET_TIME_timestamp_get (); { char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2]; char *end; end = GNUNET_STRINGS_data_to_string ( - &rch->reserve_pub, - sizeof (rch->reserve_pub), + &prch->reserve_pub, + sizeof (prch->reserve_pub), pub_str, sizeof (pub_str)); *end = '\0'; @@ -297,77 +351,68 @@ TALER_EXCHANGE_reserves_close ( "reserves/%s/close", pub_str); } - rch->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == rch->url) - { - GNUNET_free (rch); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (rch->url); - if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (rch->url); - GNUNET_free (rch); - return NULL; - } - if (NULL != target_payto_uri.full_payto) - TALER_full_payto_hash (target_payto_uri, + prch->url = TALER_url_join (prch->base_url, + arg_str, + NULL); + if (NULL == prch->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + if (NULL != prch->target_payto_uri.full_payto) + TALER_full_payto_hash (prch->target_payto_uri, &h_payto); - TALER_wallet_reserve_close_sign (rch->ts, - (NULL != target_payto_uri.full_payto) + TALER_wallet_reserve_close_sign (prch->ts, + (NULL != prch->target_payto_uri.full_payto) ? &h_payto : NULL, - reserve_priv, - &rch->reserve_sig); - { - json_t *close_obj = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_allow_null ( - TALER_JSON_pack_full_payto ("payto_uri", - target_payto_uri)), - GNUNET_JSON_pack_timestamp ("request_timestamp", - rch->ts), - GNUNET_JSON_pack_data_auto ("reserve_sig", - &rch->reserve_sig)); - - if (GNUNET_OK != - TALER_curl_easy_post (&rch->post_ctx, + &prch->reserve_priv, + &reserve_sig); + close_obj = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_allow_null ( + TALER_JSON_pack_full_payto ("payto_uri", + prch->target_payto_uri)), + GNUNET_JSON_pack_timestamp ("request_timestamp", + prch->ts), + GNUNET_JSON_pack_data_auto ("reserve_sig", + &reserve_sig)); + eh = TALER_EXCHANGE_curl_easy_get_ (prch->url); + if ( (NULL == eh) || + (GNUNET_OK != + TALER_curl_easy_post (&prch->post_ctx, eh, - close_obj)) - { - GNUNET_break (0); + close_obj)) ) + { + GNUNET_break (0); + if (NULL != eh) curl_easy_cleanup (eh); - json_decref (close_obj); - GNUNET_free (rch->url); - GNUNET_free (rch); - return NULL; - } json_decref (close_obj); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } - rch->job = GNUNET_CURL_job_add2 (ctx, - eh, - rch->post_ctx.headers, - &handle_reserves_close_finished, - rch); - return rch; + json_decref (close_obj); + prch->job = GNUNET_CURL_job_add2 (prch->ctx, + eh, + prch->post_ctx.headers, + &handle_reserves_close_finished, + prch); + if (NULL == prch->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_reserves_close_cancel ( - struct TALER_EXCHANGE_ReservesCloseHandle *rch) +TALER_EXCHANGE_post_reserves_close_cancel ( + struct TALER_EXCHANGE_PostReservesCloseHandle *prch) { - if (NULL != rch->job) + if (NULL != prch->job) { - GNUNET_CURL_job_cancel (rch->job); - rch->job = NULL; + GNUNET_CURL_job_cancel (prch->job); + prch->job = NULL; } - TALER_curl_easy_post_finished (&rch->post_ctx); - GNUNET_free (rch->url); - GNUNET_free (rch); + TALER_curl_easy_post_finished (&prch->post_ctx); + GNUNET_free (prch->url); + GNUNET_free (prch->base_url); + GNUNET_free (prch->target_payto_uri.full_payto); + GNUNET_free (prch); } -/* end of exchange_api_reserves_close.c */ +/* end of exchange_api_post-reserves-RESERVE_PUB-close.c */ diff --git a/src/lib/exchange_api_post-reserves-RESERVE_PUB-open.c b/src/lib/exchange_api_post-reserves-RESERVE_PUB-open.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA + Copyright (C) 2014-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -61,25 +61,25 @@ struct CoinData /** - * @brief A /reserves/$RID/open Handle + * @brief A POST /reserves/$RID/open Handle */ -struct TALER_EXCHANGE_ReservesOpenHandle +struct TALER_EXCHANGE_PostReservesOpenHandle { /** - * The keys of the exchange this request handle will use + * Reference to the execution context. */ - struct TALER_EXCHANGE_Keys *keys; + struct GNUNET_CURL_Context *ctx; /** - * The url for this request. + * Base URL of the exchange. */ - char *url; + char *base_url; /** - * Handle for the request. + * The url for this request, set during _start. */ - struct GNUNET_CURL_Job *job; + char *url; /** * Context for #TEH_curl_easy_post(). Keeps the data that must @@ -88,24 +88,24 @@ struct TALER_EXCHANGE_ReservesOpenHandle struct TALER_CURL_PostContext post_ctx; /** - * Function to call with the result. + * Handle for the request. */ - TALER_EXCHANGE_ReservesOpenCallback cb; + struct GNUNET_CURL_Job *job; /** - * Closure for @a cb. + * Function to call with the result. */ - void *cb_cls; + TALER_EXCHANGE_PostReservesOpenCallback cb; /** - * Information we keep per coin to validate the reply. + * Closure for @a cb. */ - struct CoinData *coins; + TALER_EXCHANGE_POST_RESERVES_OPEN_RESULT_CLOSURE *cb_cls; /** - * Length of the @e coins array. + * The keys of the exchange this request handle will use */ - unsigned int num_coins; + struct TALER_EXCHANGE_Keys *keys; /** * Public key of the reserve we are querying. @@ -113,14 +113,19 @@ struct TALER_EXCHANGE_ReservesOpenHandle struct TALER_ReservePublicKeyP reserve_pub; /** - * Our signature. + * Information we keep per coin to validate the reply. */ - struct TALER_ReserveSignatureP reserve_sig; + struct CoinData *coins; /** - * When did we make the request. + * Length of the @e coins array. */ - struct GNUNET_TIME_Timestamp ts; + unsigned int num_coins; + + /** + * Pre-built JSON body for the request. + */ + json_t *body; }; @@ -129,15 +134,15 @@ struct TALER_EXCHANGE_ReservesOpenHandle * We received an #MHD_HTTP_OK open code. Handle the JSON * response. * - * @param roh handle of the request + * @param proh handle of the request * @param j JSON response * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -handle_reserves_open_ok (struct TALER_EXCHANGE_ReservesOpenHandle *roh, +handle_reserves_open_ok (struct TALER_EXCHANGE_PostReservesOpenHandle *proh, const json_t *j) { - struct TALER_EXCHANGE_ReserveOpenResult rs = { + struct TALER_EXCHANGE_PostReservesOpenResponse rs = { .hr.reply = j, .hr.http_status = MHD_HTTP_OK, }; @@ -158,9 +163,9 @@ handle_reserves_open_ok (struct TALER_EXCHANGE_ReservesOpenHandle *roh, GNUNET_break_op (0); return GNUNET_SYSERR; } - roh->cb (roh->cb_cls, - &rs); - roh->cb = NULL; + proh->cb (proh->cb_cls, + &rs); + proh->cb = NULL; GNUNET_JSON_parse_free (spec); return GNUNET_OK; } @@ -170,15 +175,15 @@ handle_reserves_open_ok (struct TALER_EXCHANGE_ReservesOpenHandle *roh, * We received an #MHD_HTTP_PAYMENT_REQUIRED open code. Handle the JSON * response. * - * @param roh handle of the request + * @param proh handle of the request * @param j JSON response * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -handle_reserves_open_pr (struct TALER_EXCHANGE_ReservesOpenHandle *roh, +handle_reserves_open_pr (struct TALER_EXCHANGE_PostReservesOpenHandle *proh, const json_t *j) { - struct TALER_EXCHANGE_ReserveOpenResult rs = { + struct TALER_EXCHANGE_PostReservesOpenResponse rs = { .hr.reply = j, .hr.http_status = MHD_HTTP_PAYMENT_REQUIRED, }; @@ -199,9 +204,9 @@ handle_reserves_open_pr (struct TALER_EXCHANGE_ReservesOpenHandle *roh, GNUNET_break_op (0); return GNUNET_SYSERR; } - roh->cb (roh->cb_cls, - &rs); - roh->cb = NULL; + proh->cb (proh->cb_cls, + &rs); + proh->cb = NULL; GNUNET_JSON_parse_free (spec); return GNUNET_OK; } @@ -211,15 +216,15 @@ handle_reserves_open_pr (struct TALER_EXCHANGE_ReservesOpenHandle *roh, * We received an #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS open code. Handle the JSON * response. * - * @param roh handle of the request + * @param proh handle of the request * @param j JSON response * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -handle_reserves_open_kyc (struct TALER_EXCHANGE_ReservesOpenHandle *roh, +handle_reserves_open_kyc (struct TALER_EXCHANGE_PostReservesOpenHandle *proh, const json_t *j) { - struct TALER_EXCHANGE_ReserveOpenResult rs = { + struct TALER_EXCHANGE_PostReservesOpenResponse rs = { .hr.reply = j, .hr.http_status = MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, }; @@ -242,9 +247,9 @@ handle_reserves_open_kyc (struct TALER_EXCHANGE_ReservesOpenHandle *roh, GNUNET_break_op (0); return GNUNET_SYSERR; } - roh->cb (roh->cb_cls, - &rs); - roh->cb = NULL; + proh->cb (proh->cb_cls, + &rs); + proh->cb = NULL; GNUNET_JSON_parse_free (spec); return GNUNET_OK; } @@ -254,7 +259,7 @@ handle_reserves_open_kyc (struct TALER_EXCHANGE_ReservesOpenHandle *roh, * Function called when we're done processing the * HTTP /reserves/$RID/open request. * - * @param cls the `struct TALER_EXCHANGE_ReservesOpenHandle` + * @param cls the `struct TALER_EXCHANGE_PostReservesOpenHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -263,14 +268,14 @@ handle_reserves_open_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_ReservesOpenHandle *roh = cls; + struct TALER_EXCHANGE_PostReservesOpenHandle *proh = cls; const json_t *j = response; - struct TALER_EXCHANGE_ReserveOpenResult rs = { + struct TALER_EXCHANGE_PostReservesOpenResponse rs = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - roh->job = NULL; + proh->job = NULL; switch (response_code) { case 0: @@ -278,7 +283,7 @@ handle_reserves_open_finished (void *cls, break; case MHD_HTTP_OK: if (GNUNET_OK != - handle_reserves_open_ok (roh, + handle_reserves_open_ok (proh, j)) { GNUNET_break_op (0); @@ -298,7 +303,7 @@ handle_reserves_open_finished (void *cls, break; case MHD_HTTP_PAYMENT_REQUIRED: if (GNUNET_OK != - handle_reserves_open_pr (roh, + handle_reserves_open_pr (proh, j)) { GNUNET_break_op (0); @@ -339,9 +344,9 @@ handle_reserves_open_finished (void *cls, rs.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - for (unsigned int i = 0; i<roh->num_coins; i++) + for (unsigned int i = 0; i < proh->num_coins; i++) { - const struct CoinData *cdi = &roh->coins[i]; + const struct CoinData *cdi = &proh->coins[i]; if (0 == GNUNET_memcmp (&rs.details.conflict.coin_pub, &cdi->coin_pub)) @@ -363,7 +368,7 @@ handle_reserves_open_finished (void *cls, } case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: if (GNUNET_OK != - handle_reserves_open_kyc (roh, + handle_reserves_open_kyc (proh, j)) { GNUNET_break_op (0); @@ -388,18 +393,18 @@ handle_reserves_open_finished (void *cls, (int) rs.hr.ec); break; } - if (NULL != roh->cb) + if (NULL != proh->cb) { - roh->cb (roh->cb_cls, - &rs); - roh->cb = NULL; + proh->cb (proh->cb_cls, + &rs); + proh->cb = NULL; } - TALER_EXCHANGE_reserves_open_cancel (roh); + TALER_EXCHANGE_post_reserves_open_cancel (proh); } -struct TALER_EXCHANGE_ReservesOpenHandle * -TALER_EXCHANGE_reserves_open ( +struct TALER_EXCHANGE_PostReservesOpenHandle * +TALER_EXCHANGE_post_reserves_open_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, @@ -409,69 +414,38 @@ TALER_EXCHANGE_reserves_open ( const struct TALER_EXCHANGE_PurseDeposit coin_payments[ static coin_payments_length], struct GNUNET_TIME_Timestamp expiration_time, - uint32_t min_purses, - TALER_EXCHANGE_ReservesOpenCallback cb, - void *cb_cls) + uint32_t min_purses) { - struct TALER_EXCHANGE_ReservesOpenHandle *roh; - CURL *eh; - char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; + struct TALER_EXCHANGE_PostReservesOpenHandle *proh; + struct GNUNET_TIME_Timestamp ts; + struct TALER_ReserveSignatureP reserve_sig; json_t *cpa; - roh = GNUNET_new (struct TALER_EXCHANGE_ReservesOpenHandle); - roh->cb = cb; - roh->cb_cls = cb_cls; - roh->ts = GNUNET_TIME_timestamp_get (); + proh = GNUNET_new (struct TALER_EXCHANGE_PostReservesOpenHandle); + proh->ctx = ctx; + proh->base_url = GNUNET_strdup (url); + proh->keys = TALER_EXCHANGE_keys_incref (keys); + ts = GNUNET_TIME_timestamp_get (); GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, - &roh->reserve_pub.eddsa_pub); - { - char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &roh->reserve_pub, - sizeof (roh->reserve_pub), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "reserves/%s/open", - pub_str); - } - roh->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == roh->url) - { - GNUNET_free (roh); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (roh->url); - if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (roh->url); - GNUNET_free (roh); - return NULL; - } + &proh->reserve_pub.eddsa_pub); TALER_wallet_reserve_open_sign (reserve_contribution, - roh->ts, + ts, expiration_time, min_purses, reserve_priv, - &roh->reserve_sig); - roh->coins = GNUNET_new_array (coin_payments_length, - struct CoinData); + &reserve_sig); + proh->coins = GNUNET_new_array (coin_payments_length, + struct CoinData); + proh->num_coins = coin_payments_length; cpa = json_array (); GNUNET_assert (NULL != cpa); - for (unsigned int i = 0; i<coin_payments_length; i++) + for (unsigned int i = 0; i < coin_payments_length; i++) { const struct TALER_EXCHANGE_PurseDeposit *pd = &coin_payments[i]; const struct TALER_AgeCommitmentProof *acp = pd->age_commitment_proof; struct TALER_AgeCommitmentHashP ahac; struct TALER_AgeCommitmentHashP *achp = NULL; - struct CoinData *cd = &roh->coins[i]; + struct CoinData *cd = &proh->coins[i]; json_t *cp; cd->contribution = pd->amount; @@ -483,7 +457,7 @@ TALER_EXCHANGE_reserves_open ( achp = &ahac; } TALER_wallet_reserve_open_deposit_sign (&pd->amount, - &roh->reserve_sig, + &reserve_sig, &pd->coin_priv, &cd->coin_sig); GNUNET_CRYPTO_eddsa_key_get_public (&pd->coin_priv.eddsa_priv, @@ -507,61 +481,103 @@ TALER_EXCHANGE_reserves_open ( json_array_append_new (cpa, cp)); } + proh->body = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_timestamp ("request_timestamp", + ts), + GNUNET_JSON_pack_timestamp ("reserve_expiration", + expiration_time), + GNUNET_JSON_pack_array_steal ("payments", + cpa), + TALER_JSON_pack_amount ("reserve_payment", + reserve_contribution), + GNUNET_JSON_pack_uint64 ("purse_limit", + min_purses), + GNUNET_JSON_pack_data_auto ("reserve_sig", + &reserve_sig)); + if (NULL == proh->body) { - json_t *open_obj = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_timestamp ("request_timestamp", - roh->ts), - GNUNET_JSON_pack_timestamp ("reserve_expiration", - expiration_time), - GNUNET_JSON_pack_array_steal ("payments", - cpa), - TALER_JSON_pack_amount ("reserve_payment", - reserve_contribution), - GNUNET_JSON_pack_uint64 ("purse_limit", - min_purses), - GNUNET_JSON_pack_data_auto ("reserve_sig", - &roh->reserve_sig)); + GNUNET_break (0); + GNUNET_free (proh->coins); + GNUNET_free (proh->base_url); + TALER_EXCHANGE_keys_decref (proh->keys); + GNUNET_free (proh); + return NULL; + } + return proh; +} - if (GNUNET_OK != - TALER_curl_easy_post (&roh->post_ctx, + +enum TALER_ErrorCode +TALER_EXCHANGE_post_reserves_open_start ( + struct TALER_EXCHANGE_PostReservesOpenHandle *proh, + TALER_EXCHANGE_PostReservesOpenCallback cb, + TALER_EXCHANGE_POST_RESERVES_OPEN_RESULT_CLOSURE *cb_cls) +{ + CURL *eh; + char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; + + proh->cb = cb; + proh->cb_cls = cb_cls; + { + char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2]; + char *end; + + end = GNUNET_STRINGS_data_to_string ( + &proh->reserve_pub, + sizeof (proh->reserve_pub), + pub_str, + sizeof (pub_str)); + *end = '\0'; + GNUNET_snprintf (arg_str, + sizeof (arg_str), + "reserves/%s/open", + pub_str); + } + proh->url = TALER_url_join (proh->base_url, + arg_str, + NULL); + if (NULL == proh->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + eh = TALER_EXCHANGE_curl_easy_get_ (proh->url); + if ( (NULL == eh) || + (GNUNET_OK != + TALER_curl_easy_post (&proh->post_ctx, eh, - open_obj)) - { - GNUNET_break (0); + proh->body)) ) + { + GNUNET_break (0); + if (NULL != eh) curl_easy_cleanup (eh); - json_decref (open_obj); - GNUNET_free (roh->coins); - GNUNET_free (roh->url); - GNUNET_free (roh); - return NULL; - } - json_decref (open_obj); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } - roh->keys = TALER_EXCHANGE_keys_incref (keys); - roh->job = GNUNET_CURL_job_add2 (ctx, - eh, - roh->post_ctx.headers, - &handle_reserves_open_finished, - roh); - return roh; + proh->job = GNUNET_CURL_job_add2 (proh->ctx, + eh, + proh->post_ctx.headers, + &handle_reserves_open_finished, + proh); + if (NULL == proh->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_reserves_open_cancel ( - struct TALER_EXCHANGE_ReservesOpenHandle *roh) +TALER_EXCHANGE_post_reserves_open_cancel ( + struct TALER_EXCHANGE_PostReservesOpenHandle *proh) { - if (NULL != roh->job) + if (NULL != proh->job) { - GNUNET_CURL_job_cancel (roh->job); - roh->job = NULL; + GNUNET_CURL_job_cancel (proh->job); + proh->job = NULL; } - TALER_curl_easy_post_finished (&roh->post_ctx); - GNUNET_free (roh->coins); - GNUNET_free (roh->url); - TALER_EXCHANGE_keys_decref (roh->keys); - GNUNET_free (roh); + TALER_curl_easy_post_finished (&proh->post_ctx); + json_decref (proh->body); + GNUNET_free (proh->coins); + GNUNET_free (proh->url); + GNUNET_free (proh->base_url); + TALER_EXCHANGE_keys_decref (proh->keys); + GNUNET_free (proh); } -/* end of exchange_api_reserves_open.c */ +/* end of exchange_api_post-reserves-RESERVE_PUB-open.c */ diff --git a/src/lib/exchange_api_post-reserves-RESERVE_PUB-purse.c b/src/lib/exchange_api_post-reserves-RESERVE_PUB-purse.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022-2023 Taler Systems SA + Copyright (C) 2022-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -35,9 +35,9 @@ /** - * @brief A purse create with merge handle + * @brief A POST /reserves/$RESERVE_PUB/purse handle */ -struct TALER_EXCHANGE_PurseCreateMergeHandle +struct TALER_EXCHANGE_PostReservesPurseHandle { /** @@ -46,20 +46,30 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle struct TALER_EXCHANGE_Keys *keys; /** - * The url for this request. + * Context for #TEH_curl_easy_post(). Keeps the data that must + * persist for Curl to make the upload. + */ + struct TALER_CURL_PostContext ctx; + + /** + * The base URL for this request. + */ + char *base_url; + + /** + * The full URL for this request, set during _start. */ char *url; /** - * The exchange base URL. + * The exchange base URL (same as base_url, kept for conflict checks). */ char *exchange_url; /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. + * Reference to the execution context. */ - struct TALER_CURL_PostContext ctx; + struct GNUNET_CURL_Context *curl_ctx; /** * Handle for the request. @@ -69,12 +79,27 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle /** * Function to call with the result. */ - TALER_EXCHANGE_PurseCreateMergeCallback cb; + TALER_EXCHANGE_PostReservesPurseCallback cb; /** * Closure for @a cb. */ - void *cb_cls; + TALER_EXCHANGE_POST_RESERVES_PURSE_RESULT_CLOSURE *cb_cls; + + /** + * Private key for the contract. + */ + struct TALER_ContractDiffiePrivateP contract_priv; + + /** + * Private key for the purse. + */ + struct TALER_PurseContractPrivateKeyP purse_priv; + + /** + * Private key of the reserve. + */ + struct TALER_ReservePrivateKeyP reserve_priv; /** * The encrypted contract (if any). @@ -117,7 +142,7 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle struct TALER_PurseContractSignatureP purse_sig; /** - * Hash over the purse's contrac terms. + * Hash over the purse's contract terms. */ struct TALER_PrivateContractHashP h_contract_terms; @@ -130,6 +155,31 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle * When does the purse get merged/created. */ struct GNUNET_TIME_Timestamp merge_timestamp; + + /** + * Our contract terms. + */ + json_t *contract_terms; + + /** + * Minimum age for the coins as per @e contract_terms. + */ + uint32_t min_age; + + struct + { + + /** + * Are we paying for purse creation? Not yet a "real" option. + */ + bool pay_for_purse; + + /** + * Should we upload the contract? + */ + bool upload_contract; + } options; + }; @@ -137,7 +187,7 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle * Function called when we're done processing the * HTTP /reserves/$RID/purse request. * - * @param cls the `struct TALER_EXCHANGE_PurseCreateMergeHandle` + * @param cls the `struct TALER_EXCHANGE_PostReservesPurseHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -146,15 +196,15 @@ handle_purse_create_with_merge_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_PurseCreateMergeHandle *pcm = cls; + struct TALER_EXCHANGE_PostReservesPurseHandle *prph = cls; const json_t *j = response; - struct TALER_EXCHANGE_PurseCreateMergeResponse dr = { + struct TALER_EXCHANGE_PostReservesPurseResponse dr = { .hr.reply = j, .hr.http_status = (unsigned int) response_code, - .reserve_sig = &pcm->reserve_sig + .reserve_sig = &prph->reserve_sig }; - pcm->job = NULL; + prph->job = NULL; switch (response_code) { case 0: @@ -189,7 +239,7 @@ handle_purse_create_with_merge_finished (void *cls, break; } if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (pcm->keys, + TALER_EXCHANGE_test_signing_key (prph->keys, &exchange_pub)) { GNUNET_break_op (0); @@ -200,11 +250,11 @@ handle_purse_create_with_merge_finished (void *cls, if (GNUNET_OK != TALER_exchange_online_purse_created_verify ( etime, - pcm->purse_expiration, - &pcm->purse_value_after_fees, + prph->purse_expiration, + &prph->purse_value_after_fees, &total_deposited, - &pcm->purse_pub, - &pcm->h_contract_terms, + &prph->purse_pub, + &prph->h_contract_terms, &exchange_pub, &exchange_sig)) { @@ -241,8 +291,8 @@ handle_purse_create_with_merge_finished (void *cls, case TALER_EC_EXCHANGE_RESERVES_PURSE_CREATE_CONFLICTING_META_DATA: if (GNUNET_OK != TALER_EXCHANGE_check_purse_create_conflict_ ( - &pcm->purse_sig, - &pcm->purse_pub, + &prph->purse_sig, + &prph->purse_pub, j)) { dr.hr.http_status = 0; @@ -253,10 +303,10 @@ handle_purse_create_with_merge_finished (void *cls, case TALER_EC_EXCHANGE_RESERVES_PURSE_MERGE_CONFLICTING_META_DATA: if (GNUNET_OK != TALER_EXCHANGE_check_purse_merge_conflict_ ( - &pcm->merge_sig, - &pcm->merge_pub, - &pcm->purse_pub, - pcm->exchange_url, + &prph->merge_sig, + &prph->merge_pub, + &prph->purse_pub, + prph->exchange_url, j)) { GNUNET_break_op (0); @@ -271,8 +321,8 @@ handle_purse_create_with_merge_finished (void *cls, case TALER_EC_EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA: if (GNUNET_OK != TALER_EXCHANGE_check_purse_econtract_conflict_ ( - &pcm->econtract.econtract_sig, - &pcm->purse_pub, + &prph->econtract.econtract_sig, + &prph->purse_pub, j)) { GNUNET_break_op (0); @@ -335,14 +385,18 @@ handle_purse_create_with_merge_finished (void *cls, GNUNET_break_op (0); break; } - pcm->cb (pcm->cb_cls, - &dr); - TALER_EXCHANGE_purse_create_with_merge_cancel (pcm); + if (NULL != prph->cb) + { + prph->cb (prph->cb_cls, + &dr); + prph->cb = NULL; + } + TALER_EXCHANGE_post_reserves_purse_cancel (prph); } -struct TALER_EXCHANGE_PurseCreateMergeHandle * -TALER_EXCHANGE_purse_create_with_merge ( +struct TALER_EXCHANGE_PostReservesPurseHandle * +TALER_EXCHANGE_post_reserves_purse_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, @@ -351,49 +405,51 @@ TALER_EXCHANGE_purse_create_with_merge ( const struct TALER_PurseMergePrivateKeyP *merge_priv, const struct TALER_ContractDiffiePrivateP *contract_priv, const json_t *contract_terms, - bool upload_contract, - bool pay_for_purse, - struct GNUNET_TIME_Timestamp merge_timestamp, - TALER_EXCHANGE_PurseCreateMergeCallback cb, - void *cb_cls) + bool pay_for_purse, // FIXME: turn into option? + struct GNUNET_TIME_Timestamp merge_timestamp) // FIXME: turn into option? { - struct TALER_EXCHANGE_PurseCreateMergeHandle *pcm; - json_t *create_with_merge_obj; - CURL *eh; - char arg_str[sizeof (pcm->reserve_pub) * 2 + 32]; - uint32_t min_age = 0; - struct TALER_Amount purse_fee; - enum TALER_WalletAccountMergeFlags flags; + struct TALER_EXCHANGE_PostReservesPurseHandle *prph; + + prph = GNUNET_new (struct TALER_EXCHANGE_PostReservesPurseHandle); + prph->curl_ctx = ctx; + prph->keys = TALER_EXCHANGE_keys_incref (keys); + prph->base_url = GNUNET_strdup (url); + prph->contract_terms = json_incref ((json_t *) contract_terms); + prph->exchange_url = GNUNET_strdup (url); + prph->contract_priv = *contract_priv; + prph->reserve_priv = *reserve_priv; + prph->purse_priv = *purse_priv; + prph->options.pay_for_purse = pay_for_purse; - pcm = GNUNET_new (struct TALER_EXCHANGE_PurseCreateMergeHandle); - pcm->cb = cb; - pcm->cb_cls = cb_cls; if (GNUNET_OK != TALER_JSON_contract_hash (contract_terms, - &pcm->h_contract_terms)) + &prph->h_contract_terms)) { GNUNET_break (0); - GNUNET_free (pcm); + TALER_EXCHANGE_keys_decref (prph->keys); + GNUNET_free (prph->base_url); + GNUNET_free (prph->exchange_url); + GNUNET_free (prph); return NULL; } - pcm->merge_timestamp = merge_timestamp; + prph->merge_timestamp = merge_timestamp; GNUNET_CRYPTO_eddsa_key_get_public (&purse_priv->eddsa_priv, - &pcm->purse_pub.eddsa_pub); + &prph->purse_pub.eddsa_pub); GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, - &pcm->reserve_pub.eddsa_pub); + &prph->reserve_pub.eddsa_pub); GNUNET_CRYPTO_eddsa_key_get_public (&merge_priv->eddsa_priv, - &pcm->merge_pub.eddsa_pub); + &prph->merge_pub.eddsa_pub); { struct GNUNET_JSON_Specification spec[] = { TALER_JSON_spec_amount_any ("amount", - &pcm->purse_value_after_fees), + &prph->purse_value_after_fees), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_uint32 ("minimum_age", - &min_age), + &prph->min_age), NULL), GNUNET_JSON_spec_timestamp ("pay_deadline", - &pcm->purse_expiration), + &prph->purse_expiration), GNUNET_JSON_spec_end () }; @@ -403,178 +459,226 @@ TALER_EXCHANGE_purse_create_with_merge ( NULL, NULL)) { GNUNET_break (0); - GNUNET_free (pcm); + TALER_EXCHANGE_keys_decref (prph->keys); + GNUNET_free (prph->base_url); + GNUNET_free (prph->exchange_url); + GNUNET_free (prph); return NULL; } } - if (pay_for_purse) + + TALER_wallet_purse_create_sign (prph->purse_expiration, + &prph->h_contract_terms, + &prph->merge_pub, + prph->min_age, + &prph->purse_value_after_fees, + purse_priv, + &prph->purse_sig); + { + struct TALER_NormalizedPayto payto_uri; + + payto_uri = TALER_reserve_make_payto (url, + &prph->reserve_pub); + TALER_wallet_purse_merge_sign (payto_uri, + prph->merge_timestamp, + &prph->purse_pub, + merge_priv, + &prph->merge_sig); + GNUNET_free (payto_uri.normalized_payto); + } + return prph; +} + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_post_reserves_purse_set_options_ ( + struct TALER_EXCHANGE_PostReservesPurseHandle *prph, + unsigned int num_options, + const struct TALER_EXCHANGE_PostReservesPurseOptionValue options[]) +{ + for (unsigned int i = 0; i < num_options; i++) + { + const struct TALER_EXCHANGE_PostReservesPurseOptionValue *opt = &options[i]; + + switch (opt->option) + { + case TALER_EXCHANGE_POST_RESERVES_PURSE_OPTION_END: + return GNUNET_OK; + case TALER_EXCHANGE_POST_RESERVES_PURSE_OPTION_UPLOAD_CONTRACT: + prph->options.upload_contract = true; + break; + } + } + return GNUNET_OK; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_reserves_purse_start ( + struct TALER_EXCHANGE_PostReservesPurseHandle *prph, + TALER_EXCHANGE_PostReservesPurseCallback cb, + TALER_EXCHANGE_POST_RESERVES_PURSE_RESULT_CLOSURE *cb_cls) +{ + char arg_str[sizeof (prph->reserve_pub) * 2 + 32]; + CURL *eh; + json_t *body; + struct TALER_Amount purse_fee; + enum TALER_WalletAccountMergeFlags flags; + + prph->cb = cb; + prph->cb_cls = cb_cls; + if (prph->options.pay_for_purse) { const struct TALER_EXCHANGE_GlobalFee *gf; + flags = TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE; gf = TALER_EXCHANGE_get_global_fee ( - keys, + prph->keys, GNUNET_TIME_timestamp_get ()); purse_fee = gf->fees.purse; - flags = TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE; } else { + flags = TALER_WAMF_MODE_CREATE_FROM_PURSE_QUOTA; GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pcm->purse_value_after_fees.currency, + TALER_amount_set_zero (prph->purse_value_after_fees.currency, &purse_fee)); - flags = TALER_WAMF_MODE_CREATE_FROM_PURSE_QUOTA; - } - - { - char pub_str[sizeof (pcm->reserve_pub) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &pcm->reserve_pub, - sizeof (pcm->reserve_pub), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "reserves/%s/purse", - pub_str); } - pcm->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == pcm->url) - { - GNUNET_break (0); - GNUNET_free (pcm); - return NULL; - } - TALER_wallet_purse_create_sign (pcm->purse_expiration, - &pcm->h_contract_terms, - &pcm->merge_pub, - min_age, - &pcm->purse_value_after_fees, - purse_priv, - &pcm->purse_sig); - { - struct TALER_NormalizedPayto payto_uri; - payto_uri = TALER_reserve_make_payto (url, - &pcm->reserve_pub); - TALER_wallet_purse_merge_sign (payto_uri, - merge_timestamp, - &pcm->purse_pub, - merge_priv, - &pcm->merge_sig); - GNUNET_free (payto_uri.normalized_payto); - } - TALER_wallet_account_merge_sign (merge_timestamp, - &pcm->purse_pub, - pcm->purse_expiration, - &pcm->h_contract_terms, - &pcm->purse_value_after_fees, + TALER_wallet_account_merge_sign (prph->merge_timestamp, + &prph->purse_pub, + prph->purse_expiration, + &prph->h_contract_terms, + &prph->purse_value_after_fees, &purse_fee, - min_age, + prph->min_age, flags, - reserve_priv, - &pcm->reserve_sig); - if (upload_contract) + &prph->reserve_priv, + &prph->reserve_sig); + + + if (prph->options.upload_contract) { TALER_CRYPTO_contract_encrypt_for_deposit ( - &pcm->purse_pub, - contract_priv, - contract_terms, - &pcm->econtract.econtract, - &pcm->econtract.econtract_size); - GNUNET_CRYPTO_ecdhe_key_get_public (&contract_priv->ecdhe_priv, - &pcm->econtract.contract_pub.ecdhe_pub); + &prph->purse_pub, + &prph->contract_priv, + prph->contract_terms, + &prph->econtract.econtract, + &prph->econtract.econtract_size); + GNUNET_CRYPTO_ecdhe_key_get_public ( + &prph->contract_priv.ecdhe_priv, + &prph->econtract.contract_pub.ecdhe_pub); TALER_wallet_econtract_upload_sign ( - pcm->econtract.econtract, - pcm->econtract.econtract_size, - &pcm->econtract.contract_pub, - purse_priv, - &pcm->econtract.econtract_sig); + prph->econtract.econtract, + prph->econtract.econtract_size, + &prph->econtract.contract_pub, + &prph->purse_priv, + &prph->econtract.econtract_sig); } - create_with_merge_obj = GNUNET_JSON_PACK ( + + body = GNUNET_JSON_PACK ( TALER_JSON_pack_amount ("purse_value", - &pcm->purse_value_after_fees), + &prph->purse_value_after_fees), GNUNET_JSON_pack_uint64 ("min_age", - min_age), + prph->min_age), GNUNET_JSON_pack_allow_null ( TALER_JSON_pack_econtract ("econtract", - upload_contract - ? &pcm->econtract + prph->options.upload_contract + ? &prph->econtract : NULL)), GNUNET_JSON_pack_allow_null ( - pay_for_purse + prph->options.pay_for_purse ? TALER_JSON_pack_amount ("purse_fee", &purse_fee) : GNUNET_JSON_pack_string ("dummy2", NULL)), GNUNET_JSON_pack_data_auto ("merge_pub", - &pcm->merge_pub), + &prph->merge_pub), GNUNET_JSON_pack_data_auto ("merge_sig", - &pcm->merge_sig), + &prph->merge_sig), GNUNET_JSON_pack_data_auto ("reserve_sig", - &pcm->reserve_sig), + &prph->reserve_sig), GNUNET_JSON_pack_data_auto ("purse_pub", - &pcm->purse_pub), + &prph->purse_pub), GNUNET_JSON_pack_data_auto ("purse_sig", - &pcm->purse_sig), + &prph->purse_sig), GNUNET_JSON_pack_data_auto ("h_contract_terms", - &pcm->h_contract_terms), + &prph->h_contract_terms), GNUNET_JSON_pack_timestamp ("merge_timestamp", - merge_timestamp), + prph->merge_timestamp), GNUNET_JSON_pack_timestamp ("purse_expiration", - pcm->purse_expiration)); - GNUNET_assert (NULL != create_with_merge_obj); - eh = TALER_EXCHANGE_curl_easy_get_ (pcm->url); + prph->purse_expiration)); + if (NULL == body) + return TALER_EC_GENERIC_ALLOCATION_FAILURE; + + { + char pub_str[sizeof (prph->reserve_pub) * 2]; + char *end; + + end = GNUNET_STRINGS_data_to_string ( + &prph->reserve_pub, + sizeof (prph->reserve_pub), + pub_str, + sizeof (pub_str)); + *end = '\0'; + GNUNET_snprintf (arg_str, + sizeof (arg_str), + "reserves/%s/purse", + pub_str); + } + prph->url = TALER_url_join (prph->base_url, + arg_str, + NULL); + if (NULL == prph->url) + { + GNUNET_break (0); + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "URL for purse create_with_merge: `%s'\n", + prph->url); + eh = TALER_EXCHANGE_curl_easy_get_ (prph->url); if ( (NULL == eh) || (GNUNET_OK != - TALER_curl_easy_post (&pcm->ctx, + TALER_curl_easy_post (&prph->ctx, eh, - create_with_merge_obj)) ) + body)) ) { GNUNET_break (0); if (NULL != eh) curl_easy_cleanup (eh); - json_decref (create_with_merge_obj); - GNUNET_free (pcm->econtract.econtract); - GNUNET_free (pcm->url); - GNUNET_free (pcm); - return NULL; + return TALER_EC_GENERIC_CURL_ALLOCATION_FAILURE; } - json_decref (create_with_merge_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for purse create_with_merge: `%s'\n", - pcm->url); - pcm->keys = TALER_EXCHANGE_keys_incref (keys); - pcm->exchange_url = GNUNET_strdup (url); - pcm->job = GNUNET_CURL_job_add2 (ctx, - eh, - pcm->ctx.headers, - &handle_purse_create_with_merge_finished, - pcm); - return pcm; + json_decref (body); + prph->job = GNUNET_CURL_job_add2 (prph->curl_ctx, + eh, + prph->ctx.headers, + &handle_purse_create_with_merge_finished, + prph); + if (NULL == prph->job) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return TALER_EC_NONE; } void -TALER_EXCHANGE_purse_create_with_merge_cancel ( - struct TALER_EXCHANGE_PurseCreateMergeHandle *pcm) +TALER_EXCHANGE_post_reserves_purse_cancel ( + struct TALER_EXCHANGE_PostReservesPurseHandle *prph) { - if (NULL != pcm->job) + if (NULL != prph->job) { - GNUNET_CURL_job_cancel (pcm->job); - pcm->job = NULL; + GNUNET_CURL_job_cancel (prph->job); + prph->job = NULL; } - GNUNET_free (pcm->url); - GNUNET_free (pcm->exchange_url); - TALER_curl_easy_post_finished (&pcm->ctx); - TALER_EXCHANGE_keys_decref (pcm->keys); - GNUNET_free (pcm->econtract.econtract); - GNUNET_free (pcm); + GNUNET_free (prph->url); + GNUNET_free (prph->base_url); + GNUNET_free (prph->exchange_url); + TALER_curl_easy_post_finished (&prph->ctx); + TALER_EXCHANGE_keys_decref (prph->keys); + GNUNET_free (prph->econtract.econtract); + json_decref (prph->contract_terms); + GNUNET_free (prph); } -/* end of exchange_api_purse_create_with_merge.c */ +/* end of exchange_api_post-reserves-RESERVE_PUB-purse.c */ diff --git a/src/lib/exchange_api_post-reserves-attest-RESERVE_PUB.c b/src/lib/exchange_api_post-reserves-attest-RESERVE_PUB.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA + Copyright (C) 2014-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -33,25 +33,25 @@ /** - * @brief A /reserves-attest/$RID Handle + * @brief A POST /reserves-attest/$RID Handle */ -struct TALER_EXCHANGE_ReservesAttestHandle +struct TALER_EXCHANGE_PostReservesAttestHandle { /** - * The keys of the this request handle will use + * Reference to the execution context. */ - struct TALER_EXCHANGE_Keys *keys; + struct GNUNET_CURL_Context *ctx; /** - * The url for this request. + * Base URL of the exchange. */ - char *url; + char *base_url; /** - * Handle for the request. + * The url for this request, set during _start. */ - struct GNUNET_CURL_Job *job; + char *url; /** * Context for #TEH_curl_easy_post(). Keeps the data that must @@ -60,9 +60,24 @@ struct TALER_EXCHANGE_ReservesAttestHandle struct TALER_CURL_PostContext post_ctx; /** + * Handle for the request. + */ + struct GNUNET_CURL_Job *job; + + /** * Function to call with the result. */ - TALER_EXCHANGE_ReservesPostAttestCallback cb; + TALER_EXCHANGE_PostReservesAttestCallback cb; + + /** + * Closure for @a cb. + */ + TALER_EXCHANGE_POST_RESERVES_ATTEST_RESULT_CLOSURE *cb_cls; + + /** + * The keys of the exchange this request handle will use. + */ + struct TALER_EXCHANGE_Keys *keys; /** * Public key of the reserve we are querying. @@ -70,9 +85,9 @@ struct TALER_EXCHANGE_ReservesAttestHandle struct TALER_ReservePublicKeyP reserve_pub; /** - * Closure for @a cb. + * Pre-built JSON body for the request. */ - void *cb_cls; + json_t *body; }; @@ -81,15 +96,15 @@ struct TALER_EXCHANGE_ReservesAttestHandle * We received an #MHD_HTTP_OK attest code. Handle the JSON * response. * - * @param rsh handle of the request + * @param prah handle of the request * @param j JSON response * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -handle_reserves_attest_ok (struct TALER_EXCHANGE_ReservesAttestHandle *rsh, +handle_reserves_attest_ok (struct TALER_EXCHANGE_PostReservesAttestHandle *prah, const json_t *j) { - struct TALER_EXCHANGE_ReservePostAttestResult rs = { + struct TALER_EXCHANGE_PostReservesAttestResponse rs = { .hr.reply = j, .hr.http_status = MHD_HTTP_OK }; @@ -118,15 +133,15 @@ handle_reserves_attest_ok (struct TALER_EXCHANGE_ReservesAttestHandle *rsh, return GNUNET_SYSERR; } if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (rsh->keys, + TALER_EXCHANGE_test_signing_key (prah->keys, &rs.details.ok.exchange_pub)) { GNUNET_break_op (0); rs.hr.http_status = 0; rs.hr.ec = TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_SIGNATURE_BY_EXCHANGE; - rsh->cb (rsh->cb_cls, - &rs); - rsh->cb = NULL; + prah->cb (prah->cb_cls, + &rs); + prah->cb = NULL; GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } @@ -135,7 +150,7 @@ handle_reserves_attest_ok (struct TALER_EXCHANGE_ReservesAttestHandle *rsh, TALER_exchange_online_reserve_attest_details_verify ( rs.details.ok.exchange_time, rs.details.ok.expiration_time, - &rsh->reserve_pub, + &prah->reserve_pub, attributes, &rs.details.ok.exchange_pub, &rs.details.ok.exchange_sig)) @@ -144,9 +159,9 @@ handle_reserves_attest_ok (struct TALER_EXCHANGE_ReservesAttestHandle *rsh, GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } - rsh->cb (rsh->cb_cls, - &rs); - rsh->cb = NULL; + prah->cb (prah->cb_cls, + &rs); + prah->cb = NULL; GNUNET_JSON_parse_free (spec); return GNUNET_OK; } @@ -156,7 +171,7 @@ handle_reserves_attest_ok (struct TALER_EXCHANGE_ReservesAttestHandle *rsh, * Function called when we're done processing the * HTTP /reserves-attest/$RID request. * - * @param cls the `struct TALER_EXCHANGE_ReservesAttestHandle` + * @param cls the `struct TALER_EXCHANGE_PostReservesAttestHandle` * @param response_code HTTP response code, 0 on error * @param response parsed JSON result, NULL on error */ @@ -165,14 +180,14 @@ handle_reserves_attest_finished (void *cls, long response_code, const void *response) { - struct TALER_EXCHANGE_ReservesAttestHandle *rsh = cls; + struct TALER_EXCHANGE_PostReservesAttestHandle *prah = cls; const json_t *j = response; - struct TALER_EXCHANGE_ReservePostAttestResult rs = { + struct TALER_EXCHANGE_PostReservesAttestResponse rs = { .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - rsh->job = NULL; + prah->job = NULL; switch (response_code) { case 0: @@ -180,7 +195,7 @@ handle_reserves_attest_finished (void *cls, break; case MHD_HTTP_OK: if (GNUNET_OK != - handle_reserves_attest_ok (rsh, + handle_reserves_attest_ok (prah, j)) { rs.hr.http_status = 0; @@ -229,30 +244,26 @@ handle_reserves_attest_finished (void *cls, (int) rs.hr.ec); break; } - if (NULL != rsh->cb) + if (NULL != prah->cb) { - rsh->cb (rsh->cb_cls, - &rs); - rsh->cb = NULL; + prah->cb (prah->cb_cls, + &rs); + prah->cb = NULL; } - TALER_EXCHANGE_reserves_attest_cancel (rsh); + TALER_EXCHANGE_post_reserves_attest_cancel (prah); } -struct TALER_EXCHANGE_ReservesAttestHandle * -TALER_EXCHANGE_reserves_attest ( +struct TALER_EXCHANGE_PostReservesAttestHandle * +TALER_EXCHANGE_post_reserves_attest_create ( struct GNUNET_CURL_Context *ctx, const char *url, struct TALER_EXCHANGE_Keys *keys, const struct TALER_ReservePrivateKeyP *reserve_priv, unsigned int attributes_length, - const char *attributes[const static attributes_length], - TALER_EXCHANGE_ReservesPostAttestCallback cb, - void *cb_cls) + const char *attributes[const static attributes_length]) { - struct TALER_EXCHANGE_ReservesAttestHandle *rsh; - CURL *eh; - char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; + struct TALER_EXCHANGE_PostReservesAttestHandle *prah; struct TALER_ReserveSignatureP reserve_sig; json_t *details; struct GNUNET_TIME_Timestamp ts; @@ -264,24 +275,60 @@ TALER_EXCHANGE_reserves_attest ( } details = json_array (); GNUNET_assert (NULL != details); - for (unsigned int i = 0; i<attributes_length; i++) + for (unsigned int i = 0; i < attributes_length; i++) { GNUNET_assert (0 == json_array_append_new (details, json_string (attributes[i]))); } - rsh = GNUNET_new (struct TALER_EXCHANGE_ReservesAttestHandle); - rsh->cb = cb; - rsh->cb_cls = cb_cls; + prah = GNUNET_new (struct TALER_EXCHANGE_PostReservesAttestHandle); + prah->ctx = ctx; + prah->base_url = GNUNET_strdup (url); + prah->keys = TALER_EXCHANGE_keys_incref (keys); GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, - &rsh->reserve_pub.eddsa_pub); + &prah->reserve_pub.eddsa_pub); + ts = GNUNET_TIME_timestamp_get (); + TALER_wallet_reserve_attest_request_sign (ts, + details, + reserve_priv, + &reserve_sig); + prah->body = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_data_auto ("reserve_sig", + &reserve_sig), + GNUNET_JSON_pack_timestamp ("request_timestamp", + ts), + GNUNET_JSON_pack_array_steal ("details", + details)); + if (NULL == prah->body) + { + GNUNET_break (0); + GNUNET_free (prah->base_url); + TALER_EXCHANGE_keys_decref (prah->keys); + GNUNET_free (prah); + return NULL; + } + return prah; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_reserves_attest_start ( + struct TALER_EXCHANGE_PostReservesAttestHandle *prah, + TALER_EXCHANGE_PostReservesAttestCallback cb, + TALER_EXCHANGE_POST_RESERVES_ATTEST_RESULT_CLOSURE *cb_cls) +{ + CURL *eh; + char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; + + prah->cb = cb; + prah->cb_cls = cb_cls; { char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2]; char *end; end = GNUNET_STRINGS_data_to_string ( - &rsh->reserve_pub, - sizeof (rsh->reserve_pub), + &prah->reserve_pub, + sizeof (prah->reserve_pub), pub_str, sizeof (pub_str)); *end = '\0'; @@ -290,76 +337,57 @@ TALER_EXCHANGE_reserves_attest ( "reserves-attest/%s", pub_str); } - rsh->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == rsh->url) - { - json_decref (details); - GNUNET_free (rsh); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (rsh->url); - if (NULL == eh) + prah->url = TALER_url_join (prah->base_url, + arg_str, + NULL); + if (NULL == prah->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + eh = TALER_EXCHANGE_curl_easy_get_ (prah->url); + if ( (NULL == eh) || + (GNUNET_OK != + TALER_curl_easy_post (&prah->post_ctx, + eh, + prah->body)) ) { GNUNET_break (0); - json_decref (details); - GNUNET_free (rsh->url); - GNUNET_free (rsh); - return NULL; + if (NULL != eh) + curl_easy_cleanup (eh); + GNUNET_free (prah->url); + prah->url = NULL; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } - ts = GNUNET_TIME_timestamp_get (); - TALER_wallet_reserve_attest_request_sign (ts, - details, - reserve_priv, - &reserve_sig); + prah->job = GNUNET_CURL_job_add2 (prah->ctx, + eh, + prah->post_ctx.headers, + &handle_reserves_attest_finished, + prah); + if (NULL == prah->job) { - json_t *attest_obj = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("reserve_sig", - &reserve_sig), - GNUNET_JSON_pack_timestamp ("request_timestamp", - ts), - GNUNET_JSON_pack_array_steal ("details", - details)); - - if (GNUNET_OK != - TALER_curl_easy_post (&rsh->post_ctx, - eh, - attest_obj)) - { - GNUNET_break (0); - curl_easy_cleanup (eh); - json_decref (attest_obj); - GNUNET_free (rsh->url); - GNUNET_free (rsh); - return NULL; - } - json_decref (attest_obj); + TALER_curl_easy_post_finished (&prah->post_ctx); + GNUNET_free (prah->url); + prah->url = NULL; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } - rsh->job = GNUNET_CURL_job_add2 (ctx, - eh, - rsh->post_ctx.headers, - &handle_reserves_attest_finished, - rsh); - rsh->keys = TALER_EXCHANGE_keys_incref (keys); - return rsh; + return TALER_EC_NONE; } void -TALER_EXCHANGE_reserves_attest_cancel ( - struct TALER_EXCHANGE_ReservesAttestHandle *rsh) +TALER_EXCHANGE_post_reserves_attest_cancel ( + struct TALER_EXCHANGE_PostReservesAttestHandle *prah) { - if (NULL != rsh->job) + if (NULL != prah->job) { - GNUNET_CURL_job_cancel (rsh->job); - rsh->job = NULL; + GNUNET_CURL_job_cancel (prah->job); + prah->job = NULL; } - TALER_curl_easy_post_finished (&rsh->post_ctx); - TALER_EXCHANGE_keys_decref (rsh->keys); - GNUNET_free (rsh->url); - GNUNET_free (rsh); + TALER_curl_easy_post_finished (&prah->post_ctx); + json_decref (prah->body); + GNUNET_free (prah->url); + GNUNET_free (prah->base_url); + TALER_EXCHANGE_keys_decref (prah->keys); + GNUNET_free (prah); } -/* end of exchange_api_reserves_attest.c */ +/* end of exchange_api_post-reserves-attest-RESERVE_PUB.c */ diff --git a/src/lib/exchange_api_post-reveal-melt.c b/src/lib/exchange_api_post-reveal-melt.c @@ -37,7 +37,7 @@ /** * Handler for a running reveal-melt request */ -struct TALER_EXCHANGE_RevealMeltHandle +struct TALER_EXCHANGE_PostRevealMeltHandle { /** * The url for the request @@ -45,6 +45,11 @@ struct TALER_EXCHANGE_RevealMeltHandle char *request_url; /** + * The exchange base URL. + */ + char *exchange_url; + + /** * CURL handle for the request job. */ struct GNUNET_CURL_Job *job; @@ -70,9 +75,14 @@ struct TALER_EXCHANGE_RevealMeltHandle struct MeltData md; /** + * The curl context + */ + struct GNUNET_CURL_Context *curl_ctx; + + /** * Callback to pass the result onto */ - TALER_EXCHANGE_RevealMeltCallback callback; + TALER_EXCHANGE_PostRevealMeltCallback callback; /** * Closure for @e callback @@ -91,10 +101,10 @@ struct TALER_EXCHANGE_RevealMeltHandle */ static enum GNUNET_GenericReturnValue reveal_melt_ok ( - struct TALER_EXCHANGE_RevealMeltHandle *mrh, + struct TALER_EXCHANGE_PostRevealMeltHandle *mrh, const json_t *j_response) { - struct TALER_EXCHANGE_RevealMeltResponse response = { + struct TALER_EXCHANGE_PostRevealMeltResponse response = { .hr.reply = j_response, .hr.http_status = MHD_HTTP_OK, }; @@ -209,9 +219,9 @@ handle_reveal_melt_finished ( long response_code, const void *response) { - struct TALER_EXCHANGE_RevealMeltHandle *mrh = cls; + struct TALER_EXCHANGE_PostRevealMeltHandle *mrh = cls; const json_t *j_response = response; - struct TALER_EXCHANGE_RevealMeltResponse awr = { + struct TALER_EXCHANGE_PostRevealMeltResponse awr = { .hr.reply = j_response, .hr.http_status = (unsigned int) response_code }; @@ -236,7 +246,7 @@ handle_reveal_melt_finished ( break; } GNUNET_assert (NULL == mrh->callback); - TALER_EXCHANGE_reveal_melt_cancel (mrh); + TALER_EXCHANGE_post_reveal_melt_cancel (mrh); return; } case MHD_HTTP_BAD_REQUEST: @@ -280,7 +290,7 @@ handle_reveal_melt_finished ( } mrh->callback (mrh->callback_cls, &awr); - TALER_EXCHANGE_reveal_melt_cancel (mrh); + TALER_EXCHANGE_post_reveal_melt_cancel (mrh); } @@ -293,7 +303,7 @@ handle_reveal_melt_finished ( static void perform_protocol ( struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_RevealMeltHandle *mrh) + struct TALER_EXCHANGE_PostRevealMeltHandle *mrh) { CURL *curlh; json_t *j_batch_seeds; @@ -353,56 +363,70 @@ perform_protocol ( GNUNET_break (0); if (NULL != curlh) curl_easy_cleanup (curlh); - TALER_EXCHANGE_reveal_melt_cancel (mrh); + /* caller must call _cancel to free mrh */ } } -struct TALER_EXCHANGE_RevealMeltHandle * -TALER_EXCHANGE_reveal_melt ( +struct TALER_EXCHANGE_PostRevealMeltHandle * +TALER_EXCHANGE_post_reveal_melt_create ( struct GNUNET_CURL_Context *curl_ctx, const char *exchange_url, - const struct TALER_EXCHANGE_RevealMeltInput *reveal_melt_input, - TALER_EXCHANGE_RevealMeltCallback reveal_cb, - void *reveal_cb_cls) + const struct TALER_EXCHANGE_RevealMeltInput *reveal_melt_input) { - struct TALER_EXCHANGE_RevealMeltHandle *mrh = - GNUNET_new (struct TALER_EXCHANGE_RevealMeltHandle); - mrh->callback = reveal_cb; - mrh->callback_cls = reveal_cb_cls; - mrh->reveal_input = reveal_melt_input; - mrh->num_expected_coins = reveal_melt_input->melt_input->num_fresh_denom_pubs; - mrh->request_url = TALER_url_join (exchange_url, - "reveal-melt", - NULL); - if (NULL == mrh->request_url) - { - GNUNET_break (0); - GNUNET_free (mrh); - return NULL; - } + struct TALER_EXCHANGE_PostRevealMeltHandle *mrh; + if (reveal_melt_input->num_blinding_values != reveal_melt_input->melt_input->num_fresh_denom_pubs) { GNUNET_break (0); - GNUNET_free (mrh); return NULL; } + mrh = GNUNET_new (struct TALER_EXCHANGE_PostRevealMeltHandle); + mrh->reveal_input = reveal_melt_input; + mrh->num_expected_coins = reveal_melt_input->melt_input->num_fresh_denom_pubs; + mrh->curl_ctx = curl_ctx; + mrh->exchange_url = GNUNET_strdup (exchange_url); TALER_EXCHANGE_get_melt_data ( reveal_melt_input->rms, reveal_melt_input->melt_input, reveal_melt_input->blinding_seed, reveal_melt_input->blinding_values, &mrh->md); - perform_protocol (curl_ctx, - mrh); return mrh; } +enum TALER_ErrorCode +TALER_EXCHANGE_post_reveal_melt_start ( + struct TALER_EXCHANGE_PostRevealMeltHandle *mrh, + TALER_EXCHANGE_PostRevealMeltCallback reveal_cb, + TALER_EXCHANGE_POST_REVEAL_MELT_RESULT_CLOSURE *reveal_cb_cls) +{ + mrh->callback = reveal_cb; + mrh->callback_cls = reveal_cb_cls; + mrh->request_url = TALER_url_join (mrh->exchange_url, + "reveal-melt", + NULL); + if (NULL == mrh->request_url) + { + GNUNET_break (0); + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + } + perform_protocol (mrh->curl_ctx, + mrh); + if (NULL == mrh->job) + { + GNUNET_break (0); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + return TALER_EC_NONE; +} + + void -TALER_EXCHANGE_reveal_melt_cancel ( - struct TALER_EXCHANGE_RevealMeltHandle *mrh) +TALER_EXCHANGE_post_reveal_melt_cancel ( + struct TALER_EXCHANGE_PostRevealMeltHandle *mrh) { if (NULL != mrh->job) { @@ -412,5 +436,6 @@ TALER_EXCHANGE_reveal_melt_cancel ( TALER_curl_easy_post_finished (&mrh->post_ctx); TALER_EXCHANGE_free_melt_data (&mrh->md); GNUNET_free (mrh->request_url); + GNUNET_free (mrh->exchange_url); GNUNET_free (mrh); } diff --git a/src/lib/exchange_api_post-reveal-withdraw.c b/src/lib/exchange_api_post-reveal-withdraw.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2023-2025 Taler Systems SA + Copyright (C) 2023-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -16,7 +16,7 @@ */ /** * @file lib/exchange_api_post-reveal-withdraw.c - * @brief Implementation of /reveal-withdraw requests + * @brief Implementation of POST /reveal-withdraw requests * @author Özgür Kesim */ @@ -35,15 +35,16 @@ #include "taler/taler_signatures.h" #include "exchange_api_curl_defaults.h" + /** - * Handler for a running reveal-withdraw request + * Handler for a running POST /reveal-withdraw request */ -struct TALER_EXCHANGE_RevealWithdrawHandle +struct TALER_EXCHANGE_PostRevealWithdrawHandle { /** - * The commitment from the previous call withdraw + * The commitment from the previous call to withdraw */ - const struct TALER_HashBlindedPlanchetsP *planchets_h; + struct TALER_HashBlindedPlanchetsP planchets_h; /** * Number of coins for which to reveal tuples of seeds @@ -56,11 +57,21 @@ struct TALER_EXCHANGE_RevealWithdrawHandle struct TALER_RevealWithdrawMasterSeedsP seeds; /** + * The exchange base URL. + */ + char *exchange_url; + + /** * The url for the reveal request */ char *request_url; /** + * The curl context + */ + struct GNUNET_CURL_Context *curl_ctx; + + /** * CURL handle for the request job. */ struct GNUNET_CURL_Job *job; @@ -71,12 +82,12 @@ struct TALER_EXCHANGE_RevealWithdrawHandle struct TALER_CURL_PostContext post_ctx; /** - * Callback + * Callback to pass the result to */ - TALER_EXCHANGE_RevealWithdrawCallback callback; + TALER_EXCHANGE_PostRevealWithdrawCallback callback; /** - * Reveal + * Closure for @e callback */ void *callback_cls; }; @@ -84,7 +95,7 @@ struct TALER_EXCHANGE_RevealWithdrawHandle /** * We got a 200 OK response for the /reveal-withdraw operation. - * Extract the signed blindedcoins and return it to the caller. + * Extract the signed blinded coins and return it to the caller. * * @param wrh operation handle * @param j_response reply from the exchange @@ -92,10 +103,10 @@ struct TALER_EXCHANGE_RevealWithdrawHandle */ static enum GNUNET_GenericReturnValue reveal_withdraw_ok ( - struct TALER_EXCHANGE_RevealWithdrawHandle *wrh, + struct TALER_EXCHANGE_PostRevealWithdrawHandle *wrh, const json_t *j_response) { - struct TALER_EXCHANGE_RevealWithdrawResponse response = { + struct TALER_EXCHANGE_PostRevealWithdrawResponse response = { .hr.reply = j_response, .hr.http_status = MHD_HTTP_OK, }; @@ -165,7 +176,7 @@ reveal_withdraw_ok ( * Function called when we're done processing the * HTTP /reveal-withdraw request. * - * @param cls the `struct TALER_EXCHANGE_RevealWithdrawHandle` + * @param cls the `struct TALER_EXCHANGE_PostRevealWithdrawHandle` * @param response_code The HTTP response code * @param response response data */ @@ -175,9 +186,9 @@ handle_reveal_withdraw_finished ( long response_code, const void *response) { - struct TALER_EXCHANGE_RevealWithdrawHandle *wrh = cls; + struct TALER_EXCHANGE_PostRevealWithdrawHandle *wrh = cls; const json_t *j_response = response; - struct TALER_EXCHANGE_RevealWithdrawResponse awr = { + struct TALER_EXCHANGE_PostRevealWithdrawResponse awr = { .hr.reply = j_response, .hr.http_status = (unsigned int) response_code }; @@ -202,7 +213,7 @@ handle_reveal_withdraw_finished ( break; } GNUNET_assert (NULL == wrh->callback); - TALER_EXCHANGE_reveal_withdraw_cancel (wrh); + TALER_EXCHANGE_post_reveal_withdraw_cancel (wrh); return; } case MHD_HTTP_BAD_REQUEST: @@ -246,20 +257,18 @@ handle_reveal_withdraw_finished ( } wrh->callback (wrh->callback_cls, &awr); - TALER_EXCHANGE_reveal_withdraw_cancel (wrh); + TALER_EXCHANGE_post_reveal_withdraw_cancel (wrh); } /** * Call /reveal-withdraw * - * @param curl_ctx The context for CURL * @param wrh The handler */ static void perform_protocol ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_RevealWithdrawHandle *wrh) + struct TALER_EXCHANGE_PostRevealWithdrawHandle *wrh) { CURL *curlh; json_t *j_array_of_secrets; @@ -279,7 +288,7 @@ perform_protocol ( j_request_body = GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("planchets_h", - wrh->planchets_h), + &wrh->planchets_h), GNUNET_JSON_pack_array_steal ("disclosed_batch_seeds", j_array_of_secrets)); GNUNET_assert (NULL != j_request_body); @@ -295,7 +304,7 @@ perform_protocol ( } wrh->job = GNUNET_CURL_job_add2 ( - curl_ctx, + wrh->curl_ctx, curlh, wrh->post_ctx.headers, &handle_reveal_withdraw_finished, @@ -305,62 +314,71 @@ perform_protocol ( GNUNET_break (0); if (NULL != curlh) curl_easy_cleanup (curlh); - TALER_EXCHANGE_reveal_withdraw_cancel (wrh); + /* caller must call _cancel to free wrh */ } - - return; } -struct TALER_EXCHANGE_RevealWithdrawHandle * -TALER_EXCHANGE_reveal_withdraw ( +struct TALER_EXCHANGE_PostRevealWithdrawHandle * +TALER_EXCHANGE_post_reveal_withdraw_create ( struct GNUNET_CURL_Context *curl_ctx, const char *exchange_url, size_t num_coins, - const struct TALER_HashBlindedPlanchetsP *planchets_h, - const struct TALER_RevealWithdrawMasterSeedsP *seeds, - TALER_EXCHANGE_RevealWithdrawCallback reveal_cb, - void *reveal_cb_cls) + const struct TALER_HashBlindedPlanchetsP *h_planchets, + const struct TALER_RevealWithdrawMasterSeedsP *seeds) { - struct TALER_EXCHANGE_RevealWithdrawHandle *wrh = - GNUNET_new (struct TALER_EXCHANGE_RevealWithdrawHandle); - wrh->planchets_h = planchets_h; + struct TALER_EXCHANGE_PostRevealWithdrawHandle *wrh; + + wrh = GNUNET_new (struct TALER_EXCHANGE_PostRevealWithdrawHandle); + wrh->curl_ctx = curl_ctx; + wrh->exchange_url = GNUNET_strdup (exchange_url); wrh->num_coins = num_coins; + wrh->planchets_h = *h_planchets; wrh->seeds = *seeds; - wrh->callback = reveal_cb; - wrh->callback_cls = reveal_cb_cls; - wrh->request_url = TALER_url_join (exchange_url, - "reveal-withdraw", - NULL); - if (NULL == wrh->request_url) + return wrh; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_post_reveal_withdraw_start ( + struct TALER_EXCHANGE_PostRevealWithdrawHandle *prwh, + TALER_EXCHANGE_PostRevealWithdrawCallback cb, + TALER_EXCHANGE_POST_REVEAL_WITHDRAW_RESULT_CLOSURE *cb_cls) +{ + prwh->callback = cb; + prwh->callback_cls = cb_cls; + prwh->request_url = TALER_url_join (prwh->exchange_url, + "reveal-withdraw", + NULL); + if (NULL == prwh->request_url) { GNUNET_break (0); - GNUNET_free (wrh); - return NULL; + return TALER_EC_GENERIC_CONFIGURATION_INVALID; } - - perform_protocol (curl_ctx, wrh); - - return wrh; + perform_protocol (prwh); + if (NULL == prwh->job) + { + GNUNET_break (0); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + return TALER_EC_NONE; } void -TALER_EXCHANGE_reveal_withdraw_cancel ( - struct TALER_EXCHANGE_RevealWithdrawHandle *wrh) +TALER_EXCHANGE_post_reveal_withdraw_cancel ( + struct TALER_EXCHANGE_PostRevealWithdrawHandle *prwh) { - if (NULL != wrh->job) + if (NULL != prwh->job) { - GNUNET_CURL_job_cancel (wrh->job); - wrh->job = NULL; + GNUNET_CURL_job_cancel (prwh->job); + prwh->job = NULL; } - TALER_curl_easy_post_finished (&wrh->post_ctx); - - if (NULL != wrh->request_url) - GNUNET_free (wrh->request_url); - - GNUNET_free (wrh); + TALER_curl_easy_post_finished (&prwh->post_ctx); + GNUNET_free (prwh->request_url); + GNUNET_free (prwh->exchange_url); + GNUNET_free (prwh); } -/* exchange_api_reveal_withdraw.c */ +/* exchange_api_post-reveal-withdraw.c */ diff --git a/src/lib/exchange_api_post-withdraw.c b/src/lib/exchange_api_post-withdraw.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2023-2025 Taler Systems SA + Copyright (C) 2023-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -19,11 +19,6 @@ * @brief Implementation of /withdraw requests * @author Özgür Kesim */ -/** - * We want the "dangerous" exports here as these are OUR exports - * and we want to check that the prototypes match. - */ -#define TALER_TESTING_EXPORTS_DANGEROUS 1 #include "taler/platform.h" #include <gnunet/gnunet_common.h> #include <jansson.h> @@ -62,109 +57,73 @@ struct CoinCandidate /** - * Closure for a call to /blinding-prepare, contains data that is needed to process - * the result. + * Data we keep per coin in the batch. + * This is copied from and generated out of the input provided + * by the client. */ -struct BlindingPrepareClosure +struct CoinData { /** - * Number of coins in the blinding-prepare step. - * Not that this number might be smaller than the total number - * of coins in the withdraw, as the prepare is only necessary - * for CS denominations + * The denomination of the coin. */ - size_t num_prepare_coins; + struct TALER_EXCHANGE_DenomPublicKey denom_pub; /** - * Array of @e num_prepare_coins of data per coin + * The Candidates for the coin. If the batch is not age-restricted, + * only index 0 is used. */ - struct BlindingPrepareCoinData - { - /** - * Pointer to the candidate in CoinData.candidates, - * to continue to build its contents based on the results from /blinding-prepare - */ - struct CoinCandidate *candidate; - - /** - * Planchet to finally generate in the corresponding candidate - * in CoindData.planchet_details - */ - struct TALER_PlanchetDetail *planchet; - - /** - * Denomination information, needed for the - * step after /blinding-prepare - */ - const struct TALER_DenominationPublicKey *denom_pub; - - /** - * True, if denomination supports age restriction - */ - bool age_denom; - - /** - * The index into the array of returned values from the call to - * /blinding-prepare that are to be used for this coin. - */ - size_t cs_idx; - - } *coins; + struct CoinCandidate candidates[TALER_CNC_KAPPA]; /** - * Number of seeds requested. This may differ from @e num_prepare_coins - * in case of a withdraw with required age proof, in which case - * @e num_prepare_coins = TALER_CNC_KAPPA * @e num_seeds + * Details of the planchet(s). If the batch is not age-restricted, + * only index 0 is used. */ - size_t num_nonces; + struct TALER_PlanchetDetail planchet_details[TALER_CNC_KAPPA]; +}; + +/** + * Per-CS-coin data needed to complete the coin after /blinding-prepare. + */ +struct BlindingPrepareCoinData +{ /** - * Array of @e num_nonces calculated nonces. + * Pointer to the candidate in CoinData.candidates, + * to continue to build its contents based on the results from /blinding-prepare */ - union GNUNET_CRYPTO_BlindSessionNonce *nonces; + struct CoinCandidate *candidate; /** - * Handler to the originating call to /withdraw, needed to either - * cancel the running withdraw request (on failure of the current call - * to /blinding-prepare), or to eventually perform the protocol, once all - * blinding-prepare requests have successfully finished. + * Planchet to finally generate in the corresponding candidate + * in CoinData.planchet_details */ - struct TALER_EXCHANGE_WithdrawHandle *withdraw_handle; + struct TALER_PlanchetDetail *planchet; -}; - - -/** - * Data we keep per coin in the batch. - * This is copied from and generated out of the input provided - * by the client. - */ -struct CoinData -{ /** - * The denomination of the coin. + * Denomination information, needed for the + * step after /blinding-prepare */ - struct TALER_EXCHANGE_DenomPublicKey denom_pub; + const struct TALER_DenominationPublicKey *denom_pub; /** - * The Candidates for the coin. If the batch is not age-restricted, - * only index 0 is used. + * True, if denomination supports age restriction */ - struct CoinCandidate candidates[TALER_CNC_KAPPA]; + bool age_denom; /** - * Details of the planchet(s). If the batch is not age-restricted, - * only index 0 is used. + * The index into the array of returned values from the call to + * /blinding-prepare that are to be used for this coin. */ - struct TALER_PlanchetDetail planchet_details[TALER_CNC_KAPPA]; + size_t cs_idx; + }; /** * A /withdraw request-handle for calls with pre-blinded planchets. - * Returned by TALER_EXCHANGE_withdraw_blinded. + * Returned by TALER_EXCHANGE_post_withdraw_blinded_create. */ -struct TALER_EXCHANGE_WithdrawBlindedHandle +struct TALER_EXCHANGE_PostWithdrawBlindedHandle { /** @@ -195,8 +154,7 @@ struct TALER_EXCHANGE_WithdrawBlindedHandle /** * Seed used for the derival of blinding factors for denominations - * with Clause-Schnorr cipher. We derive this from the master seed - * for the withdraw, but independent from the other planchet seeds. + * with Clause-Schnorr cipher. */ const struct TALER_BlindingMasterSeedP *blinding_seed; @@ -211,13 +169,13 @@ struct TALER_EXCHANGE_WithdrawBlindedHandle struct TALER_Amount fee; /** - * Is this call for age-restriced coins, with age proof? + * Is this call for age-restricted coins, with age proof? */ bool with_age_proof; /** * If @e with_age_proof is true or @max_age is > 0, - * the age mask to use, extracted from the denominations. + * the age mask to use, extracted from the denominations. * MUST be the same for all denominations. */ struct TALER_AgeMask age_mask; @@ -252,8 +210,8 @@ struct TALER_EXCHANGE_WithdrawBlindedHandle TALER_EXCHANGE_WithdrawBlindedAgeRestrictedCoinInput *with_age_proof_input; /** - * The blinded planchet input for the call to /withdraw via - * TALER_EXCHANGE_withdraw_blinded, for age-unrestricted coins. + * The blinded planchet input for the call to /withdraw, + * for age-unrestricted coins. */ const struct TALER_EXCHANGE_WithdrawBlindedCoinInput *input; @@ -282,19 +240,20 @@ struct TALER_EXCHANGE_WithdrawBlindedHandle /** * Function to call with withdraw response results. */ - TALER_EXCHANGE_WithdrawBlindedCallback callback; + TALER_EXCHANGE_PostWithdrawBlindedCallback callback; /** - * Closure for @e blinded_callback + * Closure for @e callback */ void *callback_cls; }; + /** * A /withdraw request-handle for calls from * a wallet, i. e. when blinding data is available. */ -struct TALER_EXCHANGE_WithdrawHandle +struct TALER_EXCHANGE_PostWithdrawHandle { /** @@ -358,7 +317,6 @@ struct TALER_EXCHANGE_WithdrawHandle * If @e with_age_proof is true, the age mask, extracted * from the denominations. * MUST be the same for all denominations. - * */ struct TALER_AgeMask age_mask; @@ -388,21 +346,93 @@ struct TALER_EXCHANGE_WithdrawHandle /** * Function to call with withdraw response results. */ - TALER_EXCHANGE_WithdrawCallback callback; + TALER_EXCHANGE_PostWithdrawCallback callback; /** * Closure for @e callback */ void *callback_cls; - /* The handler for the call to /blinding-prepare, needed for CS denominations */ - struct TALER_EXCHANGE_BlindingPrepareHandle *blinding_prepare_handle; + /** + * The handler for the call to /blinding-prepare, needed for CS denominations. + * NULL until _start is called for CS denominations, or when no CS denoms. + */ + struct TALER_EXCHANGE_PostBlindingPrepareHandle *blinding_prepare_handle; + + /** + * The Handler for the actual call to the exchange + */ + struct TALER_EXCHANGE_PostWithdrawBlindedHandle *withdraw_blinded_handle; + + /** + * Number of CS denomination coin entries in @e bp_coins. + * Zero if no CS denominations. + */ + size_t num_bp_coins; + + /** + * Array of @e num_bp_coins coin data for the blinding-prepare step. + */ + struct BlindingPrepareCoinData *bp_coins; + + /** + * Number of nonces in @e bp_nonces. + */ + size_t num_bp_nonces; + + /** + * Array of @e num_bp_nonces nonces for CS denominations. + */ + union GNUNET_CRYPTO_BlindSessionNonce *bp_nonces; + + /** + * Nonce keys for the blinding-prepare call. + */ + struct TALER_EXCHANGE_NonceKey *bp_nonce_keys; + + /** + * Number of nonce keys in @e bp_nonce_keys. + */ + size_t num_bp_nonce_keys; + + /** + * Array of @e init_num_coins denomination public keys. + * NULL after _start is called. + */ + struct TALER_EXCHANGE_DenomPublicKey *init_denoms_pub; - /* The Handler for the actual call to the exchange */ - struct TALER_EXCHANGE_WithdrawBlindedHandle *withdraw_blinded_handle; + /** + * Number of coins provided in @e init_denoms_pub. + */ + size_t init_num_coins; + + struct + { + + /** + * True if @e blinding_seed is filled, that is, if + * any of the denominations is of cipher type CS + */ + bool has_blinding_seed; + + /** + * Seed used for the derivation of blinding factors for denominations + * with Clause-Schnorr cipher. We derive this from the master seed + * for the withdraw, but independent from the other planchet seeds. + * Only valid when @e has_blinding_seed is true; + */ + struct TALER_BlindingMasterSeedP blinding_seed; + + } options; }; +/* Forward declarations */ +static enum TALER_ErrorCode +call_withdraw_blinded ( + struct TALER_EXCHANGE_PostWithdrawHandle *wh); + + /** * We got a 200 OK response for the /withdraw operation. * Extract the signatures and return them to the caller. @@ -413,10 +443,10 @@ struct TALER_EXCHANGE_WithdrawHandle */ static enum GNUNET_GenericReturnValue withdraw_blinded_ok ( - struct TALER_EXCHANGE_WithdrawBlindedHandle *wbh, + struct TALER_EXCHANGE_PostWithdrawBlindedHandle *wbh, const json_t *j_response) { - struct TALER_EXCHANGE_WithdrawBlindedResponse response = { + struct TALER_EXCHANGE_PostWithdrawBlindedResponse response = { .hr.reply = j_response, .hr.http_status = MHD_HTTP_OK, }; @@ -501,10 +531,10 @@ withdraw_blinded_ok ( */ static enum GNUNET_GenericReturnValue withdraw_blinded_created ( - struct TALER_EXCHANGE_WithdrawBlindedHandle *wbh, + struct TALER_EXCHANGE_PostWithdrawBlindedHandle *wbh, const json_t *j_response) { - struct TALER_EXCHANGE_WithdrawBlindedResponse response = { + struct TALER_EXCHANGE_PostWithdrawBlindedResponse response = { .hr.reply = j_response, .hr.http_status = MHD_HTTP_CREATED, .details.created.planchets_h = wbh->planchets_h, @@ -555,7 +585,7 @@ withdraw_blinded_created ( * Function called when we're done processing the * HTTP /withdraw request. * - * @param cls the `struct TALER_EXCHANGE_WithdrawBlindedHandle` + * @param cls the `struct TALER_EXCHANGE_PostWithdrawBlindedHandle` * @param response_code The HTTP response code * @param response response data */ @@ -565,9 +595,9 @@ handle_withdraw_blinded_finished ( long response_code, const void *response) { - struct TALER_EXCHANGE_WithdrawBlindedHandle *wbh = cls; + struct TALER_EXCHANGE_PostWithdrawBlindedHandle *wbh = cls; const json_t *j_response = response; - struct TALER_EXCHANGE_WithdrawBlindedResponse wbr = { + struct TALER_EXCHANGE_PostWithdrawBlindedResponse wbr = { .hr.reply = j_response, .hr.http_status = (unsigned int) response_code }; @@ -591,7 +621,7 @@ handle_withdraw_blinded_finished ( break; } GNUNET_assert (NULL == wbh->callback); - TALER_EXCHANGE_withdraw_blinded_cancel (wbh); + TALER_EXCHANGE_post_withdraw_blinded_cancel (wbh); return; } case MHD_HTTP_CREATED: @@ -606,7 +636,7 @@ handle_withdraw_blinded_finished ( break; } GNUNET_assert (NULL == wbh->callback); - TALER_EXCHANGE_withdraw_blinded_cancel (wbh); + TALER_EXCHANGE_post_withdraw_blinded_cancel (wbh); return; case MHD_HTTP_BAD_REQUEST: /* This should never happen, either us or the exchange is buggy @@ -687,7 +717,7 @@ handle_withdraw_blinded_finished ( } wbh->callback (wbh->callback_cls, &wbr); - TALER_EXCHANGE_withdraw_blinded_cancel (wbh); + TALER_EXCHANGE_post_withdraw_blinded_cancel (wbh); } @@ -695,10 +725,11 @@ handle_withdraw_blinded_finished ( * Runs the actual withdraw operation with the blinded planchets. * * @param[in,out] wbh withdraw blinded handle + * @return #TALER_EC_NONE on success, error code on failure */ -static void +static enum TALER_ErrorCode perform_withdraw_protocol ( - struct TALER_EXCHANGE_WithdrawBlindedHandle *wbh) + struct TALER_EXCHANGE_PostWithdrawBlindedHandle *wbh) { #define FAIL_IF(cond) \ do { \ @@ -709,7 +740,7 @@ perform_withdraw_protocol ( } \ } while (0) - json_t *j_denoms = NULL; + json_t * j_denoms = NULL; json_t *j_planchets = NULL; json_t *j_request_body = NULL; CURL *curlh = NULL; @@ -936,7 +967,7 @@ perform_withdraw_protocol ( FAIL_IF (NULL == wbh->job); /* No errors, return */ - return; + return TALER_EC_NONE; ERROR: if (NULL != coins_hctx) @@ -949,27 +980,26 @@ ERROR: json_decref (j_request_body); if (NULL != curlh) curl_easy_cleanup (curlh); - TALER_EXCHANGE_withdraw_blinded_cancel (wbh); - return; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; #undef FAIL_IF } /** - * @brief Callback to copy the results from the call to TALER_withdraw_blinded - * in the non-age-restricted case to the result for the originating call from TALER_withdraw. + * @brief Callback to copy the results from the call to post_withdraw_blinded + * in the non-age-restricted case to the result for the originating call. * - * @param cls struct TALER_WithdrawHandle + * @param cls struct TALER_EXCHANGE_PostWithdrawHandle * @param wbr The response */ static void copy_results ( void *cls, - const struct TALER_EXCHANGE_WithdrawBlindedResponse *wbr) + const struct TALER_EXCHANGE_PostWithdrawBlindedResponse *wbr) { /* The original handle from the top-level call to withdraw */ - struct TALER_EXCHANGE_WithdrawHandle *wh = cls; - struct TALER_EXCHANGE_WithdrawResponse resp = { + struct TALER_EXCHANGE_PostWithdrawHandle *wh = cls; + struct TALER_EXCHANGE_PostWithdrawResponse resp = { .hr = wbr->hr, }; @@ -1062,27 +1092,27 @@ copy_results ( &resp); wh->callback = NULL; } - TALER_EXCHANGE_withdraw_cancel (wh); + TALER_EXCHANGE_post_withdraw_cancel (wh); } /** - * @brief Callback to copy the results from the call to TALER_withdraw_blinded - * in the age-restricted case to the result for the originating call from TALER_withdraw. + * @brief Callback to copy the results from the call to post_withdraw_blinded + * in the age-restricted case. * - * @param cls struct TALER_WithdrawHandle + * @param cls struct TALER_EXCHANGE_PostWithdrawHandle * @param wbr The response */ static void copy_results_with_age_proof ( void *cls, - const struct TALER_EXCHANGE_WithdrawBlindedResponse *wbr) + const struct TALER_EXCHANGE_PostWithdrawBlindedResponse *wbr) { /* The original handle from the top-level call to withdraw */ - struct TALER_EXCHANGE_WithdrawHandle *wh = cls; + struct TALER_EXCHANGE_PostWithdrawHandle *wh = cls; uint8_t k = wbr->details.created.noreveal_index; struct TALER_EXCHANGE_WithdrawCoinPrivateDetails details[wh->num_coins]; - struct TALER_EXCHANGE_WithdrawResponse resp = { + struct TALER_EXCHANGE_PostWithdrawResponse resp = { .hr = wbr->hr, }; @@ -1125,19 +1155,23 @@ copy_results_with_age_proof ( wh->callback_cls, &resp); wh->callback = NULL; - TALER_EXCHANGE_withdraw_cancel (wh); + TALER_EXCHANGE_post_withdraw_cancel (wh); } /** - * @brief Prepares and executes TALER_EXCHANGE_withdraw_blinded. - * If there were CS-denominations involved, started once the all calls - * to /blinding-prepare are done. + * @brief Prepares and starts the actual TALER_EXCHANGE_post_withdraw_blinded + * operation once all blinding-prepare steps are done (or immediately if + * there are no CS denominations). + * + * @param wh The withdraw handle + * @return #TALER_EC_NONE on success, error code on failure */ -static void +static enum TALER_ErrorCode call_withdraw_blinded ( - struct TALER_EXCHANGE_WithdrawHandle *wh) + struct TALER_EXCHANGE_PostWithdrawHandle *wh) { + enum TALER_ErrorCode ec; GNUNET_assert (NULL == wh->blinding_prepare_handle); @@ -1159,16 +1193,25 @@ call_withdraw_blinded ( } wh->withdraw_blinded_handle = - TALER_EXCHANGE_withdraw_blinded ( + TALER_EXCHANGE_post_withdraw_blinded_create ( wh->curl_ctx, wh->keys, wh->exchange_url, wh->reserve_priv, wh->has_blinding_seed ? &wh->blinding_seed : NULL, wh->num_coins, - input, - &copy_results, - wh); + input); + if (NULL == wh->withdraw_blinded_handle) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + ec = TALER_EXCHANGE_post_withdraw_blinded_start ( + wh->withdraw_blinded_handle, + &copy_results, + wh); + if (TALER_EC_NONE != ec) + { + wh->withdraw_blinded_handle = NULL; + return ec; + } } else { /* age restricted case */ @@ -1189,34 +1232,47 @@ call_withdraw_blinded ( } wh->withdraw_blinded_handle = - TALER_EXCHANGE_withdraw_blinded_with_age_proof ( + TALER_EXCHANGE_post_withdraw_blinded_create ( wh->curl_ctx, wh->keys, wh->exchange_url, wh->reserve_priv, wh->has_blinding_seed ? &wh->blinding_seed : NULL, - wh->max_age, wh->num_coins, - ari, - &copy_results_with_age_proof, - wh); + NULL); + if (NULL == wh->withdraw_blinded_handle) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + TALER_EXCHANGE_post_withdraw_blinded_set_options ( + wh->withdraw_blinded_handle, + TALER_EXCHANGE_post_withdraw_blinded_option_with_age_proof ( + wh->max_age, + ari)); + ec = TALER_EXCHANGE_post_withdraw_blinded_start ( + wh->withdraw_blinded_handle, + &copy_results_with_age_proof, + wh); + if (TALER_EC_NONE != ec) + { + wh->withdraw_blinded_handle = NULL; + return ec; + } } + return TALER_EC_NONE; } /** - * @brief Function called when /blinding-prepare is finished + * @brief Function called when /blinding-prepare is finished. * - * @param cls the `struct BlindingPrepareClosure *` + * @param cls the `struct TALER_EXCHANGE_PostWithdrawHandle *` * @param bpr replies from the /blinding-prepare request */ static void blinding_prepare_done ( void *cls, - const struct TALER_EXCHANGE_BlindingPrepareResponse *bpr) + const struct TALER_EXCHANGE_PostBlindingPrepareResponse *bpr) { - struct BlindingPrepareClosure *bpcls = cls; - struct TALER_EXCHANGE_WithdrawHandle *wh = bpcls->withdraw_handle; + struct TALER_EXCHANGE_PostWithdrawHandle *wh = cls; wh->blinding_prepare_handle = NULL; switch (bpr->hr.http_status) @@ -1227,12 +1283,12 @@ blinding_prepare_done ( size_t num = bpr->details.ok.num_blinding_values; GNUNET_assert (0 != num); - GNUNET_assert (num == bpcls->num_nonces); - for (size_t i = 0; i < bpcls->num_prepare_coins; i++) + GNUNET_assert (num == wh->num_bp_nonces); + for (size_t i = 0; i < wh->num_bp_coins; i++) { - struct TALER_PlanchetDetail *planchet = bpcls->coins[i].planchet; - struct CoinCandidate *can = bpcls->coins[i].candidate; - size_t cs_idx = bpcls->coins[i].cs_idx; + struct TALER_PlanchetDetail *planchet = wh->bp_coins[i].planchet; + struct CoinCandidate *can = wh->bp_coins[i].candidate; + size_t cs_idx = wh->bp_coins[i].cs_idx; GNUNET_assert (NULL != can); GNUNET_assert (NULL != planchet); @@ -1260,10 +1316,10 @@ blinding_prepare_done ( can->planchet_detail.blinded_planchet */ if (GNUNET_OK != TALER_planchet_prepare ( - bpcls->coins[i].denom_pub, + wh->bp_coins[i].denom_pub, &can->details.blinding_values, &can->details.blinding_key, - &bpcls->nonces[cs_idx], + &wh->bp_nonces[cs_idx], &can->details.coin_priv, &can->details.h_age_commitment, &can->details.h_coin_pub, @@ -1282,50 +1338,76 @@ blinding_prepare_done ( /* /blinding-prepare is done, we can now perform the * actual withdraw operation */ if (success) - call_withdraw_blinded (wh); - goto cleanup; + { + enum TALER_ErrorCode ec = call_withdraw_blinded (wh); + + if (TALER_EC_NONE != ec) + { + struct TALER_EXCHANGE_PostWithdrawResponse resp = { + .hr.ec = ec, + .hr.http_status = 0, + }; + + wh->callback ( + wh->callback_cls, + &resp); + wh->callback = NULL; + TALER_EXCHANGE_post_withdraw_cancel (wh); + } + return; + } + else + { + /* prepare completed but coin setup failed */ + struct TALER_EXCHANGE_PostWithdrawResponse resp = { + .hr.ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, + .hr.http_status = 0, + }; + + wh->callback ( + wh->callback_cls, + &resp); + wh->callback = NULL; + TALER_EXCHANGE_post_withdraw_cancel (wh); + return; + } } default: { /* We got an error condition during blinding prepare that we need to report */ - struct TALER_EXCHANGE_WithdrawResponse resp = { + struct TALER_EXCHANGE_PostWithdrawResponse resp = { .hr = bpr->hr }; wh->callback ( wh->callback_cls, &resp); - wh->callback = NULL; break; } } - TALER_EXCHANGE_withdraw_cancel (wh); -cleanup: - GNUNET_free (bpcls->coins); - GNUNET_free (bpcls->nonces); - GNUNET_free (bpcls); + TALER_EXCHANGE_post_withdraw_cancel (wh); } /** - * @brief Prepares non age-restricted coins for the call to withdraw and - * calculates the total amount with fees. - * For denomination with CS as cipher, initiates the preflight to retrieve the - * bpcls-parameter via /blinding-prepare. - * Note that only one of the three parameters seed, tuples or secrets must not be NULL + * @brief Prepares coins for the call to withdraw: + * Performs synchronous crypto for RSA denominations, and stores + * the data needed for the async /blinding-prepare step for CS denominations. + * Does NOT start any async operations. * * @param wh The handler to the withdraw * @param num_coins Number of coins to withdraw * @param max_age The maximum age to commit to * @param denoms_pub Array @e num_coins of denominations - * @param seed master seed from which to derive @e num_coins secrets and blinding, if @e blinding_seed is NULL - * @param blinding_seed master seed for the blinding. Might be NULL, in which case the blinding_seed is derived from @e seed + * @param seed master seed from which to derive @e num_coins secrets + * @param blinding_seed master seed for the blinding. Might be NULL, in which + * case the blinding_seed is derived from @e seed * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ static enum GNUNET_GenericReturnValue prepare_coins ( - struct TALER_EXCHANGE_WithdrawHandle *wh, + struct TALER_EXCHANGE_PostWithdrawHandle *wh, size_t num_coins, uint8_t max_age, const struct TALER_EXCHANGE_DenomPublicKey *denoms_pub, @@ -1333,7 +1415,6 @@ prepare_coins ( const struct TALER_BlindingMasterSeedP *blinding_seed) { size_t cs_num = 0; - struct BlindingPrepareClosure *cs_closure; uint8_t kappa; #define FAIL_IF(cond) \ @@ -1364,13 +1445,9 @@ prepare_coins ( } if (wh->with_age_proof) - { kappa = TALER_CNC_KAPPA; - } else - { kappa = 1; - } { struct TALER_PlanchetMasterSecretP secrets[kappa][num_coins]; @@ -1405,21 +1482,19 @@ prepare_coins ( memset (cs_nonce_keys, 0, sizeof(cs_nonce_keys)); - cs_closure = GNUNET_new (struct BlindingPrepareClosure); - cs_closure->withdraw_handle = wh; - cs_closure->num_prepare_coins = cs_num * kappa; + wh->num_bp_coins = cs_num * kappa; GNUNET_assert ((1 == kappa) || (cs_num * kappa > cs_num)); - cs_closure->coins = - GNUNET_new_array (cs_closure->num_prepare_coins, + wh->bp_coins = + GNUNET_new_array (wh->num_bp_coins, struct BlindingPrepareCoinData); - cs_closure->num_nonces = cs_num; - cs_closure->nonces = - GNUNET_new_array (cs_closure->num_nonces, + wh->num_bp_nonces = cs_num; + wh->bp_nonces = + GNUNET_new_array (wh->num_bp_nonces, union GNUNET_CRYPTO_BlindSessionNonce); - } - else - { - cs_closure = NULL; + wh->num_bp_nonce_keys = cs_num; + wh->bp_nonce_keys = + GNUNET_new_array (wh->num_bp_nonce_keys, + struct TALER_EXCHANGE_NonceKey); } for (uint32_t i = 0; i < wh->num_coins; i++) @@ -1442,10 +1517,12 @@ prepare_coins ( if (GNUNET_CRYPTO_BSA_CS == cd->denom_pub.key.bsign_pub_key->cipher) { - GNUNET_assert (cs_denom_idx<cs_num); + GNUNET_assert (cs_denom_idx < cs_num); cs_indices[cs_denom_idx] = i; cs_nonce_keys[cs_denom_idx].cnc_num = i; cs_nonce_keys[cs_denom_idx].pk = &cd->denom_pub; + wh->bp_nonce_keys[cs_denom_idx].cnc_num = i; + wh->bp_nonce_keys[cs_denom_idx].pk = &cd->denom_pub; cs_denom_idx++; } @@ -1461,8 +1538,8 @@ prepare_coins ( can->details.secret = secrets[k][i]; /* * The age restriction needs to be set on a coin if the denomination - * support age restriction. Note that his is regardless of weither - * with_age_proof is set or not. + * support age restriction. Note that this is regardless of whether + * with_age_proof is set or not. */ if (age_denom) { @@ -1504,20 +1581,17 @@ prepare_coins ( TALER_coin_ev_hash (&planchet->blinded_planchet, &planchet->denom_pub_hash, &can->blinded_coin_h); - break; case GNUNET_CRYPTO_BSA_CS: { - /** - * Prepare the nonce and save the index and the denomination for the callback - * after the call to blinding-prepare - */ - cs_closure->coins[cs_coin_idx].candidate = can; - cs_closure->coins[cs_coin_idx].planchet = planchet; - cs_closure->coins[cs_coin_idx].denom_pub = &cd->denom_pub.key; - cs_closure->coins[cs_coin_idx].cs_idx = i; - cs_closure->coins[cs_coin_idx].age_denom = age_denom; + /* Prepare the nonce and save the index and the denomination for + * the callback after the call to blinding-prepare */ + wh->bp_coins[cs_coin_idx].candidate = can; + wh->bp_coins[cs_coin_idx].planchet = planchet; + wh->bp_coins[cs_coin_idx].denom_pub = &cd->denom_pub.key; + wh->bp_coins[cs_coin_idx].cs_idx = i; + wh->bp_coins[cs_coin_idx].age_denom = age_denom; cs_coin_idx++; break; } @@ -1529,9 +1603,9 @@ prepare_coins ( if (0 < cs_num) { - if (NULL != blinding_seed) + if (NULL != wh->options.has_blinding_seed) { - wh->blinding_seed = *blinding_seed; + wh->blinding_seed = wh->options.blinding_seed; } else { @@ -1546,253 +1620,222 @@ prepare_coins ( false, /* not for melt */ cs_num, cs_indices, - cs_closure->nonces); - - wh->blinding_prepare_handle = - TALER_EXCHANGE_blinding_prepare_for_withdraw ( - wh->curl_ctx, - wh->exchange_url, - &wh->blinding_seed, - cs_num, - cs_nonce_keys, - &blinding_prepare_done, - cs_closure); - FAIL_IF (NULL == wh->blinding_prepare_handle); + wh->bp_nonces); } } return GNUNET_OK; ERROR: - if (0<cs_num) + if (0 < cs_num) { - GNUNET_free (cs_closure->nonces); - GNUNET_free (cs_closure); + GNUNET_free (wh->bp_nonces); + wh->bp_nonces = NULL; + GNUNET_free (wh->bp_coins); + wh->bp_coins = NULL; + GNUNET_free (wh->bp_nonce_keys); + wh->bp_nonce_keys = NULL; + wh->num_bp_coins = 0; + wh->num_bp_nonces = 0; + wh->num_bp_nonce_keys = 0; } - TALER_EXCHANGE_withdraw_cancel (wh); return GNUNET_SYSERR; #undef FAIL_IF - } /** - * Prepare a withdraw handle for both, the non-restricted - * and age-restricted case. + * Allocate and set up the common fields of a PostWithdrawHandle. * * @param curl_ctx The curl context to use * @param keys The keys from the exchange * @param exchange_url The base url to the exchange - * @param reserve_priv The private key of the exchange - * @param res_cb The callback to call on response - * @param res_cb_cls The closure to pass to the callback + * @param reserve_priv The private key of the reserve + * @return the handle */ -static struct TALER_EXCHANGE_WithdrawHandle * +static struct TALER_EXCHANGE_PostWithdrawHandle * setup_withdraw_handle ( struct GNUNET_CURL_Context *curl_ctx, struct TALER_EXCHANGE_Keys *keys, const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - TALER_EXCHANGE_WithdrawCallback res_cb, - void *res_cb_cls) + const struct TALER_ReservePrivateKeyP *reserve_priv) { - struct TALER_EXCHANGE_WithdrawHandle *wh; + struct TALER_EXCHANGE_PostWithdrawHandle *wh; - wh = GNUNET_new (struct TALER_EXCHANGE_WithdrawHandle); + wh = GNUNET_new (struct TALER_EXCHANGE_PostWithdrawHandle); wh->exchange_url = exchange_url; wh->keys = TALER_EXCHANGE_keys_incref (keys); wh->curl_ctx = curl_ctx; wh->reserve_priv = reserve_priv; - wh->callback = res_cb; - wh->callback_cls = res_cb_cls; return wh; } -struct TALER_EXCHANGE_WithdrawHandle * -TALER_EXCHANGE_withdraw_extra_blinding_seed ( +struct TALER_EXCHANGE_PostWithdrawHandle * +TALER_EXCHANGE_post_withdraw_create ( struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, const char *exchange_url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_ReservePrivateKeyP *reserve_priv, size_t num_coins, const struct TALER_EXCHANGE_DenomPublicKey denoms_pub[static num_coins], const struct TALER_WithdrawMasterSeedP *seed, - const struct TALER_BlindingMasterSeedP *blinding_seed, - uint8_t opaque_max_age, - TALER_EXCHANGE_WithdrawCallback res_cb, - void *res_cb_cls) + uint8_t opaque_max_age) { - struct TALER_EXCHANGE_WithdrawHandle *wh; + struct TALER_EXCHANGE_PostWithdrawHandle *wh; wh = setup_withdraw_handle (curl_ctx, keys, exchange_url, - reserve_priv, - res_cb, - res_cb_cls); + reserve_priv); GNUNET_assert (NULL != wh); - wh->with_age_proof = false; - - if (GNUNET_OK != - prepare_coins (wh, - num_coins, - opaque_max_age, - denoms_pub, - seed, - blinding_seed)) + wh->seed = *seed; + wh->max_age = opaque_max_age; + wh->init_num_coins = num_coins; + wh->init_denoms_pub = GNUNET_new_array (num_coins, + struct TALER_EXCHANGE_DenomPublicKey); + for (size_t i = 0; i < num_coins; i++) { - GNUNET_free (wh); - return NULL; + wh->init_denoms_pub[i] = denoms_pub[i]; + TALER_denom_pub_copy (&wh->init_denoms_pub[i].key, + &denoms_pub[i].key); } - /* If there were no CS denominations, we can now perform the actual - * withdraw protocol. Otherwise, there are calls to /blinding-prepare - * in flight and once they finish, the withdraw-protocol will be - * called from within the blinding_prepare_done-function. - */ - if (NULL == wh->blinding_prepare_handle) - call_withdraw_blinded (wh); - return wh; } -struct TALER_EXCHANGE_WithdrawHandle * -TALER_EXCHANGE_withdraw ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - size_t num_coins, - const struct TALER_EXCHANGE_DenomPublicKey denoms_pub[static num_coins], - const struct TALER_WithdrawMasterSeedP *seed, - uint8_t opaque_max_age, - TALER_EXCHANGE_WithdrawCallback res_cb, - void *res_cb_cls) +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_post_withdraw_set_options_ ( + struct TALER_EXCHANGE_PostWithdrawHandle *pwh, + unsigned int num_options, + const struct TALER_EXCHANGE_PostWithdrawOptionValue options[]) { - return TALER_EXCHANGE_withdraw_extra_blinding_seed ( - curl_ctx, - keys, - exchange_url, - reserve_priv, - num_coins, - denoms_pub, - seed, - NULL, - opaque_max_age, - res_cb, - res_cb_cls - ); + for (unsigned int i = 0; i < num_options; i++) + { + const struct TALER_EXCHANGE_PostWithdrawOptionValue *opt = &options[i]; + switch (opt->option) + { + case TALER_EXCHANGE_POST_WITHDRAW_OPTION_END: + return GNUNET_OK; + case TALER_EXCHANGE_POST_WITHDRAW_OPTION_WITH_AGE_PROOF: + pwh->with_age_proof = true; + pwh->max_age = opt->details.max_age; + break; + case TALER_EXCHANGE_POST_WITHDRAW_OPTION_BLINDING_SEED: + pwh->options.has_blinding_seed = true; + pwh->options.blinding_seed = opt->details.blinding_seed; + break; + } + } + return GNUNET_OK; } -struct TALER_EXCHANGE_WithdrawHandle * -TALER_EXCHANGE_withdraw_with_age_proof_extra_blinding_seed ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - size_t num_coins, - const struct TALER_EXCHANGE_DenomPublicKey denoms_pub[static num_coins], - const struct TALER_WithdrawMasterSeedP *seed, - const struct TALER_BlindingMasterSeedP *blinding_seed, - uint8_t max_age, - TALER_EXCHANGE_WithdrawCallback res_cb, - void *res_cb_cls) +enum TALER_ErrorCode +TALER_EXCHANGE_post_withdraw_start ( + struct TALER_EXCHANGE_PostWithdrawHandle *pwh, + TALER_EXCHANGE_PostWithdrawCallback cb, + TALER_EXCHANGE_POST_WITHDRAW_RESULT_CLOSURE *cb_cls) { - struct TALER_EXCHANGE_WithdrawHandle *wh; - - wh = setup_withdraw_handle (curl_ctx, - keys, - exchange_url, - reserve_priv, - res_cb, - res_cb_cls); - GNUNET_assert (NULL != wh); - - wh->with_age_proof = true; + pwh->callback = cb; + pwh->callback_cls = cb_cls; + /* Run prepare_coins now that options have been applied */ if (GNUNET_OK != - prepare_coins (wh, - num_coins, - max_age, - denoms_pub, - seed, - blinding_seed)) + prepare_coins (pwh, + pwh->init_num_coins, + pwh->max_age, + pwh->init_denoms_pub, + &pwh->seed, + pwh->has_blinding_seed + ? &pwh->blinding_seed + : NULL)) { - GNUNET_free (wh); - return NULL; + GNUNET_free (pwh->coin_data); + for (size_t i = 0; i < pwh->init_num_coins; i++) + TALER_denom_pub_free (&pwh->init_denoms_pub[i].key); + GNUNET_free (pwh->init_denoms_pub); + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } + /* Free init data - no longer needed after prepare_coins */ + for (size_t i = 0; i < pwh->init_num_coins; i++) + TALER_denom_pub_free (&pwh->init_denoms_pub[i].key); + GNUNET_free (pwh->init_denoms_pub); - /* If there were no CS denominations, we can now perform the actual - * withdraw protocol. Otherwise, there are calls to /blinding-prepare - * in flight and once they finish, the withdraw-protocol will be - * called from within the blinding_prepare_done-function. - */ - if (NULL == wh->blinding_prepare_handle) - call_withdraw_blinded (wh); - - return wh; -} - + if (0 < pwh->num_bp_coins) + { + /* There are CS denominations; start the blinding-prepare request */ + pwh->blinding_prepare_handle = + TALER_EXCHANGE_post_blinding_prepare_for_withdraw_create ( + pwh->curl_ctx, + pwh->exchange_url, + &pwh->blinding_seed, + pwh->num_bp_nonce_keys, + pwh->bp_nonce_keys); + if (NULL == pwh->blinding_prepare_handle) + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + { + enum TALER_ErrorCode ec = + TALER_EXCHANGE_post_blinding_prepare_start ( + pwh->blinding_prepare_handle, + &blinding_prepare_done, + pwh); + if (TALER_EC_NONE != ec) + { + pwh->blinding_prepare_handle = NULL; + return ec; + } + } + return TALER_EC_NONE; + } -struct TALER_EXCHANGE_WithdrawHandle * -TALER_EXCHANGE_withdraw_with_age_proof ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - size_t num_coins, - const struct TALER_EXCHANGE_DenomPublicKey denoms_pub[static num_coins], - const struct TALER_WithdrawMasterSeedP *seed, - uint8_t max_age, - TALER_EXCHANGE_WithdrawCallback res_cb, - void *res_cb_cls) -{ - return TALER_EXCHANGE_withdraw_with_age_proof_extra_blinding_seed ( - curl_ctx, - keys, - exchange_url, - reserve_priv, - num_coins, - denoms_pub, - seed, - NULL, - max_age, - res_cb, - res_cb_cls); + /* No CS denominations; proceed directly to the withdraw protocol */ + return call_withdraw_blinded (pwh); } void -TALER_EXCHANGE_withdraw_cancel ( - struct TALER_EXCHANGE_WithdrawHandle *wh) +TALER_EXCHANGE_post_withdraw_cancel ( + struct TALER_EXCHANGE_PostWithdrawHandle *wh) { uint8_t kappa = wh->with_age_proof ? TALER_CNC_KAPPA : 1; + /* Cleanup init data if _start was never called (or failed) */ + if (NULL != wh->init_denoms_pub) + { + for (size_t i = 0; i < wh->init_num_coins; i++) + TALER_denom_pub_free (&wh->init_denoms_pub[i].key); + GNUNET_free (wh->init_denoms_pub); + } /* Cleanup coin data */ - for (unsigned int i = 0; i<wh->num_coins; i++) + if (NULL != wh->coin_data) { - struct CoinData *cd = &wh->coin_data[i]; - - for (uint8_t k = 0; k < kappa; k++) + for (unsigned int i = 0; i < wh->num_coins; i++) { - struct TALER_PlanchetDetail *planchet = &cd->planchet_details[k]; - struct CoinCandidate *can = &cd->candidates[k]; + struct CoinData *cd = &wh->coin_data[i]; - TALER_blinded_planchet_free (&planchet->blinded_planchet); - TALER_denom_ewv_free (&can->details.blinding_values); - TALER_age_commitment_proof_free (&can->details.age_commitment_proof); + for (uint8_t k = 0; k < kappa; k++) + { + struct TALER_PlanchetDetail *planchet = &cd->planchet_details[k]; + struct CoinCandidate *can = &cd->candidates[k]; + + TALER_blinded_planchet_free (&planchet->blinded_planchet); + TALER_denom_ewv_free (&can->details.blinding_values); + TALER_age_commitment_proof_free (&can->details.age_commitment_proof); + } + TALER_denom_pub_free (&cd->denom_pub.key); } - TALER_denom_pub_free (&cd->denom_pub.key); } - TALER_EXCHANGE_blinding_prepare_cancel (wh->blinding_prepare_handle); - TALER_EXCHANGE_withdraw_blinded_cancel (wh->withdraw_blinded_handle); + TALER_EXCHANGE_post_blinding_prepare_cancel (wh->blinding_prepare_handle); wh->blinding_prepare_handle = NULL; + TALER_EXCHANGE_post_withdraw_blinded_cancel (wh->withdraw_blinded_handle); wh->withdraw_blinded_handle = NULL; + GNUNET_free (wh->bp_coins); + GNUNET_free (wh->bp_nonces); + GNUNET_free (wh->bp_nonce_keys); GNUNET_free (wh->coin_data); TALER_EXCHANGE_keys_decref (wh->keys); GNUNET_free (wh); @@ -1810,28 +1853,21 @@ TALER_EXCHANGE_withdraw_cancel ( * @param keys the exchange keys * @param exchange_url the url to the exchange * @param reserve_priv the reserve's private key - * @param res_cb the callback on result - * @param res_cb_cls the closure to pass on to the callback - * @return the handler + * @return the handler, NULL on error */ -static struct TALER_EXCHANGE_WithdrawBlindedHandle * +static struct TALER_EXCHANGE_PostWithdrawBlindedHandle * setup_handler_common ( struct GNUNET_CURL_Context *curl_ctx, struct TALER_EXCHANGE_Keys *keys, const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - TALER_EXCHANGE_WithdrawBlindedCallback res_cb, - void *res_cb_cls) + const struct TALER_ReservePrivateKeyP *reserve_priv) { - - struct TALER_EXCHANGE_WithdrawBlindedHandle *wbh = - GNUNET_new (struct TALER_EXCHANGE_WithdrawBlindedHandle); + struct TALER_EXCHANGE_PostWithdrawBlindedHandle *wbh = + GNUNET_new (struct TALER_EXCHANGE_PostWithdrawBlindedHandle); wbh->keys = TALER_EXCHANGE_keys_incref (keys); wbh->curl_ctx = curl_ctx; wbh->reserve_priv = reserve_priv; - wbh->callback = res_cb; - wbh->callback_cls = res_cb_cls; wbh->request_url = TALER_url_join (exchange_url, "withdraw", NULL); @@ -1843,73 +1879,71 @@ setup_handler_common ( } -struct TALER_EXCHANGE_WithdrawBlindedHandle * -TALER_EXCHANGE_withdraw_blinded ( +struct TALER_EXCHANGE_PostWithdrawBlindedHandle * +TALER_EXCHANGE_post_withdraw_blinded_create ( struct GNUNET_CURL_Context *curl_ctx, struct TALER_EXCHANGE_Keys *keys, const char *exchange_url, const struct TALER_ReservePrivateKeyP *reserve_priv, const struct TALER_BlindingMasterSeedP *blinding_seed, size_t num_input, - const struct TALER_EXCHANGE_WithdrawBlindedCoinInput - blinded_input[static num_input], - TALER_EXCHANGE_WithdrawBlindedCallback res_cb, - void *res_cb_cls) + const struct TALER_EXCHANGE_WithdrawBlindedCoinInput *blinded_input) { - struct TALER_EXCHANGE_WithdrawBlindedHandle *wbh = + struct TALER_EXCHANGE_PostWithdrawBlindedHandle *wbh = setup_handler_common (curl_ctx, keys, exchange_url, - reserve_priv, - res_cb, - res_cb_cls); + reserve_priv); wbh->with_age_proof = false; wbh->num_input = num_input; wbh->blinded.input = blinded_input; wbh->blinding_seed = blinding_seed; - perform_withdraw_protocol (wbh); return wbh; } -struct TALER_EXCHANGE_WithdrawBlindedHandle * -TALER_EXCHANGE_withdraw_blinded_with_age_proof ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_BlindingMasterSeedP *blinding_seed, - uint8_t max_age, - unsigned int num_input, - const struct TALER_EXCHANGE_WithdrawBlindedAgeRestrictedCoinInput - blinded_input[static num_input], - TALER_EXCHANGE_WithdrawBlindedCallback res_cb, - void *res_cb_cls) +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_post_withdraw_blinded_set_options_ ( + struct TALER_EXCHANGE_PostWithdrawBlindedHandle *pwbh, + unsigned int num_options, + const struct TALER_EXCHANGE_PostWithdrawBlindedOptionValue options[]) { - struct TALER_EXCHANGE_WithdrawBlindedHandle *wbh = - setup_handler_common (curl_ctx, - keys, - exchange_url, - reserve_priv, - res_cb, - res_cb_cls); + for (unsigned int i = 0; i < num_options; i++) + { + const struct TALER_EXCHANGE_PostWithdrawBlindedOptionValue *opt = + &options[i]; + switch (opt->option) + { + case TALER_EXCHANGE_POST_WITHDRAW_BLINDED_OPTION_END: + return GNUNET_OK; + case TALER_EXCHANGE_POST_WITHDRAW_BLINDED_OPTION_WITH_AGE_PROOF: + pwbh->with_age_proof = true; + pwbh->max_age = opt->details.with_age_proof.max_age; + pwbh->blinded.with_age_proof_input = opt->details.with_age_proof.input; + break; + } + } + return GNUNET_OK; +} - wbh->with_age_proof = true; - wbh->max_age = max_age; - wbh->num_input = num_input; - wbh->blinded.with_age_proof_input = blinded_input; - wbh->blinding_seed = blinding_seed; - perform_withdraw_protocol (wbh); - return wbh; +enum TALER_ErrorCode +TALER_EXCHANGE_post_withdraw_blinded_start ( + struct TALER_EXCHANGE_PostWithdrawBlindedHandle *pwbh, + TALER_EXCHANGE_PostWithdrawBlindedCallback cb, + TALER_EXCHANGE_POST_WITHDRAW_BLINDED_RESULT_CLOSURE *cb_cls) +{ + pwbh->callback = cb; + pwbh->callback_cls = cb_cls; + return perform_withdraw_protocol (pwbh); } void -TALER_EXCHANGE_withdraw_blinded_cancel ( - struct TALER_EXCHANGE_WithdrawBlindedHandle *wbh) +TALER_EXCHANGE_post_withdraw_blinded_cancel ( + struct TALER_EXCHANGE_PostWithdrawBlindedHandle *wbh) { if (NULL == wbh) return; @@ -1925,4 +1959,4 @@ TALER_EXCHANGE_withdraw_blinded_cancel ( } -/* exchange_api_withdraw.c */ +/* exchange_api_post-withdraw.c */ diff --git a/src/testing/testing_api_cmd_age_withdraw.c b/src/testing/testing_api_cmd_age_withdraw.c @@ -65,7 +65,7 @@ struct AgeWithdrawState /** * The age-withdraw handle */ - struct TALER_EXCHANGE_WithdrawHandle *handle; + struct TALER_EXCHANGE_PostWithdrawHandle *handle; /** * Exchange base URL. Only used as offered trait. @@ -114,11 +114,10 @@ struct AgeWithdrawState /** * The @e num_coins denomination public keys that are provided - * to the `TALER_EXCHANGE_withdraw_with_age_proof` API. + * to the `TALER_EXCHANGE_post_withdraw()` API. */ struct TALER_EXCHANGE_DenomPublicKey *denoms_pub; - /** * The master seed from which all the other seeds are derived from */ @@ -185,7 +184,7 @@ struct AgeWithdrawState static void age_withdraw_cb ( void *cls, - const struct TALER_EXCHANGE_WithdrawResponse *response) + const struct TALER_EXCHANGE_PostWithdrawResponse *response) { struct AgeWithdrawState *aws = cls; struct TALER_TESTING_Interpreter *is = aws->is; @@ -352,24 +351,30 @@ age_withdraw_run ( /* Execute the age-restricted variant of withdraw protocol */ aws->handle = - TALER_EXCHANGE_withdraw_with_age_proof ( + TALER_EXCHANGE_post_withdraw_create ( TALER_TESTING_interpreter_get_context (is), - keys, TALER_TESTING_get_exchange_url (is), + keys, rp, aws->num_coins, aws->denoms_pub, &aws->seed, - aws->max_age, - &age_withdraw_cb, - aws); - + aws->max_age); if (NULL == aws->handle) { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); return; } + GNUNET_assert (GNUNET_OK == + TALER_EXCHANGE_post_withdraw_set_options ( + aws->handle, + TALER_EXCHANGE_post_withdraw_option_with_age_proof ( + aws->max_age))); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_withdraw_start (aws->handle, + &age_withdraw_cb, + aws)); } @@ -391,7 +396,7 @@ age_withdraw_cleanup ( { TALER_TESTING_command_incomplete (aws->is, cmd->label); - TALER_EXCHANGE_withdraw_cancel (aws->handle); + TALER_EXCHANGE_post_withdraw_cancel (aws->handle); aws->handle = NULL; } @@ -586,7 +591,7 @@ struct AgeRevealWithdrawState /** * The handle to the reveal-operation */ - struct TALER_EXCHANGE_RevealWithdrawHandle *handle; + struct TALER_EXCHANGE_PostRevealWithdrawHandle *handle; /** @@ -611,7 +616,7 @@ struct AgeRevealWithdrawState static void age_reveal_withdraw_cb ( void *cls, - const struct TALER_EXCHANGE_RevealWithdrawResponse *response) + const struct TALER_EXCHANGE_PostRevealWithdrawResponse *response) { struct AgeRevealWithdrawState *awrs = cls; struct TALER_TESTING_Interpreter *is = awrs->is; @@ -716,14 +721,18 @@ age_reveal_withdraw_run ( } awrs->handle = - TALER_EXCHANGE_reveal_withdraw ( + TALER_EXCHANGE_post_reveal_withdraw_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), aws->num_coins, &aws->planchets_h, - &revealed_seeds, - age_reveal_withdraw_cb, - awrs); + &revealed_seeds); + GNUNET_assert (NULL != awrs->handle); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_reveal_withdraw_start ( + awrs->handle, + &age_reveal_withdraw_cb, + awrs)); } } @@ -746,7 +755,7 @@ age_reveal_withdraw_cleanup ( { TALER_TESTING_command_incomplete (awrs->is, cmd->label); - TALER_EXCHANGE_reveal_withdraw_cancel (awrs->handle); + TALER_EXCHANGE_post_reveal_withdraw_cancel (awrs->handle); awrs->handle = NULL; } GNUNET_free (awrs->denom_sigs); diff --git a/src/testing/testing_api_cmd_auditor_add_denom_sig.c b/src/testing/testing_api_cmd_auditor_add_denom_sig.c @@ -38,7 +38,7 @@ struct AuditorAddDenomSigState /** * Auditor enable handle while operation is running. */ - struct TALER_EXCHANGE_AuditorAddDenominationHandle *dh; + struct TALER_EXCHANGE_PostAuditorsHandle *dh; /** * Our interpreter. @@ -72,7 +72,7 @@ struct AuditorAddDenomSigState static void denom_sig_add_cb ( void *cls, - const struct TALER_EXCHANGE_AuditorAddDenominationResponse *adr) + const struct TALER_EXCHANGE_PostAuditorsResponse *adr) { struct AuditorAddDenomSigState *ds = cls; const struct TALER_EXCHANGE_HttpResponse *hr = &adr->hr; @@ -103,7 +103,6 @@ auditor_add_run (void *cls, { struct AuditorAddDenomSigState *ds = cls; struct TALER_AuditorSignatureP auditor_sig; - struct TALER_DenominationHashP h_denom_pub; const struct TALER_EXCHANGE_DenomPublicKey *dk; const struct TALER_AuditorPublicKeyP *auditor_pub; const struct TALER_TESTING_Command *auditor_cmd; @@ -185,20 +184,22 @@ auditor_add_run (void *cls, auditor_priv, &auditor_sig); } - ds->dh = TALER_EXCHANGE_add_auditor_denomination ( + ds->dh = TALER_EXCHANGE_post_auditors_create ( TALER_TESTING_interpreter_get_context (is), exchange_url, - &h_denom_pub, + &dk->h_key, auditor_pub, - &auditor_sig, - &denom_sig_add_cb, - ds); + &auditor_sig); if (NULL == ds->dh) { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); return; } + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_auditors_start (ds->dh, + &denom_sig_add_cb, + ds)); } @@ -219,7 +220,7 @@ auditor_add_cleanup (void *cls, { TALER_TESTING_command_incomplete (ds->is, cmd->label); - TALER_EXCHANGE_add_auditor_denomination_cancel (ds->dh); + TALER_EXCHANGE_post_auditors_cancel (ds->dh); ds->dh = NULL; } GNUNET_free (ds); diff --git a/src/testing/testing_api_cmd_batch_deposit.c b/src/testing/testing_api_cmd_batch_deposit.c @@ -144,7 +144,7 @@ struct BatchDepositState /** * Deposit handle while operation is running. */ - struct TALER_EXCHANGE_BatchDepositHandle *dh; + struct TALER_EXCHANGE_PostBatchDepositHandle *dh; /** * Array of coins to batch-deposit. @@ -224,7 +224,7 @@ struct BatchDepositState */ static void batch_deposit_cb (void *cls, - const struct TALER_EXCHANGE_BatchDepositResult *dr) + const struct TALER_EXCHANGE_PostBatchDepositResponse *dr) { struct BatchDepositState *ds = cls; @@ -472,15 +472,13 @@ batch_deposit_run (void *cls, TALER_merchant_contract_sign (&h_contract_terms, &ds->account_priv.merchant_priv, &dcd.merchant_sig); - ds->dh = TALER_EXCHANGE_batch_deposit ( + ds->dh = TALER_EXCHANGE_post_batch_deposit_create ( TALER_TESTING_interpreter_get_context (is), exchange_url, TALER_TESTING_get_keys (is), &dcd, ds->num_coins, cdds, - &batch_deposit_cb, - ds, &ec); } if (NULL == ds->dh) @@ -492,6 +490,9 @@ batch_deposit_run (void *cls, TALER_TESTING_interpreter_fail (is); return; } + TALER_EXCHANGE_post_batch_deposit_start (ds->dh, + &batch_deposit_cb, + ds); } @@ -512,7 +513,7 @@ batch_deposit_cleanup (void *cls, { TALER_TESTING_command_incomplete (ds->is, cmd->label); - TALER_EXCHANGE_batch_deposit_cancel (ds->dh); + TALER_EXCHANGE_post_batch_deposit_cancel (ds->dh); ds->dh = NULL; } if (NULL != ds->retry_task) diff --git a/src/testing/testing_api_cmd_batch_withdraw.c b/src/testing/testing_api_cmd_batch_withdraw.c @@ -111,7 +111,7 @@ struct BatchWithdrawState /** * Withdraw handle (while operation is running). */ - struct TALER_EXCHANGE_WithdrawHandle *wsh; + struct TALER_EXCHANGE_PostWithdrawHandle *wsh; /** * Array of coin states. @@ -178,7 +178,7 @@ struct BatchWithdrawState static void batch_withdraw_cb (void *cls, const struct - TALER_EXCHANGE_WithdrawResponse *wr) + TALER_EXCHANGE_PostWithdrawResponse *wr) { struct BatchWithdrawState *ws = cls; struct TALER_TESTING_Interpreter *is = ws->is; @@ -359,17 +359,15 @@ batch_withdraw_run (void *cls, ws->reserve_history.type = TALER_EXCHANGE_RTT_WITHDRAWAL; - ws->wsh = TALER_EXCHANGE_withdraw ( + ws->wsh = TALER_EXCHANGE_post_withdraw_create ( TALER_TESTING_interpreter_get_context (is), - keys, TALER_TESTING_get_exchange_url (is), + keys, rp, ws->num_coins, denoms_pub, &ws->seed, - 0, - &batch_withdraw_cb, - ws); + 0); for (unsigned int i = 0; i<ws->num_coins; i++) TALER_denom_pub_free (&denoms_pub[i].key); if (NULL == ws->wsh) @@ -378,6 +376,10 @@ batch_withdraw_run (void *cls, TALER_TESTING_interpreter_fail (is); return; } + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_withdraw_start (ws->wsh, + &batch_withdraw_cb, + ws)); } @@ -398,7 +400,7 @@ batch_withdraw_cleanup (void *cls, { TALER_TESTING_command_incomplete (ws->is, cmd->label); - TALER_EXCHANGE_withdraw_cancel (ws->wsh); + TALER_EXCHANGE_post_withdraw_cancel (ws->wsh); ws->wsh = NULL; } for (unsigned int i = 0; i<ws->num_coins; i++) diff --git a/src/testing/testing_api_cmd_coin_history.c b/src/testing/testing_api_cmd_coin_history.c @@ -47,7 +47,7 @@ struct HistoryState /** * Handle to the "coin history" operation. */ - struct TALER_EXCHANGE_CoinsHistoryHandle *rsh; + struct TALER_EXCHANGE_GetCoinsHistoryHandle *rsh; /** * Expected coin balance. @@ -344,7 +344,7 @@ analyze_command (void *cls, */ static void coin_history_cb (void *cls, - const struct TALER_EXCHANGE_CoinHistory *rs) + const struct TALER_EXCHANGE_GetCoinsHistoryResponse *rs) { struct HistoryState *ss = cls; struct TALER_TESTING_Interpreter *is = ss->is; @@ -525,13 +525,15 @@ history_run (void *cls, } GNUNET_CRYPTO_eddsa_key_get_public (&ss->coin_priv->eddsa_priv, &ss->coin_pub.eddsa_pub); - ss->rsh = TALER_EXCHANGE_coins_history ( + ss->rsh = TALER_EXCHANGE_get_coins_history_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), - ss->coin_priv, - 0, - &coin_history_cb, - ss); + ss->coin_priv); + GNUNET_assert (NULL != ss->rsh); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_get_coins_history_start (ss->rsh, + &coin_history_cb, + ss)); } @@ -581,7 +583,7 @@ history_cleanup (void *cls, { TALER_TESTING_command_incomplete (ss->is, cmd->label); - TALER_EXCHANGE_coins_history_cancel (ss->rsh); + TALER_EXCHANGE_get_coins_history_cancel (ss->rsh); ss->rsh = NULL; } GNUNET_free (ss); diff --git a/src/testing/testing_api_cmd_contract_get.c b/src/testing/testing_api_cmd_contract_get.c @@ -63,7 +63,7 @@ struct ContractGetState /** * ContractGet handle while operation is running. */ - struct TALER_EXCHANGE_ContractsGetHandle *dh; + struct TALER_EXCHANGE_GetContractsHandle *dh; /** * Interpreter state. @@ -93,7 +93,7 @@ struct ContractGetState */ static void get_cb (void *cls, - const struct TALER_EXCHANGE_ContractGetResponse *dr) + const struct TALER_EXCHANGE_GetContractsResponse *dr) { struct ContractGetState *ds = cls; const struct TALER_TESTING_Command *ref; @@ -213,12 +213,10 @@ get_run (void *cls, return; } ds->contract_priv = *contract_priv; - ds->dh = TALER_EXCHANGE_contract_get ( + ds->dh = TALER_EXCHANGE_get_contracts_create ( TALER_TESTING_interpreter_get_context (is), exchange_url, - contract_priv, - &get_cb, - ds); + contract_priv); if (NULL == ds->dh) { GNUNET_break (0); @@ -227,6 +225,17 @@ get_run (void *cls, TALER_TESTING_interpreter_fail (is); return; } + if (TALER_EC_NONE != + TALER_EXCHANGE_get_contracts_start (ds->dh, + &get_cb, + ds)) + { + GNUNET_break (0); + TALER_EXCHANGE_get_contracts_cancel (ds->dh); + ds->dh = NULL; + TALER_TESTING_interpreter_fail (is); + return; + } } @@ -247,7 +256,7 @@ get_cleanup (void *cls, { TALER_TESTING_command_incomplete (ds->is, cmd->label); - TALER_EXCHANGE_contract_get_cancel (ds->dh); + TALER_EXCHANGE_get_contracts_cancel (ds->dh); ds->dh = NULL; } json_decref (ds->contract_terms); diff --git a/src/testing/testing_api_cmd_deposit.c b/src/testing/testing_api_cmd_deposit.c @@ -109,7 +109,7 @@ struct DepositState /** * Deposit handle while operation is running. */ - struct TALER_EXCHANGE_BatchDepositHandle *dh; + struct TALER_EXCHANGE_PostBatchDepositHandle *dh; /** * Denomination public key of the deposited coin. @@ -237,7 +237,7 @@ do_retry (void *cls) */ static void deposit_cb (void *cls, - const struct TALER_EXCHANGE_BatchDepositResult *dr) + const struct TALER_EXCHANGE_PostBatchDepositResponse *dr) { struct DepositState *ds = cls; @@ -565,15 +565,13 @@ deposit_run (void *cls, if (NULL != phac) cdd.h_age_commitment = *phac; - ds->dh = TALER_EXCHANGE_batch_deposit ( + ds->dh = TALER_EXCHANGE_post_batch_deposit_create ( TALER_TESTING_interpreter_get_context (is), exchange_url, TALER_TESTING_get_keys (is), &dcd, 1, &cdd, - &deposit_cb, - ds, &ec); } if (NULL == ds->dh) @@ -585,6 +583,9 @@ deposit_run (void *cls, TALER_TESTING_interpreter_fail (is); return; } + TALER_EXCHANGE_post_batch_deposit_start (ds->dh, + &deposit_cb, + ds); } @@ -605,7 +606,7 @@ deposit_cleanup (void *cls, { TALER_TESTING_command_incomplete (ds->is, cmd->label); - TALER_EXCHANGE_batch_deposit_cancel (ds->dh); + TALER_EXCHANGE_post_batch_deposit_cancel (ds->dh); ds->dh = NULL; } if (NULL != ds->retry_task) diff --git a/src/testing/testing_api_cmd_deposits_get.c b/src/testing/testing_api_cmd_deposits_get.c @@ -88,7 +88,7 @@ struct TrackTransactionState /** * Handle to the "track transaction" pending operation. */ - struct TALER_EXCHANGE_DepositGetHandle *tth; + struct TALER_EXCHANGE_GetDepositsHandle *tth; /** * Interpreter state. @@ -109,7 +109,7 @@ struct TrackTransactionState static void deposit_wtid_cb ( void *cls, - const struct TALER_EXCHANGE_GetDepositResponse *dr) + const struct TALER_EXCHANGE_GetDepositsResponse *dr) { struct TrackTransactionState *tts = cls; struct TALER_TESTING_Interpreter *is = tts->is; @@ -275,18 +275,31 @@ deposits_get_run ( return; } - tts->tth = TALER_EXCHANGE_deposits_get ( + tts->tth = TALER_EXCHANGE_get_deposits_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), merchant_priv, &h_wire_details, &h_contract_terms, - &coin_pub, - GNUNET_TIME_UNIT_ZERO, - &deposit_wtid_cb, - tts); - GNUNET_assert (NULL != tts->tth); + &coin_pub); + if (NULL == tts->tth) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (TALER_EC_NONE != + TALER_EXCHANGE_get_deposits_start (tts->tth, + &deposit_wtid_cb, + tts)) + { + GNUNET_break (0); + TALER_EXCHANGE_get_deposits_cancel (tts->tth); + tts->tth = NULL; + TALER_TESTING_interpreter_fail (is); + return; + } } @@ -308,7 +321,7 @@ deposits_get_cleanup ( { TALER_TESTING_command_incomplete (tts->is, cmd->label); - TALER_EXCHANGE_deposits_get_cancel (tts->tth); + TALER_EXCHANGE_get_deposits_cancel (tts->tth); tts->tth = NULL; } GNUNET_free (tts->merchant_payto_uri.full_payto); diff --git a/src/testing/testing_api_cmd_purse_create_deposit.c b/src/testing/testing_api_cmd_purse_create_deposit.c @@ -131,7 +131,7 @@ struct PurseCreateDepositState /** * PurseCreateDeposit handle while operation is running. */ - struct TALER_EXCHANGE_PurseCreateDepositHandle *dh; + struct TALER_EXCHANGE_PostPursesCreateHandle *dh; /** * Interpreter state. @@ -165,7 +165,7 @@ struct PurseCreateDepositState */ static void deposit_cb (void *cls, - const struct TALER_EXCHANGE_PurseCreateDepositResponse *dr) + const struct TALER_EXCHANGE_PostPursesCreateResponse *dr) { struct PurseCreateDepositState *ds = cls; @@ -277,7 +277,7 @@ deposit_run (void *cls, ds->contract_terms, "pay_deadline", GNUNET_JSON_from_timestamp (ds->purse_expiration))); - ds->dh = TALER_EXCHANGE_purse_create_with_deposit ( + ds->dh = TALER_EXCHANGE_post_purses_create_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), @@ -286,18 +286,16 @@ deposit_run (void *cls, &ds->contract_priv, ds->contract_terms, ds->num_coin_references, - deposits, - ds->upload_contract, - &deposit_cb, - ds); - if (NULL == ds->dh) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not create purse with deposit\n"); - TALER_TESTING_interpreter_fail (is); - return; - } + deposits); + GNUNET_assert (NULL != ds->dh); + if (ds->upload_contract) + TALER_EXCHANGE_post_purses_create_set_options ( + ds->dh, + TALER_EXCHANGE_post_purses_create_option_upload_contract ()); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_purses_create_start (ds->dh, + &deposit_cb, + ds)); } @@ -318,7 +316,7 @@ deposit_cleanup (void *cls, { TALER_TESTING_command_incomplete (ds->is, cmd->label); - TALER_EXCHANGE_purse_create_with_deposit_cancel (ds->dh); + TALER_EXCHANGE_post_purses_create_cancel (ds->dh); ds->dh = NULL; } for (unsigned int i = 0; i<ds->num_coin_references; i++) diff --git a/src/testing/testing_api_cmd_purse_deposit.c b/src/testing/testing_api_cmd_purse_deposit.c @@ -91,7 +91,7 @@ struct PurseDepositState /** * PurseDeposit handle while operation is running. */ - struct TALER_EXCHANGE_PurseDepositHandle *dh; + struct TALER_EXCHANGE_PostPursesDepositHandle *dh; /** * Interpreter state. @@ -140,7 +140,7 @@ struct PurseDepositState */ static void deposit_cb (void *cls, - const struct TALER_EXCHANGE_PurseDepositResponse *dr) + const struct TALER_EXCHANGE_PostPursesDepositResponse *dr) { struct PurseDepositState *ds = cls; @@ -334,7 +334,7 @@ deposit_run (void *cls, pd->h_denom_pub = denom_pub->h_key; } - ds->dh = TALER_EXCHANGE_purse_deposit ( + ds->dh = TALER_EXCHANGE_post_purses_deposit_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), @@ -342,9 +342,7 @@ deposit_run (void *cls, &ds->purse_pub, ds->min_age, ds->num_coin_references, - deposits, - &deposit_cb, - ds); + deposits); if (NULL == ds->dh) { GNUNET_break (0); @@ -353,6 +351,10 @@ deposit_run (void *cls, TALER_TESTING_interpreter_fail (is); return; } + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_purses_deposit_start (ds->dh, + &deposit_cb, + ds)); } @@ -373,7 +375,7 @@ deposit_cleanup (void *cls, { TALER_TESTING_command_incomplete (ds->is, cmd->label); - TALER_EXCHANGE_purse_deposit_cancel (ds->dh); + TALER_EXCHANGE_post_purses_deposit_cancel (ds->dh); ds->dh = NULL; } for (unsigned int i = 0; i<ds->num_coin_references; i++) diff --git a/src/testing/testing_api_cmd_purse_get.c b/src/testing/testing_api_cmd_purse_get.c @@ -81,7 +81,7 @@ struct StatusState /** * Handle to the "purse status" operation. */ - struct TALER_EXCHANGE_PurseGetHandle *pgh; + struct TALER_EXCHANGE_GetPursesHandle *pgh; /** * Expected purse balance. @@ -120,7 +120,7 @@ struct StatusState */ static void purse_status_cb (void *cls, - const struct TALER_EXCHANGE_PurseGetResponse *rs) + const struct TALER_EXCHANGE_GetPursesResponse *rs) { struct StatusState *ss = cls; struct TALER_TESTING_Interpreter *is = ss->is; @@ -192,15 +192,32 @@ status_run (void *cls, TALER_TESTING_interpreter_fail (is); return; } - ss->pgh = TALER_EXCHANGE_purse_get ( + ss->pgh = TALER_EXCHANGE_get_purses_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), - ss->purse_pub, - ss->timeout, - ss->wait_for_merge, - &purse_status_cb, - ss); + ss->purse_pub); + if (NULL == ss->pgh) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + TALER_EXCHANGE_get_purses_set_options ( + ss->pgh, + TALER_EXCHANGE_get_purses_option_timeout (ss->timeout), + TALER_EXCHANGE_get_purses_option_wait_for_merge (ss->wait_for_merge)); + if (TALER_EC_NONE != + TALER_EXCHANGE_get_purses_start (ss->pgh, + &purse_status_cb, + ss)) + { + GNUNET_break (0); + TALER_EXCHANGE_get_purses_cancel (ss->pgh); + ss->pgh = NULL; + TALER_TESTING_interpreter_fail (is); + return; + } if (! GNUNET_TIME_relative_is_zero (ss->timeout)) { TALER_TESTING_interpreter_next (is); @@ -226,7 +243,7 @@ status_cleanup (void *cls, { TALER_TESTING_command_incomplete (ss->is, cmd->label); - TALER_EXCHANGE_purse_get_cancel (ss->pgh); + TALER_EXCHANGE_get_purses_cancel (ss->pgh); ss->pgh = NULL; } GNUNET_free (ss); diff --git a/src/testing/testing_api_cmd_purse_merge.c b/src/testing/testing_api_cmd_purse_merge.c @@ -54,7 +54,7 @@ struct PurseMergeState /** * Handle while operation is running. */ - struct TALER_EXCHANGE_AccountMergeHandle *dh; + struct TALER_EXCHANGE_PostPursesMergeHandle *dh; /** * Reference to the merge capability. @@ -136,7 +136,7 @@ struct PurseMergeState */ static void merge_cb (void *cls, - const struct TALER_EXCHANGE_AccountMergeResponse *dr) + const struct TALER_EXCHANGE_PostPursesMergeResponse *dr) { struct PurseMergeState *ds = cls; @@ -322,7 +322,7 @@ merge_run (void *cls, GNUNET_CRYPTO_eddsa_key_get_public (&merge_priv->eddsa_priv, &ds->merge_pub.eddsa_pub); ds->merge_timestamp = GNUNET_TIME_timestamp_get (); - ds->dh = TALER_EXCHANGE_account_merge ( + ds->dh = TALER_EXCHANGE_post_purses_merge_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), @@ -334,17 +334,12 @@ merge_run (void *cls, ds->min_age, &ds->value_after_fees, ds->purse_expiration, - ds->merge_timestamp, - &merge_cb, - ds); - if (NULL == ds->dh) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not merge purse\n"); - TALER_TESTING_interpreter_fail (is); - return; - } + ds->merge_timestamp); + GNUNET_assert (NULL != ds->dh); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_purses_merge_start (ds->dh, + &merge_cb, + ds)); } @@ -365,7 +360,7 @@ merge_cleanup (void *cls, { TALER_TESTING_command_incomplete (ds->is, cmd->label); - TALER_EXCHANGE_account_merge_cancel (ds->dh); + TALER_EXCHANGE_post_purses_merge_cancel (ds->dh); ds->dh = NULL; } GNUNET_free (ds); diff --git a/src/testing/testing_api_cmd_recoup.c b/src/testing/testing_api_cmd_recoup.c @@ -51,7 +51,7 @@ struct RecoupState /** * Handle to the ongoing operation. */ - struct TALER_EXCHANGE_RecoupHandle *ph; + struct TALER_EXCHANGE_PostRecoupWithdrawHandle *ph; /** * If the recoup filled a reserve, this is set to the reserve's public key. @@ -87,7 +87,7 @@ struct RecoupState */ static void recoup_cb (void *cls, - const struct TALER_EXCHANGE_RecoupResponse *rr) + const struct TALER_EXCHANGE_PostRecoupWithdrawResponse *rr) { struct RecoupState *ps = cls; const struct TALER_EXCHANGE_HttpResponse *hr = &rr->hr; @@ -294,7 +294,7 @@ recoup_run (void *cls, &ps->che.details.recoup.coin_bks, coin_priv, &ps->che.details.recoup.coin_sig); - ps->ph = TALER_EXCHANGE_recoup ( + ps->ph = TALER_EXCHANGE_post_recoup_withdraw_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), @@ -302,10 +302,12 @@ recoup_run (void *cls, coin_sig, ewv, &secret, - h_planchets, - &recoup_cb, - ps); + h_planchets); GNUNET_assert (NULL != ps->ph); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_recoup_withdraw_start (ps->ph, + &recoup_cb, + ps)); } @@ -323,7 +325,7 @@ recoup_cleanup (void *cls, struct RecoupState *ps = cls; if (NULL != ps->ph) { - TALER_EXCHANGE_recoup_cancel (ps->ph); + TALER_EXCHANGE_post_recoup_withdraw_cancel (ps->ph); ps->ph = NULL; } GNUNET_free (ps); diff --git a/src/testing/testing_api_cmd_recoup_refresh.c b/src/testing/testing_api_cmd_recoup_refresh.c @@ -76,7 +76,7 @@ struct RecoupRefreshState /** * Handle to the ongoing operation. */ - struct TALER_EXCHANGE_RecoupRefreshHandle *ph; + struct TALER_EXCHANGE_PostRecoupRefreshHandle *ph; /** * NULL if coin was not refreshed, otherwise reference @@ -97,7 +97,7 @@ struct RecoupRefreshState */ static void recoup_refresh_cb (void *cls, - const struct TALER_EXCHANGE_RecoupRefreshResponse *rrr) + const struct TALER_EXCHANGE_PostRecoupRefreshResponse *rrr) { struct RecoupRefreshState *rrs = cls; const struct TALER_EXCHANGE_HttpResponse *hr = &rrr->hr; @@ -331,7 +331,7 @@ recoup_refresh_run (void *cls, &rrs->che_new.details.recoup_refresh.coin_bks, coin_priv, &rrs->che_new.details.recoup_refresh.coin_sig); - rrs->ph = TALER_EXCHANGE_recoup_refresh ( + rrs->ph = TALER_EXCHANGE_post_recoup_refresh_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), @@ -340,10 +340,12 @@ recoup_refresh_run (void *cls, ewv, rms, planchet, - idx, - &recoup_refresh_cb, - rrs); + idx); GNUNET_assert (NULL != rrs->ph); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_recoup_refresh_start (rrs->ph, + &recoup_refresh_cb, + rrs)); } @@ -361,7 +363,7 @@ recoup_refresh_cleanup (void *cls, struct RecoupRefreshState *rrs = cls; if (NULL != rrs->ph) { - TALER_EXCHANGE_recoup_refresh_cancel (rrs->ph); + TALER_EXCHANGE_post_recoup_refresh_cancel (rrs->ph); rrs->ph = NULL; } GNUNET_free (rrs); diff --git a/src/testing/testing_api_cmd_refresh.c b/src/testing/testing_api_cmd_refresh.c @@ -116,7 +116,7 @@ struct MeltState /** * Melt handle while operation is running. */ - struct TALER_EXCHANGE_MeltHandle *mh; + struct TALER_EXCHANGE_PostMeltHandle *mh; /** * Expected entry in the coin history created by this @@ -267,7 +267,7 @@ struct RevealMeltState /** * Reveal handle while operation is running. */ - struct TALER_EXCHANGE_RevealMeltHandle *rmh; + struct TALER_EXCHANGE_PostRevealMeltHandle *rmh; /** * Our command. @@ -421,7 +421,7 @@ do_reveal_retry (void *cls) */ static void reveal_cb (void *cls, - const struct TALER_EXCHANGE_RevealMeltResponse *rmr) + const struct TALER_EXCHANGE_PostRevealMeltResponse *rmr) { struct RevealMeltState *rrs = cls; const struct TALER_EXCHANGE_HttpResponse *hr = &rmr->hr; @@ -577,18 +577,20 @@ melt_reveal_run (void *cls, ms->reveal_melt_input.num_blinding_values = ms->num_blinding_values; ms->reveal_melt_input.blinding_values = ms->blinding_values; ms->reveal_melt_input.noreveal_index = ms->noreveal_index; - rrs->rmh = TALER_EXCHANGE_reveal_melt ( + rrs->rmh = TALER_EXCHANGE_post_reveal_melt_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), - &ms->reveal_melt_input, - &reveal_cb, - rrs); + &ms->reveal_melt_input); if (NULL == rrs->rmh) { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); return; } + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_reveal_melt_start (rrs->rmh, + &reveal_cb, + rrs)); } @@ -610,7 +612,7 @@ melt_reveal_cleanup (void *cls, { TALER_TESTING_command_incomplete (rrs->is, cmd->label); - TALER_EXCHANGE_reveal_melt_cancel (rrs->rmh); + TALER_EXCHANGE_post_reveal_melt_cancel (rrs->rmh); rrs->rmh = NULL; } if (NULL != rrs->retry_task) @@ -660,7 +662,7 @@ do_melt_retry (void *cls) */ static void melt_cb (void *cls, - const struct TALER_EXCHANGE_MeltResponse *mr) + const struct TALER_EXCHANGE_PostMeltResponse *mr) { struct MeltState *ms = cls; const struct TALER_EXCHANGE_HttpResponse *hr = &mr->hr; @@ -741,14 +743,17 @@ melt_cb (void *cls, { TALER_LOG_DEBUG ("Doubling the melt (%s)\n", ms->cmd->label); - ms->mh = TALER_EXCHANGE_melt ( + ms->mh = TALER_EXCHANGE_post_melt_create ( TALER_TESTING_interpreter_get_context (ms->is), TALER_TESTING_get_exchange_url (ms->is), TALER_TESTING_get_keys (ms->is), &ms->rms, - &ms->melt_input, - &melt_cb, - ms); + &ms->melt_input); + GNUNET_assert (NULL != ms->mh); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_melt_start (ms->mh, + &melt_cb, + ms)); ms->double_melt = false; return; } @@ -939,14 +944,12 @@ melt_run (void *cls, else rms->che.details.melt.no_hac = true; - rms->mh = TALER_EXCHANGE_melt ( + rms->mh = TALER_EXCHANGE_post_melt_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), &rms->rms, - &rms->melt_input, - &melt_cb, - rms); + &rms->melt_input); if (NULL == rms->mh) { @@ -954,6 +957,10 @@ melt_run (void *cls, TALER_TESTING_interpreter_fail (rms->is); return; } + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_melt_start (rms->mh, + &melt_cb, + rms)); } } @@ -976,7 +983,7 @@ melt_cleanup (void *cls, { TALER_TESTING_command_incomplete (rms->is, cmd->label); - TALER_EXCHANGE_melt_cancel (rms->mh); + TALER_EXCHANGE_post_melt_cancel (rms->mh); rms->mh = NULL; } if (NULL != rms->retry_task) diff --git a/src/testing/testing_api_cmd_refund.c b/src/testing/testing_api_cmd_refund.c @@ -66,7 +66,7 @@ struct RefundState /** * Handle to the refund operation. */ - struct TALER_EXCHANGE_RefundHandle *rh; + struct TALER_EXCHANGE_PostCoinsRefundHandle *rh; /** * Interpreter state. @@ -84,7 +84,7 @@ struct RefundState */ static void refund_cb (void *cls, - const struct TALER_EXCHANGE_RefundResponse *rr) + const struct TALER_EXCHANGE_PostCoinsRefundResponse *rr) { struct RefundState *rs = cls; const struct TALER_EXCHANGE_HttpResponse *hr = &rr->hr; @@ -222,7 +222,7 @@ refund_run (void *cls, &refund_amount, merchant_priv, &rs->che.details.refund.sig); - rs->rh = TALER_EXCHANGE_refund ( + rs->rh = TALER_EXCHANGE_post_coins_refund_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), @@ -230,10 +230,12 @@ refund_run (void *cls, &h_contract_terms, &rs->coin, rs->refund_transaction_id, - merchant_priv, - &refund_cb, - rs); + merchant_priv); GNUNET_assert (NULL != rs->rh); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_coins_refund_start (rs->rh, + &refund_cb, + rs)); } @@ -285,7 +287,7 @@ refund_cleanup (void *cls, { TALER_TESTING_command_incomplete (rs->is, cmd->label); - TALER_EXCHANGE_refund_cancel (rs->rh); + TALER_EXCHANGE_post_coins_refund_cancel (rs->rh); rs->rh = NULL; } GNUNET_free (rs); diff --git a/src/testing/testing_api_cmd_reserve_attest.c b/src/testing/testing_api_cmd_reserve_attest.c @@ -40,7 +40,7 @@ struct AttestState /** * Handle to the "reserve attest" operation. */ - struct TALER_EXCHANGE_ReservesAttestHandle *rsh; + struct TALER_EXCHANGE_PostReservesAttestHandle *rsh; /** * Private key of the reserve being analyzed. @@ -106,7 +106,7 @@ struct AttestState static void reserve_attest_cb ( void *cls, - const struct TALER_EXCHANGE_ReservePostAttestResult *rs) + const struct TALER_EXCHANGE_PostReservesAttestResponse *rs) { struct AttestState *ss = cls; struct TALER_TESTING_Interpreter *is = ss->is; @@ -182,15 +182,33 @@ attest_run (void *cls, } GNUNET_CRYPTO_eddsa_key_get_public (&ss->reserve_priv->eddsa_priv, &ss->reserve_pub.eddsa_pub); - ss->rsh = TALER_EXCHANGE_reserves_attest ( + ss->rsh = TALER_EXCHANGE_post_reserves_attest_create ( TALER_TESTING_interpreter_get_context (is), exchange_url, TALER_TESTING_get_keys (is), ss->reserve_priv, ss->attrs_len, - ss->attrs, - &reserve_attest_cb, - ss); + ss->attrs); + if (NULL == ss->rsh) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + { + enum TALER_ErrorCode ec; + + ec = TALER_EXCHANGE_post_reserves_attest_start (ss->rsh, + &reserve_attest_cb, + ss); + if (TALER_EC_NONE != ec) + { + GNUNET_break (0); + ss->rsh = NULL; + TALER_TESTING_interpreter_fail (is); + return; + } + } } @@ -211,7 +229,7 @@ attest_cleanup (void *cls, { TALER_TESTING_command_incomplete (ss->is, cmd->label); - TALER_EXCHANGE_reserves_attest_cancel (ss->rsh); + TALER_EXCHANGE_post_reserves_attest_cancel (ss->rsh); ss->rsh = NULL; } json_decref (ss->attributes); diff --git a/src/testing/testing_api_cmd_reserve_close.c b/src/testing/testing_api_cmd_reserve_close.c @@ -41,7 +41,7 @@ struct CloseState /** * Handle to the "reserve close" operation. */ - struct TALER_EXCHANGE_ReservesCloseHandle *rsh; + struct TALER_EXCHANGE_PostReservesCloseHandle *rsh; /** * payto://-URI where to wire the funds. @@ -91,7 +91,7 @@ struct CloseState */ static void reserve_close_cb (void *cls, - const struct TALER_EXCHANGE_ReserveCloseResult *rs) + const struct TALER_EXCHANGE_PostReservesCloseResponse *rs) { struct CloseState *ss = cls; struct TALER_TESTING_Interpreter *is = ss->is; @@ -162,13 +162,37 @@ close_run (void *cls, } GNUNET_CRYPTO_eddsa_key_get_public (&ss->reserve_priv->eddsa_priv, &ss->reserve_pub.eddsa_pub); - ss->rsh = TALER_EXCHANGE_reserves_close ( + ss->rsh = TALER_EXCHANGE_post_reserves_close_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), - ss->reserve_priv, - ss->target_account, - &reserve_close_cb, - ss); + ss->reserve_priv); + if (NULL == ss->rsh) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (NULL != ss->target_account.full_payto) + { + TALER_EXCHANGE_post_reserves_close_set_options ( + ss->rsh, + TALER_EXCHANGE_post_reserves_close_option_payto_uri ( + ss->target_account)); + } + { + enum TALER_ErrorCode ec; + + ec = TALER_EXCHANGE_post_reserves_close_start (ss->rsh, + &reserve_close_cb, + ss); + if (TALER_EC_NONE != ec) + { + GNUNET_break (0); + ss->rsh = NULL; + TALER_TESTING_interpreter_fail (is); + return; + } + } } @@ -189,7 +213,7 @@ close_cleanup (void *cls, { TALER_TESTING_command_incomplete (ss->is, cmd->label); - TALER_EXCHANGE_reserves_close_cancel (ss->rsh); + TALER_EXCHANGE_post_reserves_close_cancel (ss->rsh); ss->rsh = NULL; } GNUNET_free (ss); diff --git a/src/testing/testing_api_cmd_reserve_get.c b/src/testing/testing_api_cmd_reserve_get.c @@ -81,7 +81,7 @@ struct StatusState /** * Handle to the "reserve status" operation. */ - struct TALER_EXCHANGE_ReservesGetHandle *rsh; + struct TALER_EXCHANGE_GetReservesHandle *rsh; /** * Expected reserve balance. @@ -115,7 +115,7 @@ struct StatusState */ static void reserve_status_cb (void *cls, - const struct TALER_EXCHANGE_ReserveSummary *rs) + const struct TALER_EXCHANGE_GetReservesResponse *rs) { struct StatusState *ss = cls; struct TALER_TESTING_Interpreter *is = ss->is; @@ -200,13 +200,31 @@ status_run (void *cls, TALER_TESTING_interpreter_fail (is); return; } - ss->rsh = TALER_EXCHANGE_reserves_get ( + ss->rsh = TALER_EXCHANGE_get_reserves_create ( TALER_TESTING_interpreter_get_context (is), exchange_url, - ss->reserve_pubp, - ss->timeout, - &reserve_status_cb, - ss); + ss->reserve_pubp); + if (NULL == ss->rsh) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (! GNUNET_TIME_relative_is_zero (ss->timeout)) + TALER_EXCHANGE_get_reserves_set_options ( + ss->rsh, + TALER_EXCHANGE_get_reserves_option_timeout (ss->timeout)); + if (TALER_EC_NONE != + TALER_EXCHANGE_get_reserves_start (ss->rsh, + &reserve_status_cb, + ss)) + { + GNUNET_break (0); + TALER_EXCHANGE_get_reserves_cancel (ss->rsh); + ss->rsh = NULL; + TALER_TESTING_interpreter_fail (is); + return; + } if (! GNUNET_TIME_relative_is_zero (ss->timeout)) { TALER_TESTING_interpreter_next (is); @@ -232,7 +250,7 @@ status_cleanup (void *cls, { TALER_TESTING_command_incomplete (ss->is, cmd->label); - TALER_EXCHANGE_reserves_get_cancel (ss->rsh); + TALER_EXCHANGE_get_reserves_cancel (ss->rsh); ss->rsh = NULL; } GNUNET_free (ss); diff --git a/src/testing/testing_api_cmd_reserve_get_attestable.c b/src/testing/testing_api_cmd_reserve_get_attestable.c @@ -41,7 +41,7 @@ struct GetAttestableState /** * Handle to the "reserve get_attestable" operation. */ - struct TALER_EXCHANGE_ReservesGetAttestHandle *rgah; + struct TALER_EXCHANGE_GetReservesAttestHandle *rgah; /** * Expected attestable attributes. @@ -80,7 +80,7 @@ struct GetAttestableState static void reserve_get_attestable_cb ( void *cls, - const struct TALER_EXCHANGE_ReserveGetAttestResult *rs) + const struct TALER_EXCHANGE_GetReservesAttestResponse *rs) { struct GetAttestableState *ss = cls; struct TALER_TESTING_Interpreter *is = ss->is; @@ -165,12 +165,27 @@ get_attestable_run (void *cls, } ss->reserve_pub = *reserve_pub; } - ss->rgah = TALER_EXCHANGE_reserves_get_attestable ( + ss->rgah = TALER_EXCHANGE_get_reserves_attest_create ( TALER_TESTING_interpreter_get_context (is), exchange_url, - &ss->reserve_pub, - &reserve_get_attestable_cb, - ss); + &ss->reserve_pub); + if (NULL == ss->rgah) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (TALER_EC_NONE != + TALER_EXCHANGE_get_reserves_attest_start (ss->rgah, + &reserve_get_attestable_cb, + ss)) + { + GNUNET_break (0); + TALER_EXCHANGE_get_reserves_attest_cancel (ss->rgah); + ss->rgah = NULL; + TALER_TESTING_interpreter_fail (is); + return; + } } @@ -191,7 +206,7 @@ get_attestable_cleanup (void *cls, { TALER_TESTING_command_incomplete (ss->is, cmd->label); - TALER_EXCHANGE_reserves_get_attestable_cancel (ss->rgah); + TALER_EXCHANGE_get_reserves_attest_cancel (ss->rgah); ss->rgah = NULL; } GNUNET_free (ss->expected_attestables); diff --git a/src/testing/testing_api_cmd_reserve_history.c b/src/testing/testing_api_cmd_reserve_history.c @@ -47,7 +47,7 @@ struct HistoryState /** * Handle to the "reserve history" operation. */ - struct TALER_EXCHANGE_ReservesHistoryHandle *rsh; + struct TALER_EXCHANGE_GetReservesHistoryHandle *rsh; /** * Expected reserve balance. @@ -366,7 +366,7 @@ analyze_command (void *cls, */ static void reserve_history_cb (void *cls, - const struct TALER_EXCHANGE_ReserveHistory *rs) + const struct TALER_EXCHANGE_GetReservesHistoryResponse *rs) { struct HistoryState *ss = cls; struct TALER_TESTING_Interpreter *is = ss->is; @@ -487,14 +487,28 @@ history_run (void *cls, } GNUNET_CRYPTO_eddsa_key_get_public (&ss->reserve_priv->eddsa_priv, &ss->reserve_pub.eddsa_pub); - ss->rsh = TALER_EXCHANGE_reserves_history ( + ss->rsh = TALER_EXCHANGE_get_reserves_history_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), - ss->reserve_priv, - 0, - &reserve_history_cb, - ss); + ss->reserve_priv); + if (NULL == ss->rsh) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (TALER_EC_NONE != + TALER_EXCHANGE_get_reserves_history_start (ss->rsh, + &reserve_history_cb, + ss)) + { + GNUNET_break (0); + TALER_EXCHANGE_get_reserves_history_cancel (ss->rsh); + ss->rsh = NULL; + TALER_TESTING_interpreter_fail (is); + return; + } } @@ -543,7 +557,7 @@ history_cleanup (void *cls, { TALER_TESTING_command_incomplete (ss->is, cmd->label); - TALER_EXCHANGE_reserves_history_cancel (ss->rsh); + TALER_EXCHANGE_get_reserves_history_cancel (ss->rsh); ss->rsh = NULL; } GNUNET_free (ss); diff --git a/src/testing/testing_api_cmd_reserve_open.c b/src/testing/testing_api_cmd_reserve_open.c @@ -74,7 +74,7 @@ struct OpenState /** * Handle to the "reserve open" operation. */ - struct TALER_EXCHANGE_ReservesOpenHandle *rsh; + struct TALER_EXCHANGE_PostReservesOpenHandle *rsh; /** * Expected reserve balance. @@ -122,7 +122,7 @@ struct OpenState */ static void reserve_open_cb (void *cls, - const struct TALER_EXCHANGE_ReserveOpenResult *rs) + const struct TALER_EXCHANGE_PostReservesOpenResponse *rs) { struct OpenState *ss = cls; struct TALER_TESTING_Interpreter *is = ss->is; @@ -251,7 +251,7 @@ open_run (void *cls, cpi->amount = ss->cd[i].amount; cpi->h_denom_pub = denom_pub->h_key; } - ss->rsh = TALER_EXCHANGE_reserves_open ( + ss->rsh = TALER_EXCHANGE_post_reserves_open_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), @@ -260,9 +260,27 @@ open_run (void *cls, ss->cpl, cp, GNUNET_TIME_relative_to_timestamp (ss->req_expiration_time), - ss->min_purses, - &reserve_open_cb, - ss); + ss->min_purses); + if (NULL == ss->rsh) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + { + enum TALER_ErrorCode ec; + + ec = TALER_EXCHANGE_post_reserves_open_start (ss->rsh, + &reserve_open_cb, + ss); + if (TALER_EC_NONE != ec) + { + GNUNET_break (0); + ss->rsh = NULL; + TALER_TESTING_interpreter_fail (is); + return; + } + } } @@ -283,7 +301,7 @@ open_cleanup (void *cls, { TALER_TESTING_command_incomplete (ss->is, cmd->label); - TALER_EXCHANGE_reserves_open_cancel (ss->rsh); + TALER_EXCHANGE_post_reserves_open_cancel (ss->rsh); ss->rsh = NULL; } GNUNET_free (ss->cd); diff --git a/src/testing/testing_api_cmd_reserve_purse.c b/src/testing/testing_api_cmd_reserve_purse.c @@ -85,7 +85,7 @@ struct ReservePurseState /** * Handle while operation is running. */ - struct TALER_EXCHANGE_PurseCreateMergeHandle *dh; + struct TALER_EXCHANGE_PostReservesPurseHandle *dh; /** * When will the purse expire? @@ -145,7 +145,7 @@ struct ReservePurseState */ static void purse_cb (void *cls, - const struct TALER_EXCHANGE_PurseCreateMergeResponse *dr) + const struct TALER_EXCHANGE_PostReservesPurseResponse *dr) { struct ReservePurseState *ds = cls; @@ -257,7 +257,7 @@ purse_run (void *cls, "pay_deadline", GNUNET_JSON_from_timestamp (ds->purse_expiration))); ds->merge_timestamp = GNUNET_TIME_timestamp_get (); - ds->dh = TALER_EXCHANGE_purse_create_with_merge ( + ds->dh = TALER_EXCHANGE_post_reserves_purse_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), @@ -266,11 +266,8 @@ purse_run (void *cls, &ds->merge_priv, &ds->contract_priv, ds->contract_terms, - true /* upload contract */, ds->pay_purse_fee, - ds->merge_timestamp, - &purse_cb, - ds); + ds->merge_timestamp); if (NULL == ds->dh) { GNUNET_break (0); @@ -279,6 +276,15 @@ purse_run (void *cls, TALER_TESTING_interpreter_fail (is); return; } + GNUNET_assert (GNUNET_OK == + TALER_EXCHANGE_post_reserves_purse_set_options ( + ds->dh, + TALER_EXCHANGE_post_reserves_purse_option_upload_contract ()) + ); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_reserves_purse_start (ds->dh, + &purse_cb, + ds)); } @@ -299,7 +305,7 @@ purse_cleanup (void *cls, { TALER_TESTING_command_incomplete (ds->is, cmd->label); - TALER_EXCHANGE_purse_create_with_merge_cancel (ds->dh); + TALER_EXCHANGE_post_reserves_purse_cancel (ds->dh); ds->dh = NULL; } json_decref (ds->contract_terms); diff --git a/src/testing/testing_api_cmd_transfer_get.c b/src/testing/testing_api_cmd_transfer_get.c @@ -72,7 +72,7 @@ struct TrackTransferState /** * Handle to a pending "track transfer" operation. */ - struct TALER_EXCHANGE_TransfersGetHandle *tth; + struct TALER_EXCHANGE_GetTransfersHandle *tth; /** * Interpreter state. @@ -105,7 +105,7 @@ track_transfer_cleanup ( { TALER_TESTING_command_incomplete (tts->is, cmd->label); - TALER_EXCHANGE_transfers_get_cancel (tts->tth); + TALER_EXCHANGE_get_transfers_cancel (tts->tth); tts->tth = NULL; } GNUNET_free (tts); @@ -123,7 +123,7 @@ track_transfer_cleanup ( static void track_transfer_cb ( void *cls, - const struct TALER_EXCHANGE_TransfersGetResponse *tgr) + const struct TALER_EXCHANGE_GetTransfersResponse *tgr) { struct TrackTransferState *tts = cls; const struct TALER_EXCHANGE_HttpResponse *hr = &tgr->hr; @@ -344,14 +344,16 @@ track_transfer_run ( } GNUNET_assert (NULL != wtid_ptr); } - tts->tth = TALER_EXCHANGE_transfers_get ( + tts->tth = TALER_EXCHANGE_get_transfers_create ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), - wtid_ptr, - &track_transfer_cb, - tts); + wtid_ptr); GNUNET_assert (NULL != tts->tth); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_get_transfers_start (tts->tth, + &track_transfer_cb, + tts)); } diff --git a/src/testing/testing_api_cmd_withdraw.c b/src/testing/testing_api_cmd_withdraw.c @@ -175,7 +175,7 @@ struct WithdrawState /** * Withdraw handle (while operation is running). */ - struct TALER_EXCHANGE_WithdrawHandle *wsh; + struct TALER_EXCHANGE_PostWithdrawHandle *wsh; /** * The commitment for the withdraw operation, later needed for /recoup @@ -264,7 +264,7 @@ do_retry (void *cls) */ static void withdraw_cb (void *cls, - const struct TALER_EXCHANGE_WithdrawResponse *wr) + const struct TALER_EXCHANGE_PostWithdrawResponse *wr) { struct WithdrawState *ws = cls; struct TALER_TESTING_Interpreter *is = ws->is; @@ -483,25 +483,30 @@ withdraw_run (void *cls, ws->reserve_history.details.withdraw.fee = ws->pk->fees.withdraw; - ws->wsh = TALER_EXCHANGE_withdraw_extra_blinding_seed ( + ws->wsh = TALER_EXCHANGE_post_withdraw_create ( TALER_TESTING_interpreter_get_context (is), - TALER_TESTING_get_keys (is), TALER_TESTING_get_exchange_url (is), + TALER_TESTING_get_keys (is), rp, 1, ws->pk, &ws->seed, - &ws->blinding_seed, - ws->age, - &withdraw_cb, - ws); - + ws->age); if (NULL == ws->wsh) { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); return; } + GNUNET_assert (GNUNET_OK == + TALER_EXCHANGE_post_withdraw_set_options ( + ws->wsh, + TALER_EXCHANGE_post_withdraw_option_blinding_seed ( + &ws->blinding_seed))); + GNUNET_assert (TALER_EC_NONE == + TALER_EXCHANGE_post_withdraw_start (ws->wsh, + &withdraw_cb, + ws)); } @@ -522,7 +527,7 @@ withdraw_cleanup (void *cls, { TALER_TESTING_command_incomplete (ws->is, cmd->label); - TALER_EXCHANGE_withdraw_cancel (ws->wsh); + TALER_EXCHANGE_post_withdraw_cancel (ws->wsh); ws->wsh = NULL; } if (NULL != ws->retry_task) diff --git a/src/util/taler_error_codes.c b/src/util/taler_error_codes.c @@ -249,6 +249,14 @@ static const struct ErrorCodeAndHint code_hint_pairs[] = { }, { + /* 33 */ + .ec = TALER_EC_GENERIC_PARAMETER_EXTRA, + .hint = gettext_noop ( + "A parameter in the request was given that must not be present. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers."), + .http_code = MHD_HTTP_BAD_REQUEST + }, + + { /* 40 */ .ec = TALER_EC_GENERIC_UNAUTHORIZED, .hint = gettext_noop ( @@ -5644,7 +5652,7 @@ static const struct ErrorCodeAndHint code_hint_pairs[] = { /** * The length of @e code_hint_pairs. */ -static const unsigned int code_hint_pairs_length = 706; +static const unsigned int code_hint_pairs_length = 707; const char *