From 77ab94eb6869ec3494d435b6ee285fd58be3d30d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 3 May 2020 19:54:36 +0200 Subject: [PATCH] update exchange API to return struct instead of lots of individual args for TALER_EXCHANGE_transfers_get() -- simplifies merchant later --- src/include/taler_exchange_service.h | 72 ++++++--- src/lib/exchange_api_transfers_get.c | 164 ++++++++++----------- src/testing/testing_api_cmd_transfer_get.c | 33 +---- 3 files changed, 140 insertions(+), 129 deletions(-) diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index a57a2655a..307a76de8 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -1580,32 +1580,68 @@ TALER_EXCHANGE_link_cancel (struct TALER_EXCHANGE_LinkHandle *lh); struct TALER_EXCHANGE_TransfersGetHandle; +/** + * Information the exchange returns per wire transfer. + */ +struct TALER_EXCHANGE_TransferData +{ + + /** + * exchange key used to sign + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * exchange signature over the transfer data + */ + struct TALER_ExchangeSignatureP exchange_sig; + + /** + * hash of the wire transfer address the transfer went to + */ + struct GNUNET_HashCode h_wire; + + /** + * time when the exchange claims to have performed the wire transfer + */ + struct GNUNET_TIME_Absolute execution_time; + + /** + * amount of the wire transfer + */ + struct TALER_Amount total_amount; + + /** + * wire fee that was charged by the exchange + */ + struct TALER_Amount wire_fee; + + /** + * length of the @e details array + */ + unsigned int details_length; + + /** + * array with details about the combined transactions + */ + const struct TALER_TrackTransferDetails *details; + +}; + + /** * Function called with detailed wire transfer data, including all * of the coin transactions that were combined into the wire transfer. * * @param cls closure * @param hr HTTP response data - * @param sign_key exchange key used to sign @a json, or NULL - * @param h_wire hash of the wire transfer address the transfer went to, or NULL on error - * @param execution_time time when the exchange claims to have performed the wire transfer - * @param total_amount total amount of the wire transfer, or NULL if the exchange could - * not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK) - * @param wire_fee wire fee that was charged by the exchange - * @param details_length length of the @a details array - * @param details array with details about the combined transactions + * @param ta transfer data, (set only if @a http_status is #MHD_HTTP_OK, otherwise NULL) */ typedef void (*TALER_EXCHANGE_TransfersGetCallback)( void *cls, const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_ExchangePublicKeyP *sign_key, - const struct GNUNET_HashCode *h_wire, - struct GNUNET_TIME_Absolute execution_time, - const struct TALER_Amount *total_amount, - const struct TALER_Amount *wire_fee, - unsigned int details_length, - const struct TALER_TrackTransferDetails *details); + const struct TALER_EXCHANGE_TransferData *ta); /** @@ -1651,17 +1687,19 @@ struct TALER_EXCHANGE_DepositGetHandle; * * @param cls closure * @param hr HTTP response data - * @param sign_key exchange key used to sign @a json, or NULL + * @param exchange_pub exchange key used to sign @a json, or NULL * @param wtid wire transfer identifier used by the exchange, NULL if exchange did not * yet execute the transaction * @param execution_time actual or planned execution time for the wire transfer * @param coin_contribution contribution to the total amount by this coin (can be NULL) + * // FIXME: also return the exchange signature + * // FIXME: combine all of the above (except cls,hr) into a 'struct'! => DepositData */ typedef void (*TALER_EXCHANGE_DepositGetCallback)( void *cls, const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_ExchangePublicKeyP *sign_key, + const struct TALER_ExchangePublicKeyP *exchange_pub, const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute execution_time, const struct TALER_Amount *coin_contribution); diff --git a/src/lib/exchange_api_transfers_get.c b/src/lib/exchange_api_transfers_get.c index 552536958..dd9b64467 100644 --- a/src/lib/exchange_api_transfers_get.c +++ b/src/lib/exchange_api_transfers_get.c @@ -85,24 +85,18 @@ check_transfers_get_response_ok ( const json_t *json) { json_t *details_j; - struct GNUNET_HashCode h_wire; - struct GNUNET_TIME_Absolute exec_time; - struct TALER_Amount total_amount; + struct TALER_EXCHANGE_TransferData td; struct TALER_Amount total_expected; - struct TALER_Amount wire_fee; struct TALER_MerchantPublicKeyP merchant_pub; - unsigned int num_details; - struct TALER_ExchangePublicKeyP exchange_pub; - struct TALER_ExchangeSignatureP exchange_sig; struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount ("total", &total_amount), - TALER_JSON_spec_amount ("wire_fee", &wire_fee), + TALER_JSON_spec_amount ("total", &td.total_amount), + TALER_JSON_spec_amount ("wire_fee", &td.wire_fee), GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub), - GNUNET_JSON_spec_fixed_auto ("h_wire", &h_wire), - GNUNET_JSON_spec_absolute_time ("execution_time", &exec_time), + GNUNET_JSON_spec_fixed_auto ("h_wire", &td.h_wire), + GNUNET_JSON_spec_absolute_time ("execution_time", &td.execution_time), GNUNET_JSON_spec_json ("deposits", &details_j), - GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig), - GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub), + GNUNET_JSON_spec_fixed_auto ("exchange_sig", &td.exchange_sig), + GNUNET_JSON_spec_fixed_auto ("exchange_pub", &td.exchange_pub), GNUNET_JSON_spec_end () }; struct TALER_EXCHANGE_HttpResponse hr = { @@ -119,22 +113,32 @@ check_transfers_get_response_ok ( return GNUNET_SYSERR; } if (GNUNET_OK != - TALER_amount_get_zero (total_amount.currency, + TALER_amount_get_zero (td.total_amount.currency, &total_expected)) { GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } - num_details = json_array_size (details_j); + if (GNUNET_OK != + TALER_EXCHANGE_test_signing_key ( + TALER_EXCHANGE_get_keys (wdh->exchange), + &td.exchange_pub)) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + return GNUNET_SYSERR; + } + td.details_length = json_array_size (details_j); { - struct TALER_TrackTransferDetails details[num_details]; - unsigned int i; struct GNUNET_HashContext *hash_context; - struct TALER_WireDepositDetailP dd; - struct TALER_WireDepositDataPS wdp; + struct TALER_TrackTransferDetails *details; + details = GNUNET_new_array (td.details_length, + struct TALER_TrackTransferDetails); + td.details = details; hash_context = GNUNET_CRYPTO_hash_context_start (); - for (i = 0; ih_contract_terms; - dd.execution_time = GNUNET_TIME_absolute_hton (exec_time); - dd.coin_pub = detail->coin_pub; - TALER_amount_hton (&dd.deposit_value, - &detail->coin_value); - TALER_amount_hton (&dd.deposit_fee, - &detail->coin_fee); - if ( (0 > + if ( (GNUNET_OK != + GNUNET_JSON_parse (detail_j, + spec_detail, + NULL, NULL)) || + (0 > TALER_amount_add (&total_expected, &total_expected, &detail->coin_value)) || @@ -177,71 +167,78 @@ check_transfers_get_response_ok ( GNUNET_break_op (0); GNUNET_CRYPTO_hash_context_abort (hash_context); GNUNET_JSON_parse_free (spec); + GNUNET_free (details); return GNUNET_SYSERR; } - GNUNET_CRYPTO_hash_context_read ( - hash_context, - &dd, - sizeof (struct TALER_WireDepositDetailP)); + /* build up big hash for signature checking later */ + { + struct TALER_WireDepositDetailP dd; + + dd.h_contract_terms = detail->h_contract_terms; + dd.execution_time = GNUNET_TIME_absolute_hton (td.execution_time); + dd.coin_pub = detail->coin_pub; + TALER_amount_hton (&dd.deposit_value, + &detail->coin_value); + TALER_amount_hton (&dd.deposit_fee, + &detail->coin_fee); + GNUNET_CRYPTO_hash_context_read (hash_context, + &dd, + sizeof (dd)); + } } /* Check signature */ - wdp.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT); - wdp.purpose.size = htonl (sizeof (struct TALER_WireDepositDataPS)); - TALER_amount_hton (&wdp.total, - &total_amount); - TALER_amount_hton (&wdp.wire_fee, - &wire_fee); - wdp.merchant_pub = merchant_pub; - wdp.h_wire = h_wire; - GNUNET_CRYPTO_hash_context_finish (hash_context, - &wdp.h_details); - if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (TALER_EXCHANGE_get_keys ( - wdh->exchange), - &exchange_pub)) { - GNUNET_break_op (0); - GNUNET_JSON_parse_free (spec); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify ( - TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT, - &wdp, - &exchange_sig.eddsa_signature, - &exchange_pub.eddsa_pub)) - { - GNUNET_break_op (0); - GNUNET_JSON_parse_free (spec); - return GNUNET_SYSERR; + struct TALER_WireDepositDataPS wdp = { + .purpose.purpose = htonl ( + TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT), + .purpose.size = htonl (sizeof (wdp)), + .merchant_pub = merchant_pub, + .h_wire = td.h_wire + }; + + TALER_amount_hton (&wdp.total, + &td.total_amount); + TALER_amount_hton (&wdp.wire_fee, + &td.wire_fee); + GNUNET_CRYPTO_hash_context_finish (hash_context, + &wdp.h_details); + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify ( + TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT, + &wdp, + &td.exchange_sig.eddsa_signature, + &td.exchange_pub.eddsa_pub)) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + GNUNET_free (details); + return GNUNET_SYSERR; + } } if (0 > TALER_amount_subtract (&total_expected, &total_expected, - &wire_fee)) + &td.wire_fee)) { GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); + GNUNET_free (details); return GNUNET_SYSERR; } if (0 != TALER_amount_cmp (&total_expected, - &total_amount)) + &td.total_amount)) { GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); + GNUNET_free (details); return GNUNET_SYSERR; } wdh->cb (wdh->cb_cls, &hr, - &exchange_pub, - &h_wire, - exec_time, - &total_amount, - &wire_fee, - num_details, - details); + &td); + GNUNET_free (details); } GNUNET_JSON_parse_free (spec); TALER_EXCHANGE_transfers_get_cancel (wdh); @@ -322,12 +319,7 @@ handle_transfers_get_finished (void *cls, } wdh->cb (wdh->cb_cls, &hr, - NULL, - NULL, - GNUNET_TIME_UNIT_ZERO_ABS, - NULL, - NULL, - 0, NULL); + NULL); TALER_EXCHANGE_transfers_get_cancel (wdh); } diff --git a/src/testing/testing_api_cmd_transfer_get.c b/src/testing/testing_api_cmd_transfer_get.c index 699313e56..3ca319cb5 100644 --- a/src/testing/testing_api_cmd_transfer_get.c +++ b/src/testing/testing_api_cmd_transfer_get.c @@ -121,37 +121,18 @@ track_transfer_cleanup (void *cls, * * @param cls closure. * @param hr HTTP response details - * @param exchange_pub public key the exchange used for signing - * the response. - * @param h_wire hash of the wire transfer address the transfer - * went to, or NULL on error. - * @param execution_time time when the exchange claims to have - * performed the wire transfer. - * @param total_amount total amount of the wire transfer, or NULL - * if the exchange could not provide any @a wtid (set only - * if @a http_status is "200 OK"). - * @param wire_fee wire fee that was charged by the exchange. - * @param details_length length of the @a details array. - * @param details array with details about the combined - * transactions. + * @param ta transfer data returned by the exchange */ static void track_transfer_cb (void *cls, const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct GNUNET_HashCode *h_wire, - struct GNUNET_TIME_Absolute execution_time, - const struct TALER_Amount *total_amount, - const struct TALER_Amount *wire_fee, - unsigned int details_length, - const struct TALER_TrackTransferDetails *details) + const struct TALER_EXCHANGE_TransferData *ta) { struct TrackTransferState *tts = cls; struct TALER_TESTING_Interpreter *is = tts->is; struct TALER_TESTING_Command *cmd = &is->commands[is->ip]; struct TALER_Amount expected_amount; - (void) exchange_pub; tts->tth = NULL; if (tts->expected_response_code != hr->http_status) { @@ -193,14 +174,14 @@ track_transfer_cb (void *cls, TALER_TESTING_interpreter_fail (is); return; } - if (0 != TALER_amount_cmp (total_amount, + if (0 != TALER_amount_cmp (&ta->total_amount, &expected_amount)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Total amount mismatch to command %s - " "%s vs %s\n", cmd->label, - TALER_amount_to_string (total_amount), + TALER_amount_to_string (&ta->total_amount), TALER_amount_to_string (&expected_amount)); json_dumpf (hr->reply, stderr, @@ -219,7 +200,7 @@ track_transfer_cb (void *cls, return; } - if (0 != TALER_amount_cmp (wire_fee, + if (0 != TALER_amount_cmp (&ta->wire_fee, &expected_amount)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -266,7 +247,7 @@ track_transfer_cb (void *cls, TALER_JSON_merchant_wire_signature_hash (wire_details, &h_wire_details)); if (0 != GNUNET_memcmp (&h_wire_details, - h_wire)) + &ta->h_wire)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wire hash missmath to command %s\n", @@ -301,7 +282,7 @@ track_transfer_cb (void *cls, TALER_TESTING_interpreter_fail (is); return; } - if (0 != TALER_amount_cmp (total_amount, + if (0 != TALER_amount_cmp (&ta->total_amount, total_amount_from_reference)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR,