From ce199e6e9590a4290c11cdbc1b40600f74ac41e6 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 21 Jan 2016 14:46:17 +0100 Subject: adding API code for /deposit/wtid requests --- src/mint-lib/mint_api_deposit_wtid.c | 387 +++++++++++++++++++++++++++++++++++ 1 file changed, 387 insertions(+) create mode 100644 src/mint-lib/mint_api_deposit_wtid.c (limited to 'src/mint-lib/mint_api_deposit_wtid.c') diff --git a/src/mint-lib/mint_api_deposit_wtid.c b/src/mint-lib/mint_api_deposit_wtid.c new file mode 100644 index 00000000..bb81d93e --- /dev/null +++ b/src/mint-lib/mint_api_deposit_wtid.c @@ -0,0 +1,387 @@ +/* + This file is part of TALER + Copyright (C) 2014, 2015, 2016 GNUnet e.V. + + 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. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, If not, see + +*/ +/** + * @file mint-lib/mint_api_deposit_wtid.c + * @brief Implementation of the /deposit/wtid request of the mint's HTTP API + * @author Christian Grothoff + */ +#include "platform.h" +#include +#include +#include /* just for HTTP status codes */ +#include +#include "taler_mint_service.h" +#include "mint_api_common.h" +#include "mint_api_json.h" +#include "mint_api_context.h" +#include "mint_api_handle.h" +#include "taler_signatures.h" + + +/** + * @brief A Deposit Wtid Handle + */ +struct TALER_MINT_DepositWtidHandle +{ + + /** + * The connection to mint this request handle will use + */ + struct TALER_MINT_Handle *mint; + + /** + * The url for this request. + */ + char *url; + + /** + * JSON encoding of the request to POST. + */ + char *json_enc; + + /** + * Handle for the request. + */ + struct MAC_Job *job; + + /** + * Function to call with the result. + */ + TALER_MINT_DepositWtidCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * Download buffer + */ + struct MAC_DownloadBuffer db; + + /** + * Information the mint should sign in response. + * (with pre-filled fields from the request). + */ + struct TALER_ConfirmWirePS depconf; + +}; + + +/** + * Verify that the signature on the "200 OK" response + * from the mint is valid. + * + * @param dwh deposit wtid handle + * @param json json reply with the signature + * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not + */ +static int +verify_deposit_wtid_signature_ok (const struct TALER_MINT_DepositWtidHandle *dwh, + json_t *json) +{ + struct TALER_MintSignatureP mint_sig; + struct TALER_MintPublicKeyP mint_pub; + const struct TALER_MINT_Keys *key_state; + struct MAJ_Specification spec[] = { + MAJ_spec_fixed_auto ("mint_sig", &mint_sig), + MAJ_spec_fixed_auto ("mint_pub", &mint_pub), + MAJ_spec_end + }; + + if (GNUNET_OK != + MAJ_parse_json (json, + spec)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + key_state = TALER_MINT_get_keys (dwh->mint); + if (GNUNET_OK != + TALER_MINT_test_signing_key (key_state, + &mint_pub)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_CONFIRM_WIRE, + &dwh->depconf.purpose, + &mint_sig.eddsa_signature, + &mint_pub.eddsa_pub)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Function called when we're done processing the + * HTTP /deposit/wtid request. + * + * @param cls the `struct TALER_MINT_DepositWtidHandle` + * @param eh the curl request handle + */ +static void +handle_deposit_wtid_finished (void *cls, + CURL *eh) +{ + struct TALER_MINT_DepositWtidHandle *dwh = cls; + long response_code; + json_t *json; + const struct TALER_WireTransferIdentifierRawP *wtid = NULL; + struct GNUNET_TIME_Absolute execution_time = GNUNET_TIME_UNIT_FOREVER_ABS; + const struct TALER_Amount *coin_contribution = NULL; + const struct TALER_Amount *total_amount = NULL; + struct TALER_Amount coin_contribution_s; + struct TALER_Amount total_amount_s; + + dwh->job = NULL; + json = MAC_download_get_result (&dwh->db, + eh, + &response_code); + switch (response_code) + { + case 0: + break; + case MHD_HTTP_OK: + { + struct MAJ_Specification spec[] = { + MAJ_spec_fixed_auto ("wtid", &dwh->depconf.wtid), + MAJ_spec_absolute_time ("execution_time", &execution_time), + MAJ_spec_amount ("coin_contribution", &coin_contribution_s), + MAJ_spec_amount ("total_amount", &total_amount_s), + MAJ_spec_end + }; + + if (GNUNET_OK != + MAJ_parse_json (json, + spec)) + { + GNUNET_break_op (0); + response_code = 0; + break; + } + wtid = &dwh->depconf.wtid; + dwh->depconf.execution_time = GNUNET_TIME_absolute_hton (execution_time); + TALER_amount_hton (&dwh->depconf.coin_contribution, + &coin_contribution_s); + coin_contribution = &coin_contribution_s; + TALER_amount_hton (&dwh->depconf.total_amount, + &total_amount_s); + total_amount = &total_amount_s; + if (GNUNET_OK != + verify_deposit_wtid_signature_ok (dwh, + json)) + { + GNUNET_break_op (0); + response_code = 0; + } + } + break; + case MHD_HTTP_ACCEPTED: + { + /* Transaction known, but not executed yet */ + struct MAJ_Specification spec[] = { + MAJ_spec_absolute_time ("execution_time", &execution_time), + MAJ_spec_end + }; + + if (GNUNET_OK != + MAJ_parse_json (json, + spec)) + { + GNUNET_break_op (0); + response_code = 0; + break; + } + } + break; + case MHD_HTTP_BAD_REQUEST: + /* This should never happen, either us or the mint is buggy + (or API version conflict); just pass JSON reply to the application */ + break; + case MHD_HTTP_UNAUTHORIZED: + /* Nothing really to verify, mint says one of the signatures is + invalid; as we checked them, this should never happen, we + should pass the JSON reply to the application */ + break; + case MHD_HTTP_NOT_FOUND: + /* Mint does not know about transaction; + we should pass the reply to the application */ + break; + case MHD_HTTP_INTERNAL_SERVER_ERROR: + /* Server had an internal issue; we should retry, but this API + leaves this to the application */ + break; + default: + /* unexpected response code */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u\n", + response_code); + GNUNET_break (0); + response_code = 0; + break; + } + dwh->cb (dwh->cb_cls, + response_code, + json, + wtid, + execution_time, + coin_contribution, + total_amount); + json_decref (json); + TALER_MINT_deposit_wtid_cancel (dwh); +} + + +/** + * Obtain wire transfer details about an existing deposit operation. + * + * @param mint the mint to query + * @param merchant_priv the merchant's private key + * @param h_wire hash of merchant's wire transfer details + * @param h_contract hash of the contract + * @param coin_pub public key of the coin + * @param transaction_id transaction identifier + * @param cb function to call with the result + * @param cb_cls closure for @a cb + * @return handle to abort request + */ +struct TALER_MINT_DepositWtidHandle * +TALER_MINT_deposit_wtid (struct TALER_MINT_Handle *mint, + const struct TALER_MerchantPrivateKeyP *merchant_priv, + const struct GNUNET_HashCode *h_wire, + const struct GNUNET_HashCode *h_contract, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t transaction_id, + TALER_MINT_DepositWtidCallback cb, + void *cb_cls) +{ + struct TALER_DepositTrackPS dtp; + struct TALER_MerchantSignatureP merchant_sig; + struct TALER_MINT_DepositWtidHandle *dwh; + struct TALER_MINT_Context *ctx; + json_t *deposit_wtid_obj; + CURL *eh; + + if (GNUNET_YES != + MAH_handle_is_ready (mint)) + { + GNUNET_break (0); + return NULL; + } + dtp.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_DEPOSIT_WTID); + dtp.purpose.size = htonl (sizeof (dtp)); + dtp.h_contract = *h_contract; + dtp.h_wire = *h_wire; + dtp.transaction_id = GNUNET_htonll (transaction_id); + GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv, + &dtp.merchant.eddsa_pub); + + dtp.coin_pub = *coin_pub; + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv, + &dtp.purpose, + &merchant_sig.eddsa_sig)); + + deposit_wtid_obj = json_pack ("{s:o, s:o," /* H_wire, H_contract */ + " s:o, s:I," /* coin_pub, transaction_id */ + " s:o, s:o}", /* merchant_pub, merchant_sig */ + "H_wire", TALER_json_from_data (h_wire, + sizeof (struct GNUNET_HashCode)), + "H_contract", TALER_json_from_data (h_contract, + sizeof (struct GNUNET_HashCode)), + "coin_pub", TALER_json_from_data (coin_pub, + sizeof (*coin_pub)), + "transaction_id", (json_int_t) transaction_id, + "merchant_pub", TALER_json_from_data (&dtp.merchant, + sizeof (struct TALER_MerchantPublicKeyP)), + "merchant_sig", TALER_json_from_data (&merchant_sig, + sizeof (merchant_sig))); + + dwh = GNUNET_new (struct TALER_MINT_DepositWtidHandle); + dwh->mint = mint; + dwh->cb = cb; + dwh->cb_cls = cb_cls; + dwh->url = MAH_path_to_url (mint, "/deposit/wtid"); + dwh->depconf.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)); + dwh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_WIRE); + dwh->depconf.h_wire = *h_wire; + dwh->depconf.h_contract = *h_contract; + dwh->depconf.coin_pub = *coin_pub; + dwh->depconf.transaction_id = GNUNET_htonll (transaction_id); + + eh = curl_easy_init (); + GNUNET_assert (NULL != (dwh->json_enc = + json_dumps (deposit_wtid_obj, + JSON_COMPACT))); + json_decref (deposit_wtid_obj); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_URL, + dwh->url)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_POSTFIELDS, + dwh->json_enc)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_POSTFIELDSIZE, + strlen (dwh->json_enc))); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_WRITEFUNCTION, + &MAC_download_cb)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_WRITEDATA, + &dwh->db)); + ctx = MAH_handle_to_context (mint); + dwh->job = MAC_job_add (ctx, + eh, + GNUNET_YES, + &handle_deposit_wtid_finished, + dwh); + return dwh; +} + + +/** + * Cancel deposit wtid request. This function cannot be used on a request + * handle if a response is already served for it. + * + * @param dwh the wire deposits request handle + */ +void +TALER_MINT_deposit_wtid_cancel (struct TALER_MINT_DepositWtidHandle *dwh) +{ + if (NULL != dwh->job) + { + MAC_job_cancel (dwh->job); + dwh->job = NULL; + } + GNUNET_free_non_null (dwh->db.buf); + GNUNET_free (dwh->url); + GNUNET_free (dwh->json_enc); + GNUNET_free (dwh); +} + + +/* end of mint_api_deposit_wtid.c */ -- cgit v1.2.3 From 5601a81d4dbefcd62ff84b2d6b8802046dc8520a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 22 Jan 2016 16:52:52 +0100 Subject: do not have curl be verbose --- src/mint-lib/mint_api_deposit_wtid.c | 1 - src/mint-lib/mint_api_handle.c | 2 +- src/mint/taler-mint-httpd_tracking.c | 5 ++--- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'src/mint-lib/mint_api_deposit_wtid.c') diff --git a/src/mint-lib/mint_api_deposit_wtid.c b/src/mint-lib/mint_api_deposit_wtid.c index bb81d93e..50f9c55d 100644 --- a/src/mint-lib/mint_api_deposit_wtid.c +++ b/src/mint-lib/mint_api_deposit_wtid.c @@ -300,7 +300,6 @@ TALER_MINT_deposit_wtid (struct TALER_MINT_Handle *mint, GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv, &dtp.purpose, &merchant_sig.eddsa_sig)); - deposit_wtid_obj = json_pack ("{s:o, s:o," /* H_wire, H_contract */ " s:o, s:I," /* coin_pub, transaction_id */ " s:o, s:o}", /* merchant_pub, merchant_sig */ diff --git a/src/mint-lib/mint_api_handle.c b/src/mint-lib/mint_api_handle.c index 077e42c2..c8898d5c 100644 --- a/src/mint-lib/mint_api_handle.c +++ b/src/mint-lib/mint_api_handle.c @@ -757,7 +757,7 @@ TALER_MINT_connect (struct TALER_MINT_Context *ctx, GNUNET_assert (CURLE_OK == curl_easy_setopt (c, CURLOPT_VERBOSE, - 1)); + 0)); GNUNET_assert (CURLE_OK == curl_easy_setopt (c, CURLOPT_STDERR, diff --git a/src/mint/taler-mint-httpd_tracking.c b/src/mint/taler-mint-httpd_tracking.c index 76293803..a6b41cf8 100644 --- a/src/mint/taler-mint-httpd_tracking.c +++ b/src/mint/taler-mint-httpd_tracking.c @@ -121,13 +121,12 @@ TMH_TRACKING_handler_deposit_wtid (struct TMH_RequestHandler *rh, struct TALER_DepositTrackPS tps; uint64_t transaction_id; struct TALER_MerchantSignatureP merchant_sig; - struct TALER_MerchantPublicKeyP merchant_pub; struct TMH_PARSE_FieldSpecification spec[] = { TMH_PARSE_member_fixed ("H_wire", &tps.h_wire), TMH_PARSE_member_fixed ("H_contract", &tps.h_contract), TMH_PARSE_member_fixed ("coin_pub", &tps.coin_pub), TMH_PARSE_member_uint64 ("transaction_id", &transaction_id), - TMH_PARSE_member_fixed ("merchant_pub", &merchant_pub), + TMH_PARSE_member_fixed ("merchant_pub", &tps.merchant), TMH_PARSE_member_fixed ("merchant_sig", &merchant_sig), TMH_PARSE_MEMBER_END }; @@ -154,7 +153,7 @@ TMH_TRACKING_handler_deposit_wtid (struct TMH_RequestHandler *rh, tps.transaction_id = GNUNET_htonll (transaction_id); res = check_and_handle_deposit_wtid_request (connection, &tps, - &merchant_pub, + &tps.merchant, &merchant_sig, transaction_id); TMH_PARSE_release_data (spec); -- cgit v1.2.3 From 46d9cc367bdc9bf8cda7ae12e78ea0a2e0853d36 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 28 Jan 2016 03:58:21 +0100 Subject: finishing core logic for #4141, but untested --- src/include/taler_mint_service.h | 5 +- src/include/taler_mintdb_plugin.h | 6 +- src/include/taler_signatures.h | 14 - src/mint-lib/mint_api_deposit_wtid.c | 9 +- src/mint/taler-mint-aggregator.c | 661 ++++++++++++++++++++++++++++++++-- src/mint/taler-mint-httpd_db.c | 3 - src/mint/taler-mint-httpd_responses.c | 5 - src/mint/taler-mint-httpd_responses.h | 2 +- src/mintdb/plugin_mintdb_postgres.c | 25 +- 9 files changed, 640 insertions(+), 90 deletions(-) (limited to 'src/mint-lib/mint_api_deposit_wtid.c') diff --git a/src/include/taler_mint_service.h b/src/include/taler_mint_service.h index b151cb00..1502edfb 100644 --- a/src/include/taler_mint_service.h +++ b/src/include/taler_mint_service.h @@ -1173,8 +1173,6 @@ struct TALER_MINT_DepositWtidHandle; * yet execute the transaction * @param execution_time actual or planned execution time for the wire transfer * @param coin_contribution contribution to the @a total_amount of the deposited coin (may be NULL) - * @param total_amount total amount of the wire transfer, or NULL if the mint could - * not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK) */ typedef void (*TALER_MINT_DepositWtidCallback)(void *cls, @@ -1182,8 +1180,7 @@ typedef void json_t *json, const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute execution_time, - const struct TALER_Amount *coin_contribution, - const struct TALER_Amount *total_amount); + const struct TALER_Amount *coin_contribution); /** diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 7c48114b..d2cc3d76 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -583,7 +583,6 @@ typedef void * @param coin_contribution how much did the coin we asked about * contribute to the total transfer value? (deposit value including fee) * @param coin_fee how much did the mint charge for the deposit fee - * @param total_amount how much was the total wire transfer? * @param execution_time when was the transaction done, or * when we expect it to be done (if @a wtid was NULL) */ @@ -592,7 +591,6 @@ typedef void const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_Amount *coin_contribution, const struct TALER_Amount *coin_fee, - const struct TALER_Amount *total_amount, struct GNUNET_TIME_Absolute execution_time); @@ -1360,7 +1358,6 @@ struct TALER_MINTDB_Plugin * @param coin_pub which public key was this payment about * @param coin_value amount contributed by this coin in total * @param coin_fee deposit fee charged by mint for this coin - * @param transfer_value total amount of the wire transfer * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors */ int @@ -1374,8 +1371,7 @@ struct TALER_MINTDB_Plugin struct GNUNET_TIME_Absolute execution_time, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, - const struct TALER_Amount *coin_fee, - const struct TALER_Amount *transfer_value); + const struct TALER_Amount *coin_fee); /** diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 85c681da..2526597e 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -953,20 +953,6 @@ struct TALER_ConfirmWirePS */ struct TALER_AmountNBO coin_contribution; - /** - * The total amount the mint transferred in the transaction. - * Note that we may be aggregating multiple coin's @e coin_contribution - * values into a single wire transfer, so this value may be larger - * than that of @e coin_contribution. It may also be smaller, as - * @e coin_contribution may be say "1.123456" but the wire unit may - * be rounded down, i.e. to "1.12" (depending on the transfer method). - * - * Note that the mint books the deltas from rounding down as profit, - * so aggregating transfers is a good thing for the merchant (as it - * reduces rounding down expenses). - */ - struct TALER_AmountNBO total_amount; - }; GNUNET_NETWORK_STRUCT_END diff --git a/src/mint-lib/mint_api_deposit_wtid.c b/src/mint-lib/mint_api_deposit_wtid.c index 50f9c55d..d29f406e 100644 --- a/src/mint-lib/mint_api_deposit_wtid.c +++ b/src/mint-lib/mint_api_deposit_wtid.c @@ -148,9 +148,7 @@ handle_deposit_wtid_finished (void *cls, const struct TALER_WireTransferIdentifierRawP *wtid = NULL; struct GNUNET_TIME_Absolute execution_time = GNUNET_TIME_UNIT_FOREVER_ABS; const struct TALER_Amount *coin_contribution = NULL; - const struct TALER_Amount *total_amount = NULL; struct TALER_Amount coin_contribution_s; - struct TALER_Amount total_amount_s; dwh->job = NULL; json = MAC_download_get_result (&dwh->db, @@ -166,7 +164,6 @@ handle_deposit_wtid_finished (void *cls, MAJ_spec_fixed_auto ("wtid", &dwh->depconf.wtid), MAJ_spec_absolute_time ("execution_time", &execution_time), MAJ_spec_amount ("coin_contribution", &coin_contribution_s), - MAJ_spec_amount ("total_amount", &total_amount_s), MAJ_spec_end }; @@ -183,9 +180,6 @@ handle_deposit_wtid_finished (void *cls, TALER_amount_hton (&dwh->depconf.coin_contribution, &coin_contribution_s); coin_contribution = &coin_contribution_s; - TALER_amount_hton (&dwh->depconf.total_amount, - &total_amount_s); - total_amount = &total_amount_s; if (GNUNET_OK != verify_deposit_wtid_signature_ok (dwh, json)) @@ -244,8 +238,7 @@ handle_deposit_wtid_finished (void *cls, json, wtid, execution_time, - coin_contribution, - total_amount); + coin_contribution); json_decref (json); TALER_MINT_deposit_wtid_cancel (dwh); } diff --git a/src/mint/taler-mint-aggregator.c b/src/mint/taler-mint-aggregator.c index ee0f6ab2..5e05c867 100644 --- a/src/mint/taler-mint-aggregator.c +++ b/src/mint/taler-mint-aggregator.c @@ -18,6 +18,10 @@ * @file taler-mint-aggregator.c * @brief Process that aggregates outgoing transactions and executes them * @author Christian Grothoff + * + * TODO: + * - simplify global_ret: make it a global! + * - handle shutdown more nicely (call 'cancel' method on wire transfers) */ #include "platform.h" #include @@ -62,6 +66,16 @@ static struct TALER_WIRE_Plugin *wire_plugin; */ static struct GNUNET_SCHEDULER_Task *task; +/** + * Limit on the number of transactions we aggregate at once. Note + * that the limit must be big enough to ensure that when transactions + * of the smallest possible unit are aggregated, they do surpass the + * "tiny" threshold beyond which we never trigger a wire transaction! + * + * TODO: make configurable (via config file or command line option) + */ +static unsigned int aggregation_limit = 10000; + /** * Load configuration parameters for the mint @@ -143,11 +157,86 @@ mint_serve_process_config (const char *mint_directory) } +/** + * Information about one aggregation process to + * be executed. + */ +struct AggregationUnit +{ + /** + * Public key of the merchant. + */ + struct TALER_MerchantPublicKeyP merchant_pub; + + /** + * Total amount to be transferred. + */ + struct TALER_Amount total_amount; + + /** + * Hash of @e wire. + */ + struct GNUNET_HashCode h_wire; + + /** + * Wire transfer identifier we use. + */ + struct TALER_WireTransferIdentifierRawP wtid; + + /** + * Row ID of the transaction that started it all. + */ + unsigned long long row_id; + + /** + * The current time. + */ + struct GNUNET_TIME_Absolute execution_time; + + /** + * Wire details of the merchant. + */ + json_t *wire; + + /** + * Database session for all of our transactions. + */ + struct TALER_MINTDB_Session *session; + + /** + * Wire preparation handle. + */ + struct TALER_WIRE_PrepareHandle *ph; + + /** + * Array of #aggregation_limit row_ids from the + * aggregation. + */ + unsigned long long *additional_rows; + + /** + * Pointer to global return value. Closure for #run(). + */ + int *global_ret; + + /** + * Offset specifying how many #additional_rows are in use. + */ + unsigned int rows_offset; + + /** + * Set to #GNUNET_YES if we have to abort due to failure. + */ + int failed; + +}; + + /** * Function called with details about deposits that have been made, * with the goal of executing the corresponding wire transaction. * - * @param cls closure + * @param cls closure with the `struct AggregationUnit` * @param row_id identifies database entry * @param merchant_pub public key of the merchant * @param coin_pub public key of the coin @@ -172,20 +261,187 @@ deposit_cb (void *cls, struct GNUNET_TIME_Absolute wire_deadline, const json_t *wire) { - /* FIXME: compute aggregates, etc. */ + struct AggregationUnit *au = cls; + + au->merchant_pub = *merchant_pub; + if (GNUNET_OK != + TALER_amount_subtract (&au->total_amount, + amount_with_fee, + deposit_fee)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Fatally malformed record at %llu\n", + row_id); + return GNUNET_SYSERR; + } + au->row_id = row_id; + au->wire = (json_t *) wire; + au->execution_time = GNUNET_TIME_absolute_get (); + TALER_hash_json (au->wire, + &au->h_wire); + json_incref (au->wire); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &au->wtid, + sizeof (au->wtid)); + if (GNUNET_OK != + db_plugin->insert_aggregation_tracking (db_plugin->cls, + au->session, + &au->wtid, + merchant_pub, + &au->h_wire, + h_contract, + transaction_id, + au->execution_time, + coin_pub, + amount_with_fee, + deposit_fee)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + db_plugin->mark_deposit_done (db_plugin->cls, + au->session, + row_id)) + { + GNUNET_break (0); + au->failed = GNUNET_YES; + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + + +/** + * Function called with details about another deposit we + * can aggregate into an existing aggregation unit. + * + * @param cls closure with the `struct AggregationUnit` + * @param row_id identifies database entry + * @param merchant_pub public key of the merchant + * @param coin_pub public key of the coin + * @param amount_with_fee amount that was deposited including fee + * @param deposit_fee amount the mint gets to keep as transaction fees + * @param transaction_id unique transaction ID chosen by the merchant + * @param h_contract hash of the contract between merchant and customer + * @param wire_deadline by which the merchant adviced that he would like the + * wire transfer to be executed + * @param wire wire details for the merchant + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +static int +aggregate_cb (void *cls, + unsigned long long row_id, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *amount_with_fee, + const struct TALER_Amount *deposit_fee, + uint64_t transaction_id, + const struct GNUNET_HashCode *h_contract, + struct GNUNET_TIME_Absolute wire_deadline, + const json_t *wire) +{ + struct AggregationUnit *au = cls; + struct TALER_Amount delta; + + GNUNET_break (0 == + memcmp (&au->merchant_pub, + merchant_pub, + sizeof (struct TALER_MerchantPublicKeyP))); + /* compute contribution of this coin after fees */ + if (GNUNET_OK != + TALER_amount_subtract (&delta, + amount_with_fee, + deposit_fee)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Fatally malformed record at %llu\n", + row_id); + return GNUNET_SYSERR; + } + /* add to total */ + if (GNUNET_OK != + TALER_amount_add (&au->total_amount, + &au->total_amount, + &delta)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Overflow or currency incompatibility during aggregation at %llu\n", + row_id); + /* Skip this one, but keep going! */ + return GNUNET_OK; + } + if (au->rows_offset >= aggregation_limit) + { + /* Bug: we asked for at most #aggregation_limit results! */ + GNUNET_break (0); + /* Skip this one, but keep going. */ + return GNUNET_OK; + } + if (NULL == au->additional_rows) + au->additional_rows = GNUNET_new_array (aggregation_limit, + unsigned long long); + /* "append" to our list of rows */ + au->additional_rows[au->rows_offset++] = row_id; + /* insert into aggregation tracking table */ + if (GNUNET_OK != + db_plugin->insert_aggregation_tracking (db_plugin->cls, + au->session, + &au->wtid, + merchant_pub, + &au->h_wire, + h_contract, + transaction_id, + au->execution_time, + coin_pub, + amount_with_fee, + deposit_fee)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + db_plugin->mark_deposit_done (db_plugin->cls, + au->session, + row_id)) + { + GNUNET_break (0); + au->failed = GNUNET_YES; + return GNUNET_SYSERR; + } return GNUNET_OK; } /** - * Main work function that queries the DB and executes transactions. + * Function to be called with the prepared transfer data. + * + * @param cls closure with the `struct AggregationUnit` + * @param buf transaction data to persist, NULL on error + * @param buf_size number of bytes in @a buf, 0 on error + */ +static void +prepare_cb (void *cls, + const char *buf, + size_t buf_size); + + +/** + * Main work function that queries the DB and aggregates transactions + * into larger wire transfers. + * + * @param cls pointer to an `int` which we will return from main() + * @param tc scheduler context */ static void -run (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +run_aggregation (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { int *global_ret = cls; struct TALER_MINTDB_Session *session; + struct AggregationUnit *au; + unsigned int i; int ret; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) @@ -207,50 +463,399 @@ run (void *cls, *global_ret = GNUNET_SYSERR; return; } + au = GNUNET_new (struct AggregationUnit); + au->session = session; ret = db_plugin->get_ready_deposit (db_plugin->cls, session, &deposit_cb, - NULL); - // FIXME: handle 0 == ret... - + au); if (GNUNET_OK != ret) + { + GNUNET_free (au); + db_plugin->rollback (db_plugin->cls, + session); + if (0 != ret) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to execute deposit iteration!\n"); + *global_ret = GNUNET_SYSERR; + return; + } + /* nothing to do, sleep for a minute and try again */ + task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, + &run_aggregation, + global_ret); + return; + } + /* Now try to find other deposits to aggregate */ + ret = db_plugin->iterate_matching_deposits (db_plugin->cls, + session, + &au->h_wire, + &au->merchant_pub, + &aggregate_cb, + au, + aggregation_limit); + if ( (GNUNET_SYSERR == ret) || + (GNUNET_YES == au->failed) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to execute deposit iteration!\n"); + GNUNET_free_non_null (au->additional_rows); + GNUNET_free (au); + db_plugin->rollback (db_plugin->cls, + session); *global_ret = GNUNET_SYSERR; + return; + } + /* Round to the unit supported by the wire transfer method */ + GNUNET_assert (GNUNET_SYSERR != + wire_plugin->amount_round (wire_plugin->cls, + &au->total_amount)); + /* Check if after rounding down, we still have an amount to transfer */ + if ( (0 == au->total_amount.value) && + (0 == au->total_amount.fraction) ) + { + /* Rollback ongoing transaction, as we will not use the respective + WTID and thus need to remove the tracking data */ + db_plugin->rollback (db_plugin->cls, + session); + /* Start another transaction to mark all* of the selected deposits + *as minor! */ + if (GNUNET_OK != + db_plugin->start (db_plugin->cls, + session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to start database transaction!\n"); + *global_ret = GNUNET_SYSERR; + GNUNET_free_non_null (au->additional_rows); + GNUNET_free (au); + return; + } + /* Mark transactions by row_id as minor */ + ret = GNUNET_OK; + if (GNUNET_OK != + db_plugin->mark_deposit_tiny (db_plugin->cls, + session, + au->row_id)) + ret = GNUNET_SYSERR; + else + for (i=0;irows_offset;i++) + if (GNUNET_OK != + db_plugin->mark_deposit_tiny (db_plugin->cls, + session, + au->additional_rows[i])) + ret = GNUNET_SYSERR; + /* commit */ + if (GNUNET_OK != + db_plugin->commit (db_plugin->cls, + session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to commit database transaction!\n"); + } + GNUNET_free_non_null (au->additional_rows); + GNUNET_free (au); + /* start again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + return; + } + au->global_ret = global_ret; + au->ph = wire_plugin->prepare_wire_transfer (wire_plugin->cls, + au->wire, + &au->total_amount, + &au->wtid, + &prepare_cb, + au); + /* FIXME: currently we have no clean-up plan on + shutdown to call prepare_wire_transfer_cancel! + Maybe make 'au' global? */ + if (NULL == au->ph) + { + GNUNET_break (0); /* why? how to best recover? */ db_plugin->rollback (db_plugin->cls, session); + GNUNET_free_non_null (au->additional_rows); + GNUNET_free (au); + /* start again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); return; } - /* FIXME: finish aggregate computation */ - /* wire_plugin->prepare_wire_transfer () -- ASYNC! */ - /* db_plugin->wire_prepare_data_insert () -- transactional! */ - /* db_plugin->XXX () -- mark transactions selected for aggregate as finished */ + /* otherwise we continue with #prepare_cb(), see below */ +} + - /* then finally: commit! */ +/** + * Execute the wire transfers that we have committed to + * do. + * + * @param cls pointer to an `int` which we will return from main() + * @param tc scheduler context + */ +static void +run_transfers (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + + +/** + * Function to be called with the prepared transfer data. + * + * @param cls closure with the `struct AggregationUnit` + * @param buf transaction data to persist, NULL on error + * @param buf_size number of bytes in @a buf, 0 on error + */ +static void +prepare_cb (void *cls, + const char *buf, + size_t buf_size) +{ + struct AggregationUnit *au = cls; + int *global_ret = au->global_ret; + struct TALER_MINTDB_Session *session = au->session; + + GNUNET_free_non_null (au->additional_rows); + GNUNET_free (au); + if (NULL == buf) + { + GNUNET_break (0); /* why? how to best recover? */ + db_plugin->rollback (db_plugin->cls, + session); + /* start again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + return; + } + + /* Commit our intention to execute the wire transfer! */ + if (GNUNET_OK != + db_plugin->wire_prepare_data_insert (db_plugin->cls, + session, + mint_wireformat, + buf, + buf_size)) + { + GNUNET_break (0); /* why? how to best recover? */ + db_plugin->rollback (db_plugin->cls, + session); + /* start again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + return; + } + + /* Now we can finally commit the overall transaction, as we are + again consistent if all of this passes. */ if (GNUNET_OK != db_plugin->commit (db_plugin->cls, session)) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Failed to commit database transaction!\n"); + /* try again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + return; } - /* While possible, run 2nd type of transaction: - db_plugin->start() - - select pre-commit data from DB: - db_plugin->wire_prepare_data_iterate () - - execute wire transfer (successfully!) - wire_plugin->execute_wire_transfer() # ASYNC! - db_plugin->wire_prepare_data_mark_finished () - db_plugin->insert_aggregation_tracking () - db_plugin->commit() - */ + /* run alternative task: actually do wire transfer! */ + task = GNUNET_SCHEDULER_add_now (&run_transfers, + &global_ret); +} + + +/** + * Data we keep to #run_transfers(). + */ +struct WirePrepareData +{ + + /** + * Database session for all of our transactions. + */ + struct TALER_MINTDB_Session *session; + + /** + * Wire execution handle. + */ + struct TALER_WIRE_ExecuteHandle *eh; + + /** + * Pointer to global return value. Closure for #run(). + */ + int *global_ret; + + + /** + * Row ID of the transfer. + */ + unsigned long long row_id; +}; - task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS /* FIXME: adjust! */, - &run, - global_ret); + +/** + * Function called with the result from the execute step. + * + * @param cls closure with the `struct WirePrepareData` + * @param success #GNUNET_OK on success, #GNUNET_SYSERR on failure + * @param emsg NULL on success, otherwise an error message + */ +static void +wire_confirm_cb (void *cls, + int success, + const char *emsg) +{ + struct WirePrepareData *wpd = cls; + int *global_ret = wpd->global_ret; + struct TALER_MINTDB_Session *session = wpd->session; + + wpd->eh = NULL; + if (GNUNET_SYSERR == success) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Wire transaction failed: %s\n", + emsg); + db_plugin->rollback (db_plugin->cls, + session); + *global_ret = GNUNET_SYSERR; + GNUNET_free (wpd); + return; + } + if (GNUNET_OK != + db_plugin->wire_prepare_data_mark_finished (db_plugin->cls, + session, + wpd->row_id)) + { + GNUNET_break (0); /* why!? */ + db_plugin->rollback (db_plugin->cls, + session); + *global_ret = GNUNET_SYSERR; + GNUNET_free (wpd); + return; + } + GNUNET_free (wpd); + if (GNUNET_OK != + db_plugin->commit (db_plugin->cls, + session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Failed to commit database transaction!\n"); + /* try again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + return; + } + /* continue with #run_transfers(), just to guard + against the unlikely case that there are more. */ + task = GNUNET_SCHEDULER_add_now (&run_transfers, + &global_ret); + +} + + +/** + * Callback with data about a prepared transaction. + * + * @param cls closure with the `struct WirePrepareData` + * @param rowid row identifier used to mark prepared transaction as done + * @param buf transaction data that was persisted, NULL on error + * @param buf_size number of bytes in @a buf, 0 on error + */ +static void +wire_prepare_cb (void *cls, + unsigned long long rowid, + const char *buf, + size_t buf_size) +{ + struct WirePrepareData *wpd = cls; + int *global_ret = wpd->global_ret; + + wpd->row_id = rowid; + wpd->eh = wire_plugin->execute_wire_transfer (wire_plugin->cls, + buf, + buf_size, + &wire_confirm_cb, + wpd); + /* FIXME: currently we have no clean-up plan on + shutdown to call execute_wire_transfer_cancel! + Maybe make 'wpd' global? */ + if (NULL == wpd->eh) + { + GNUNET_break (0); /* why? how to best recover? */ + db_plugin->rollback (db_plugin->cls, + wpd->session); + *global_ret = GNUNET_SYSERR; + GNUNET_free (wpd); + return; + } +} + + +/** + * Execute the wire transfers that we have committed to + * do. + * + * @param cls pointer to an `int` which we will return from main() + * @param tc scheduler context + */ +static void +run_transfers (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + int *global_ret = cls; + int ret; + struct WirePrepareData *wpd; + struct TALER_MINTDB_Session *session; + + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + return; + if (NULL == (session = db_plugin->get_session (db_plugin->cls, + GNUNET_NO))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to obtain database session!\n"); + *global_ret = GNUNET_SYSERR; + return; + } + if (GNUNET_OK != + db_plugin->start (db_plugin->cls, + session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to start database transaction!\n"); + *global_ret = GNUNET_SYSERR; + return; + } + wpd = GNUNET_new (struct WirePrepareData); + wpd->session = session; + wpd->global_ret = global_ret; + ret = db_plugin->wire_prepare_data_get (db_plugin->cls, + session, + mint_wireformat, + &wire_prepare_cb, + wpd); + if (GNUNET_SYSERR == ret) + { + GNUNET_break (0); /* why? how to best recover? */ + db_plugin->rollback (db_plugin->cls, + session); + *global_ret = GNUNET_SYSERR; + GNUNET_free (wpd); + return; + } + if (GNUNET_NO == ret) + { + /* no more prepared wire transfers, go back to aggregation! */ + db_plugin->rollback (db_plugin->cls, + session); + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + GNUNET_free (wpd); + return; + } + /* otherwise, continues in #wire_prepare_cb() */ } @@ -299,7 +904,7 @@ main (int argc, return 1; } - GNUNET_SCHEDULER_run (&run, &ret); + GNUNET_SCHEDULER_run (&run_transfers, &ret); TALER_MINTDB_plugin_unload (db_plugin); TALER_WIRE_plugin_unload (wire_plugin); diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index c39cbbcf..b93ead3a 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -1804,7 +1804,6 @@ struct DepositWtidContext * @param coin_contribution how much did the coin we asked about * contribute to the total transfer value? (deposit value including fee) * @param coin_fee how much did the mint charge for the deposit fee - * @param total_amount how much was the total wire transfer? * @param execution_time when was the transaction done, or * when we expect it to be done (if @a wtid was NULL); * #GNUNET_TIME_UNIT_FOREVER_ABS if the /deposit is unknown @@ -1815,7 +1814,6 @@ handle_wtid_data (void *cls, const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_Amount *coin_contribution, const struct TALER_Amount *coin_fee, - const struct TALER_Amount *total_amount, struct GNUNET_TIME_Absolute execution_time) { struct DepositWtidContext *ctx = cls; @@ -1843,7 +1841,6 @@ handle_wtid_data (void *cls, &ctx->h_wire, &ctx->coin_pub, &coin_delta, - total_amount, ctx->transaction_id, wtid, execution_time); diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 041f694b..2ebd0d33 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -1097,7 +1097,6 @@ TMH_RESPONSE_reply_deposit_pending (struct MHD_Connection *connection, * @param coin_pub public key of the coin * @param coin_contribution how much did the coin we asked about * contribute to the total transfer value? (deposit value minus fee) - * @param total_amount how much was the total wire transfer? * @param transaction_id merchant transaction identifier * @param wtid raw wire transfer identifier * @param exec_time execution time of the wire transfer @@ -1109,7 +1108,6 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, const struct GNUNET_HashCode *h_wire, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_contribution, - const struct TALER_Amount *total_amount, uint64_t transaction_id, const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute exec_time) @@ -1128,8 +1126,6 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, cw.execution_time = GNUNET_TIME_absolute_hton (exec_time); TALER_amount_hton (&cw.coin_contribution, coin_contribution); - TALER_amount_hton (&cw.total_amount, - total_amount); TMH_KS_sign (&cw.purpose, &pub, &sig); @@ -1140,7 +1136,6 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, sizeof (*wtid)), "execution_time", TALER_json_from_abs (exec_time), "coin_contribution", TALER_json_from_amount (coin_contribution), - "total_amount", TALER_json_from_amount (total_amount), "mint_sig", TALER_json_from_data (&sig, sizeof (sig)), "mint_pub", TALER_json_from_data (&pub, diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index caad2904..a0396c8a 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h @@ -280,6 +280,7 @@ TMH_RESPONSE_reply_deposit_pending (struct MHD_Connection *connection, * @param h_contract hash of the contract * @param h_wire hash of wire account details * @param coin_pub public key of the coin + * @param coin_contribution contribution of this coin to the total amount transferred * @param transaction_id merchant transaction identifier * @param wtid raw wire transfer identifier * @param exec_time execution time of the wire transfer @@ -291,7 +292,6 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, const struct GNUNET_HashCode *h_wire, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_contribution, - const struct TALER_Amount *total_amount, uint64_t transaction_id, const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute exec_time); diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index fc204f5e..2ab3e81a 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -466,9 +466,6 @@ postgres_create_tables (void *cls, ",coin_fee_val INT8 NOT NULL" ",coin_fee_frac INT4 NOT NULL" ",coin_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" - ",transfer_total_val INT8 NOT NULL" - ",transfer_total_frac INT4 NOT NULL" - ",transfer_total_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" ")"); /* Index for lookup_transactions statement on wtid */ SQLEXEC_INDEX("CREATE INDEX aggregation_tracking_wtid_index " @@ -1090,9 +1087,6 @@ postgres_prepare (PGconn *db_conn) ",coin_fee_val" ",coin_fee_frac" ",coin_fee_curr" - ",transfer_total_val" - ",transfer_total_frac" - ",transfer_total_curr" " FROM aggregation_tracking" " WHERE wtid_raw=$1", 1, NULL); @@ -1108,9 +1102,6 @@ postgres_prepare (PGconn *db_conn) ",coin_fee_val" ",coin_fee_frac" ",coin_fee_curr" - ",transfer_total_val" - ",transfer_total_frac" - ",transfer_total_curr" " FROM aggregation_tracking" " WHERE" " coin_pub=$1 AND" @@ -1136,12 +1127,9 @@ postgres_prepare (PGconn *db_conn) ",coin_fee_val" ",coin_fee_frac" ",coin_fee_curr" - ",transfer_total_val" - ",transfer_total_frac" - ",transfer_total_curr" ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)", - 16, NULL); + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)", + 13, NULL); /* Used in #postgres_wire_prepare_data_insert() to store @@ -3950,7 +3938,6 @@ postgres_wire_lookup_deposit_wtid (void *cls, NULL, &coin_amount, &coin_fee, - NULL, exec_time); PQclear (result); return GNUNET_YES; @@ -3967,13 +3954,11 @@ postgres_wire_lookup_deposit_wtid (void *cls, struct GNUNET_TIME_Absolute exec_time; struct TALER_Amount coin_amount; struct TALER_Amount coin_fee; - struct TALER_Amount transaction_amount; struct TALER_PQ_ResultSpec rs[] = { TALER_PQ_result_spec_auto_from_type ("wtid_raw", &wtid), TALER_PQ_result_spec_absolute_time ("execution_time", &exec_time), TALER_PQ_result_spec_amount ("coin_amount", &coin_amount), TALER_PQ_result_spec_amount ("coin_fee", &coin_fee), - TALER_PQ_result_spec_amount ("transfer_total", &transaction_amount), TALER_PQ_result_spec_end }; if (GNUNET_OK != TALER_PQ_extract_result (result, rs, 0)) @@ -3986,7 +3971,6 @@ postgres_wire_lookup_deposit_wtid (void *cls, &wtid, &coin_amount, &coin_fee, - &transaction_amount, exec_time); } PQclear (result); @@ -4007,7 +3991,6 @@ postgres_wire_lookup_deposit_wtid (void *cls, * @param coin_pub which public key was this payment about * @param coin_value amount contributed by this coin in total * @param coin_fee deposit fee charged by mint for this coin - * @param transfer_value total amount of the wire transfer * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors */ static int @@ -4021,8 +4004,7 @@ postgres_insert_aggregation_tracking (void *cls, struct GNUNET_TIME_Absolute execution_time, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, - const struct TALER_Amount *coin_fee, - const struct TALER_Amount *transfer_value) + const struct TALER_Amount *coin_fee) { struct TALER_PQ_QueryParam params[] = { TALER_PQ_query_param_auto_from_type (h_contract), @@ -4034,7 +4016,6 @@ postgres_insert_aggregation_tracking (void *cls, TALER_PQ_query_param_absolute_time (&execution_time), TALER_PQ_query_param_amount (coin_value), TALER_PQ_query_param_amount (coin_fee), - TALER_PQ_query_param_amount (transfer_value), TALER_PQ_query_param_end }; PGresult *result; -- cgit v1.2.3