From f0c88588254e8fa671bec19e0fea45364fe13b34 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 22 Jun 2015 14:23:09 +0200 Subject: [PATCH 1/4] -check consistency of amount with purpose's amount --- src/mint-lib/mint_api_deposit.c | 50 +++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/src/mint-lib/mint_api_deposit.c b/src/mint-lib/mint_api_deposit.c index c78680756..346f02800 100644 --- a/src/mint-lib/mint_api_deposit.c +++ b/src/mint-lib/mint_api_deposit.c @@ -213,15 +213,53 @@ verify_deposit_signature_forbidden (const struct TALER_MINT_DepositHandle *dh, GNUNET_break_op (0); return GNUNET_SYSERR; } - switch (purpose->purpose) + switch (ntohl (purpose->purpose)) { case TALER_SIGNATURE_WALLET_COIN_DEPOSIT: - GNUNET_break (0); - /* FIXME: check amount! #3516 */ + { + const struct TALER_DepositRequestPS *dr; + struct TALER_Amount dr_amount; + + if (ntohl (purpose->size) != sizeof (struct TALER_DepositRequestPS)) + { + GNUNET_break (0); + MAJ_parse_free (spec); + return GNUNET_SYSERR; + } + dr = (const struct TALER_DepositRequestPS *) purpose; + TALER_amount_ntoh (&dr_amount, + &dr->amount_with_fee); + if (0 != TALER_amount_cmp (&dr_amount, + &amount)) + { + GNUNET_break (0); + MAJ_parse_free (spec); + return GNUNET_SYSERR; + } + } break; case TALER_SIGNATURE_WALLET_COIN_MELT: - GNUNET_break (0); - /* FIXME: check amount! #3516 */ + { + const struct TALER_RefreshMeltCoinAffirmationPS *rm; + struct TALER_Amount rm_amount; + + if (ntohl (purpose->size) != sizeof (struct TALER_RefreshMeltCoinAffirmationPS)) + { + GNUNET_break (0); + MAJ_parse_free (spec); + return GNUNET_SYSERR; + } + rm = (const struct TALER_RefreshMeltCoinAffirmationPS *) purpose; + TALER_amount_ntoh (&rm_amount, + &rm->amount_with_fee); + if (0 != TALER_amount_cmp (&rm_amount, + &amount)) + { + GNUNET_break (0); + MAJ_parse_free (spec); + return GNUNET_SYSERR; + } + } break; default: /* signature not supported, new version on server? */ @@ -234,7 +272,7 @@ verify_deposit_signature_forbidden (const struct TALER_MINT_DepositHandle *dh, &total, &amount)) { - /* overflow in history already!? inconceivable! */ + /* overflow in history already!? inconceivable! Bad mint! */ GNUNET_break_op (0); MAJ_parse_free (spec); return GNUNET_SYSERR; From 3954fbe8c0bf1501c6067907c874127109a12457 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 22 Jun 2015 14:36:01 +0200 Subject: [PATCH 2/4] finishing implementation of #3516 --- src/mint-lib/mint_api_json.c | 40 ++++++++++++++++++++++++++++++------ src/mint-lib/mint_api_json.h | 11 ++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/mint-lib/mint_api_json.c b/src/mint-lib/mint_api_json.c index 81511c1c0..e2a73bdd4 100644 --- a/src/mint-lib/mint_api_json.c +++ b/src/mint-lib/mint_api_json.c @@ -202,12 +202,40 @@ parse_json (json_t *root, case MAJ_CMD_EDDSA_SIGNATURE: { - /* FIXME: parse the JSON signature - and the purpose, then check that the - signature is valid and the size field - is also correct; if all checks out, - return the purpose */ - GNUNET_break (0); // FIXME: implement! #3516 + struct TALER_CoinSpendSignatureP sig; + struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; + size_t size; + struct MAJ_Specification sig_spec[] = { + MAJ_spec_fixed_auto ("eddsa_sig", &sig), + MAJ_spec_varsize ("eddsa_val", (void**) &purpose, &size), + MAJ_spec_end + }; + + if (GNUNET_OK != + MAJ_parse_json (pos, + sig_spec)) + { + GNUNET_break_op (0); + MAJ_parse_free (sig_spec); + return i; + } + if (size != ntohl (purpose->size)) + { + GNUNET_break_op (0); + MAJ_parse_free (sig_spec); + return i; + } + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (ntohl (purpose->purpose), + purpose, + &sig.eddsa_signature, + spec[i].details.eddsa_signature.pub_key)) + { + GNUNET_break_op (0); + MAJ_parse_free (sig_spec); + return i; + } + *spec[i].details.eddsa_signature.purpose_p = purpose; } break; diff --git a/src/mint-lib/mint_api_json.h b/src/mint-lib/mint_api_json.h index 91679831d..ec3b63cbc 100644 --- a/src/mint-lib/mint_api_json.h +++ b/src/mint-lib/mint_api_json.h @@ -218,6 +218,17 @@ MAJ_parse_free (struct MAJ_Specification *spec); #define MAJ_spec_fixed_auto(name,obj) { .cmd = MAJ_CMD_BINARY_FIXED, .field = name, .details.fixed_data.dest = obj, .details.fixed_data.dest_size = sizeof (*obj) } +/** + * Variable size object (in network byte order, encoded using Crockford + * Base32hex encoding). + * + * @param name name of the JSON field + * @param obj_ptr pointer where to write the data (a `void **`) + * @param size where to store the number of bytes allocated for @a obj (of type `size_t *` + */ +#define MAJ_spec_varsize(name,obj,size) { .cmd = MAJ_CMD_BINARY_VARIABLE, .field = name, .details.variable_data.dest_p = obj, .details.variable_data.dest_size_p = size } + + /** * Absolute time. * From a4773ac3909239fa9cb8e2f71913c186b4edc745 Mon Sep 17 00:00:00 2001 From: Fournier Nicolas Date: Mon, 22 Jun 2015 14:46:19 +0200 Subject: [PATCH 3/4] Added suport for testing more database operations --- src/mintdb/perf_taler_mintdb_interpreter.c | 178 +++++++++++++++++---- src/mintdb/perf_taler_mintdb_interpreter.h | 163 +++++++++++++++---- 2 files changed, 281 insertions(+), 60 deletions(-) diff --git a/src/mintdb/perf_taler_mintdb_interpreter.c b/src/mintdb/perf_taler_mintdb_interpreter.c index 73c0669ea..d7d3a6d00 100644 --- a/src/mintdb/perf_taler_mintdb_interpreter.c +++ b/src/mintdb/perf_taler_mintdb_interpreter.c @@ -227,6 +227,10 @@ interpret_end_loop (struct PERF_TALER_MINTDB_interpreter_state *state) } +/** + * Saves the data exposed by another command into + * an array in the command specific struct. + */ static void interpret_save_array (struct PERF_TALER_MINTDB_interpreter_state *state) { @@ -309,6 +313,53 @@ interpret_save_array (struct PERF_TALER_MINTDB_interpreter_state *state) } +static void +interpret_load_array (struct PERF_TALER_MINTDB_interpreter_state *state) +{ + int loop_index, save_index; + union PERF_TALER_MINTDB_Data zero = {0}; + union PERF_TALER_MINTDB_Data *loaded_data; + + loop_index = cmd_find (state->cmd, + state->cmd[state->i].details.load_array.label_loop); + save_index = cmd_find (state->cmd, + state->cmd[state->i].details.load_array.label_save); + /* Extracting the data from the loop_indexth indice in save_index + * array. + */ + loaded_data = &state->cmd[save_index].details.save_array.data_saved[ + state->cmd[state->i].details.load_array.permutation[ + state->cmd[loop_index].details.loop.curr_iteration]]; + + switch (state->cmd[state->i].exposed_type) + { + case PERF_TALER_MINTDB_TIME: + state->cmd[state->i].exposed.time = loaded_data->time; + break; + + case PERF_TALER_MINTDB_DEPOSIT: + state->cmd[state->i].exposed.deposit = loaded_data->deposit; + break; + + case PERF_TALER_MINTDB_BLINDCOIN: + state->cmd[state->i].exposed.blindcoin = loaded_data->blindcoin; + break; + + case PERF_TALER_MINTDB_RESERVE: + state->cmd[state->i].exposed.reserve = loaded_data->reserve; + break; + + case PERF_TALER_MINTDB_DENOMINATION_INFO: + state->cmd[state->i].exposed.dki = loaded_data->dki; + + case PERF_TALER_MINTDB_COIN_INFO: + state->cmd[state->i].exposed.cpi = loaded_data->cpi; + default: + break; + } + *loaded_data = zero; +} + /** * Main interpreter loop. * @@ -344,12 +395,13 @@ interpret (struct PERF_TALER_MINTDB_interpreter_state *state) int start_index, stop_index; struct timespec start, stop; unsigned long elapsed_ms; + start_index = cmd_find (state->cmd, state->cmd[state->i].details.gauger.label_start); stop_index = cmd_find (state->cmd, state->cmd[state->i].details.gauger.label_stop); - start = state->cmd [start_index].exposed.time; - stop = state->cmd [stop_index].exposed.time; + start = state->cmd[start_index].exposed.time; + stop = state->cmd[stop_index].exposed.time; elapsed_ms = (start.tv_sec - stop.tv_sec) * 1000 + (start.tv_nsec - stop.tv_nsec) / 1000000; @@ -380,35 +432,7 @@ interpret (struct PERF_TALER_MINTDB_interpreter_state *state) break; case PERF_TALER_MINTDB_CMD_LOAD_ARRAY: - { - int loop_index, save_index; - union PERF_TALER_MINTDB_Data *loaded_data; - loop_index = cmd_find (state->cmd, - state->cmd[state->i].details.load_array.label_loop); - save_index = cmd_find (state->cmd, - state->cmd[state->i].details.load_array.label_save); - /* Extracting the data from the loop_indexth indice in save_index - * array. - */ - loaded_data = &state->cmd[save_index].details.save_array.data_saved[ - state->cmd[state->i].details.load_array.permutation[ - state->cmd[loop_index].details.loop.curr_iteration]]; - - switch (state->cmd[state->i].exposed_type) - { - case PERF_TALER_MINTDB_TIME: - state->cmd[state->i].exposed.time = loaded_data->time; - break; - - case PERF_TALER_MINTDB_DEPOSIT: - state->cmd[state->i].exposed.deposit = loaded_data->deposit; - loaded_data->deposit = NULL; - break; - - default: - break; - } - } + interpret_load_array (state); break; case PERF_TALER_MINTDB_CMD_INSERT_DEPOSIT: @@ -431,8 +455,98 @@ interpret (struct PERF_TALER_MINTDB_interpreter_state *state) state->cmd[state->i] .details.get_deposit.label_source)] .exposed.deposit; // Get the deposit from the source + state->plugin->have_deposit (state->plugin->cls, - state->session, deposit); + state->session, + deposit); + } + break; + + case PERF_TALER_MINTDB_CMD_INSERT_RESERVE: + { + struct TALER_MINTDB_Reserve *reserve; + json_t *details = json_pack ("si","justification", + GNUNET_CRYPTO_random_u32 ( + GNUNET_CRYPTO_QUALITY_WEAK, + UINT32_MAX)); + reserve = PERF_TALER_MINTDB_reserve_init (); + state->plugin->reserves_in_insert ( + state->plugin->cls, + state->session, + &reserve->pub, + &reserve->balance, + details + ); + json_decref (details); + state->cmd[state->i].exposed.reserve = reserve; + } + break; + + case PERF_TALER_MINTDB_CMD_GET_RESERVE: + { + struct TALER_MINTDB_Reserve *reserve = + state->cmd[cmd_find (state->cmd, + state->cmd[state->i] + .details.get_reserve.label_source)] + .exposed.reserve; // Get the deposit from the source + + state->plugin->reserve_get (state->plugin->cls, + state->session, + reserve); + } + break; + + case PERF_TALER_MINTDB_CMD_INSERT_DENOMINATION: + { + struct TALER_MINTDB_DenominationKeyIssueInformation *dki = + PERF_TALER_MINTDB_denomination_init (); + + state->plugin->insert_denomination_info (state->plugin->cls, + state->session, + &dki->denom_pub, + &dki->issue); + state->cmd[state->i].exposed.dki = dki; + } + break; + + case PERF_TALER_MINTDB_CMD_GET_DENOMINATION: + { + struct TALER_MINTDB_DenominationKeyIssueInformation *dki = + state->cmd[cmd_find (state->cmd, + state->cmd[state->i] + .details.get_denomination.label_source)] + .exposed.dki; + state->plugin->get_denomination_info (state->plugin->cls, + state->session, + &dki->denom_pub, + &dki->issue); + } + break; + + case PERF_TALER_MINTDB_CMD_INSERT_WITHDRAW: + { + struct TALER_MINTDB_CollectableBlindcoin *blindcoin = + PERF_TALER_MINTDB_collectable_blindcoin_init (); + + state->plugin->insert_withdraw_info (state->plugin->cls, + state->session, + blindcoin); + state->cmd[state->i].exposed.blindcoin = blindcoin; + } + break; + + case PERF_TALER_MINTDB_CMD_GET_WITHDRAW: + { + struct TALER_MINTDB_CollectableBlindcoin *blindcoin = + state->cmd[cmd_find (state->cmd, + state->cmd[state->i] + .details.get_denomination.label_source)] + .exposed.blindcoin; + + state->plugin->get_withdraw_info (state->plugin->cls, + state->session, + &blindcoin->h_coin_envelope, + blindcoin); } break; diff --git a/src/mintdb/perf_taler_mintdb_interpreter.h b/src/mintdb/perf_taler_mintdb_interpreter.h index 367aaf295..798660313 100644 --- a/src/mintdb/perf_taler_mintdb_interpreter.h +++ b/src/mintdb/perf_taler_mintdb_interpreter.h @@ -118,28 +118,6 @@ .exposed_type = PERF_TALER_MINTDB_NONE, \ } -/** - * Insert a deposit into the database - */ -#define PERF_TALER_MINTDB_INIT_CMD_INSERT_DEPOSIT(_label) \ -{ \ - .command = PERF_TALER_MINTDB_CMD_INSERT_DEPOSIT,\ - .label = _label, \ - .exposed_type = PERF_TALER_MINTDB_DEPOSIT, \ -} - -/** - * Check if a deposit is in the database - * @param _label_deposit Label of the deposit to use - */ -#define PERF_TALER_MINTDB_INIT_CMD_GET_DEPOSIT(_label, _label_deposit) \ -{ \ - .command = PERF_TALER_MINTDB_CMD_GET_DEPOSIT, \ - .label = _label, \ - .exposed_type = PERF_TALER_MINTDB_NONE, \ - .details.get_deposit.label_source = _label_deposit \ -} - /** * Extracts @a _nb_saved items of type @a _save_type * from the command @a _label_save during the loop @a _label_loop @@ -171,7 +149,94 @@ .label_save = _label_save \ } \ } +/** + * Insert a deposit into the database + */ +#define PERF_TALER_MINTDB_INIT_CMD_INSERT_DEPOSIT(_label) \ +{ \ + .command = PERF_TALER_MINTDB_CMD_INSERT_DEPOSIT,\ + .label = _label, \ + .exposed_type = PERF_TALER_MINTDB_DEPOSIT, \ +} +/** + * Check if a deposit is in the database + * @param _label_deposit Label of the deposit to use + */ +#define PERF_TALER_MINTDB_INIT_CMD_GET_DEPOSIT(_label, _label_deposit) \ +{ \ + .command = PERF_TALER_MINTDB_CMD_GET_DEPOSIT, \ + .label = _label, \ + .exposed_type = PERF_TALER_MINTDB_NONE, \ + .details.get_deposit.label_source = _label_deposit \ +} + +/** + * Creates a new reserve in the database + */ +#define PERF_TALER_MINTDB_INIT_CMD_INSERT_RESERVE(_label) \ +{ \ + .command = PERF_TALER_MINTDB_CMD_INSERT_RESERVE \ + .label = _label \ + .exposed_type = PERF_TALER_MINTDB_RESERVE \ +} + + +/** + * Polls the database for a secific reserve's details + * @param _label_source Source for the reserve to poll + */ +#define PERF_TALER_MINTDB_INIT_CMD_GET_RESERVE(_label, _label_source) \ +{ \ + .command = PERF_TALER_MINTDB_CMD_GET_RESERVE \ + .label = _label, \ + .exposed_type = PERF_TALER_MINTDB_NONE, \ + .details.get_reserve.label_source = _label_source \ +} + + +/** + * Inserts informations about a withdrawal in the database + */ +#define PERF_TALER_MINTDB_INIT_CMD_INSERT_WITHDRAW(_label) \ +{ \ + .command = PERF_TALER_MINTDB_CMD_INSERT_WITHDRAW, \ + .label = _label, \ + .exposed_type = PERF_TALER_MINTDB_BLINDCOIN, \ +}\ + + +/** + * Polls the database about informations regarding a secific withdrawal + */ +#define PERF_TALER_MINTDB_INIT_CMD_GET_WITHDRAW(_label, _label_source) \ +{ \ + .command = PERF_TALER_MINTDB_CMD_GET_WITHDRAW, \ + .label = _label, \ + .exposed_type = PERF_TALER_MINTDB_NONE, \ + .details.get_withdraw.label_source = _label_source, \ +} + +/** + * Inserts informations about a denomination key in the database + */ +#define PERF_TALER_MINTDB_INIT_CMD_INSERT_DENOMINATION(_label) \ +{ \ + .command = PERF_TALER_MINTDB_CMD_INSERT_WITHDRAW, \ + .label = _label, \ + .exposed_type = PERF_TALER_MINTDB_DENOMINATION_KEY, \ +} + +/** + * Polls the database about informations regarding a specific denomination key + */ +#define PERF_TALER_MINTDB_INIT_CMD_GET_DENOMINATION(_label, _label_source) \ +{ \ + .command = PERF_TALER_MINTDB_CMD_GET_DENOMINATION, \ + .label = _label, \ + .exposed_type = PERF_TALER_MINTDB_NONE, \ + .details.get_denomination.label_source = _label_source, \ +} /** @@ -184,7 +249,9 @@ enum PERF_TALER_MINTDB_Type PERF_TALER_MINTDB_TIME, PERF_TALER_MINTDB_DEPOSIT, PERF_TALER_MINTDB_BLINDCOIN, + PERF_TALER_MINTDB_RESERVE_KEY, PERF_TALER_MINTDB_RESERVE, + PERF_TALER_MINTDB_DENOMINATION_KEY, PERF_TALER_MINTDB_DENOMINATION_INFO, PERF_TALER_MINTDB_COIN_INFO, }; @@ -195,10 +262,11 @@ enum PERF_TALER_MINTDB_Type */ union PERF_TALER_MINTDB_Data { - struct TALER_MINTDB_Deposit *deposit; struct timespec time; + struct TALER_MINTDB_Deposit *deposit; struct TALER_MINTDB_CollectableBlindcoin *blindcoin; struct TALER_MINTDB_Reserve *reserve; + struct TALER_DenominationPublicKey *dpk; struct TALER_MINTDB_DenominationKeyIssueInformation *dki; struct TALER_CoinPublicInfo *cpi; }; @@ -239,19 +307,36 @@ enum PERF_TALER_MINTDB_CMD_Name // Abort a transaction PERF_TALER_MINTDB_CMD_ABORT_TRANSACTION, + // Saves random deposits from a loop + PERF_TALER_MINTDB_CMD_SAVE_ARRAY, + + // Load deposits saved earlier + PERF_TALER_MINTDB_CMD_LOAD_ARRAY, + // Insert a deposit into the database PERF_TALER_MINTDB_CMD_INSERT_DEPOSIT, // Check if a deposit is in the database PERF_TALER_MINTDB_CMD_GET_DEPOSIT, - // Saves random deposits from a loop - PERF_TALER_MINTDB_CMD_SAVE_ARRAY, + // Insert currency in a reserve / Create a reserve + PERF_TALER_MINTDB_CMD_INSERT_RESERVE, - // Load deposits saved earlier - PERF_TALER_MINTDB_CMD_LOAD_ARRAY, + // Get Informations about a reserve + PERF_TALER_MINTDB_CMD_GET_RESERVE, -} command; + // Insert informations about a withdrawal in the database + PERF_TALER_MINTDB_CMD_INSERT_WITHDRAW, + + // Pulls informations about a withdrawal from the database + PERF_TALER_MINTDB_CMD_GET_WITHDRAW, + + // Insert informations about a denomination key in the database + PERF_TALER_MINTDB_CMD_INSERT_DENOMINATION, + + // polls the database for informations about a specific denomination key + PERF_TALER_MINTDB_CMD_GET_DENOMINATION +}; /** @@ -365,6 +450,26 @@ struct PERF_TALER_MINTDB_CMD_get_deposit_details }; +/** + * Extra data requiered for the GET_DEPOSIT command + */ +struct PERF_TALER_MINTDB_CMD_get_reserve_details +{ + /** + * The label of the source of the reserve to check + */ + const char *label_source; +}; + + +struct PERF_TALER_MINTDB_CMD_get_denomination_details +{ + /** + * The label of the source of the denomination to check + */ + const char *label_source; +}; + /** * Contains extra data required for any command */ @@ -376,6 +481,8 @@ union PERF_TALER_MINTDB_CMD_Details struct PERF_TALER_MINTDB_CMD_save_array_details save_array; struct PERF_TALER_MINTDB_CMD_load_array_details load_array; struct PERF_TALER_MINTDB_CMD_get_deposit_details get_deposit; + struct PERF_TALER_MINTDB_CMD_get_reserve_details get_reserve; + struct PERF_TALER_MINTDB_CMD_get_denomination_details get_denomination; }; From e51b6f753af6ec0592594ba787f05f4ac46b6859 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 22 Jun 2015 15:23:18 +0200 Subject: [PATCH 4/4] drafting API for /withdraw/status and /withdraw/sign --- src/include/taler_mint_service.h | 179 ++++++++++++++++++++++++++++++- 1 file changed, 178 insertions(+), 1 deletion(-) diff --git a/src/include/taler_mint_service.h b/src/include/taler_mint_service.h index 850f07630..a243da540 100644 --- a/src/include/taler_mint_service.h +++ b/src/include/taler_mint_service.h @@ -420,7 +420,184 @@ void TALER_MINT_deposit_cancel (struct TALER_MINT_DepositHandle *deposit); -/* ********************* /withdraw/xxx *********************** */ +/* ********************* /withdraw/status *********************** */ + + +/** + * @brief A /withdraw/status Handle + */ +struct TALER_MINT_WithdrawStatusHandle; + + +/** + * Ways how a reserve's balance may change. + */ +enum TALER_MINT_ReserveTransactionType { + + /** + * Deposit into the reserve. + */ + TALER_MINT_RTT_DEPOSIT, + + /** + * Withdrawal from the reserve. + */ + TALER_MINT_RTT_WITHDRAWAL + +}; + + +/** + * Entry in the reserve's transaction history. + */ +struct TALER_MINT_ReserveHistory +{ + + /** + * Type of the transaction. + */ + enum TALER_MINT_ReserveTransactionType type; + + /** + * Amount transferred (in or out). + */ + struct TALER_Amount amount; + + /** + * Details depending on @e type. + */ + union { + + /** + * Transaction details for the incoming transaction. + */ + json_t *wire_in_details; + + /** + * Signature authorizing the withdrawal for outgoing transaction. + */ + struct TALER_ReserveSignatureP out_authorization_sig; + + }; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * deposit permission request to a mint. + * + * @param cls closure + * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request + * 0 if the mint's reply is bogus (fails to follow the protocol) + * @param balance current balance in the reserve + * @param history_length number of entries in the transaction history + * @param history detailed transaction history + */ +typedef void +(*TALER_MINT_WithdrawStatusResultCallback) (void *cls, + unsigned int http_status, + const struct TALER_Amount *balance, + unsigned int history_length, + const struct TALER_MINT_ReserveHistory *history); + + +/** + * Submit a request to obtain the transaction history of a reserve + * from the mint. Note that while we return the full response to the + * caller for further processing, we do already verify that the + * response is well-formed (i.e. that signatures included in the + * response are all valid and add up to the balance). If the mint's + * reply is not well-formed, we return an HTTP status code of zero to + * @a cb. + * + * @param mint the mint handle; the mint must be ready to operate + * @param reserve_pub public key of the reserve to inspect + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + * signatures fail to verify). In this case, the callback is not called. + */ +struct TALER_MINT_WithdrawStatusHandle * +TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint, + const struct TALER_ReservePublicKeyP *reserve_pub, + TALER_MINT_WithdrawStatusResultCallback cb, + void *cb_cls); + + +/** + * Cancel a withdraw status request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param status the withdraw status request handle + */ +void +TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *status); + + +/* ********************* /withdraw/sign *********************** */ + + +/** + * @brief A /withdraw/sign Handle + */ +struct TALER_MINT_WithdrawSignHandle; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * deposit permission request to a mint. + * + * @param cls closure + * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request + * 0 if the mint's reply is bogus (fails to follow the protocol) + * @param sig signature over the coin, NULL on error + * @param full_response full response from the mint (for logging, in case of errors) + */ +typedef void +(*TALER_MINT_WithdrawSignResultCallback) (void *cls, + unsigned int http_status, + const struct TALER_DenominationSignature *sig, + json_t *full_response); + + +/** + * Withdraw a coin from the mint using a /withdraw/sign request. Note + * that to ensure that no money is lost in case of hardware failures, + * the caller must have committed (most of) the arguments to disk + * before calling, and be ready to repeat the request with the same + * arguments in case of failures. + * + * @param mint the mint handle; the mint must be ready to operate + * @param pk kind of coin to create + * @param coin_priv where to store the coin's private key, + * caller must have committed this value to disk before the call (with @a pk) + * @param blinding_key where to store the coin's blinding key + * caller must have committed this value to disk before the call (with @a pk) + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for the above callback + * @return #GNUNET_OK on success, #GNUNET_SYSERR + * if the inputs are invalid (i.e. denomination key not with this mint). + * In this case, the callback is not called. + */ +struct TALER_MINT_WithdrawSignHandle * +TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint, + const struct TALER_MINT_DenomPublicKey *pk, + const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_DenominationBlindingKey *blinding_key, + TALER_MINT_WithdrawSignResultCallback res_cb, + void *res_cb_cls); + + +/** + * Cancel a withdraw status request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param sign the withdraw sign request handle + */ +void +TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign);