diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-05-05 21:24:37 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-05-05 21:24:37 +0200 |
commit | 68fcf5f245b9beccf157f95f06984508df95730a (patch) | |
tree | 8393623e7fb5a312ca21557f98252908dd54a85c /src | |
parent | 9d33dde616b0d227b76e9692304cdb22507c72bc (diff) | |
download | merchant-68fcf5f245b9beccf157f95f06984508df95730a.tar.gz merchant-68fcf5f245b9beccf157f95f06984508df95730a.tar.bz2 merchant-68fcf5f245b9beccf157f95f06984508df95730a.zip |
fix backenddb
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-transfers.c | 497 | ||||
-rw-r--r-- | src/backenddb/merchant-0001.sql | 11 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 119 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 19 |
4 files changed, 318 insertions, 328 deletions
diff --git a/src/backend/taler-merchant-httpd_private-post-transfers.c b/src/backend/taler-merchant-httpd_private-post-transfers.c index 7f55c917..6304761f 100644 --- a/src/backend/taler-merchant-httpd_private-post-transfers.c +++ b/src/backend/taler-merchant-httpd_private-post-transfers.c @@ -14,8 +14,8 @@ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** - * @file backend/taler-merchant-httpd_track-transfer.c - * @brief implement API for tracking transfers and wire transfers + * @file backend/taler-merchant-httpd_private-post-transfers.c + * @brief implement API for registering wire transfers * @author Marcello Stanisci * @author Christian Grothoff */ @@ -23,11 +23,9 @@ #include <jansson.h> #include <taler/taler_signatures.h> #include <taler/taler_json_lib.h> -#include "taler-merchant-httpd.h" -#include "taler-merchant-httpd_mhd.h" #include "taler-merchant-httpd_auditors.h" #include "taler-merchant-httpd_exchanges.h" -#include "taler-merchant-httpd_track-transfer.h" +#include "taler-merchant-httpd_private-post-transfers.h" /** @@ -42,20 +40,45 @@ #define MAX_RETRIES 3 /** - * Context used for handing /track/transfer requests. + * Context used for handing POST /private/transfers requests. */ struct TrackTransferContext { /** - * This MUST be first! + * Kept in a DLL. */ - struct TM_HandlerContext hc; + struct TrackTransferContext *next; /** - * Handle to the exchange. + * Kept in a DLL. */ - struct TALER_EXCHANGE_Handle *eh; + struct TrackTransferContext *prev; + + /** + * Argument for the /wire/transfers request. + */ + struct TALER_WireTransferIdentifierRawP wtid; + + /** + * Amount of the wire transfer. + */ + struct TALER_Amount amount; + + /** + * URL of the exchange. + */ + char *exchange_url; + + /** + * payto:// URI used for the transfer. + */ + char *payto_uri; + + /** + * Master public key of the exchange at @e exchange_url. + */ + struct TALER_MasterPublicKeyP master_pub; /** * Handle for the /wire/transfers request. @@ -89,15 +112,6 @@ struct TrackTransferContext */ struct GNUNET_SCHEDULER_Task *timeout_task; - /** - * URL of the exchange. - */ - char *url; - - /** - * Wire method used for the transfer. - */ - char *wire_method; /** * Pointer to the detail that we are currently @@ -106,21 +120,6 @@ struct TrackTransferContext const struct TALER_TrackTransferDetails *current_detail; /** - * Argument for the /wire/transfers request. - */ - struct TALER_WireTransferIdentifierRawP wtid; - - /** - * Full original response we are currently processing. - */ - const json_t *original_response; - - /** - * Modified response to return to the frontend. - */ - json_t *deposits_response; - - /** * Which transaction detail are we currently looking at? */ unsigned int current_offset; @@ -140,13 +139,32 @@ struct TrackTransferContext /** + * Head of list of suspended requests. + */ +static struct TrackTransferContext *pth_head; + +/** + * Tail of list of suspended requests. + */ +static struct TrackTransferContext *pth_tail; + + +/** * Represents an entry in the table used to sum up - * individual deposits for each h_contract_terms. + * individual deposits for each h_contract_terms/order_id + * (as the exchange gives us per coin, and we return + * per order). FIXME: decide whether we do this HERE + * or in the DB! (SUM()...) */ struct Entry { /** + * Order of the entry. FIXME: to be used!? + */ + char *order_id; + + /** * Sum accumulator for deposited value. */ struct TALER_Amount deposit_value; @@ -404,13 +422,16 @@ resume_track_transfer_with_response (struct TrackTransferContext *rctx, rctx->response_code = response_code; rctx->response = response; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Resuming /track/transfer handling as exchange interaction is done (%u)\n", + "Resuming POST /transfers handling as exchange interaction is done (%u)\n", response_code); if (NULL != rctx->timeout_task) { GNUNET_SCHEDULER_cancel (rctx->timeout_task); rctx->timeout_task = NULL; } + GNUNET_CONTAINER_DLL_remove (pth_head, + pth_tail, + rctx); MHD_resume_connection (rctx->connection); TMH_trigger_daemon (); /* we resumed, kick MHD */ } @@ -419,12 +440,12 @@ resume_track_transfer_with_response (struct TrackTransferContext *rctx, /** * Custom cleanup routine for a `struct TrackTransferContext`. * - * @param hc the `struct TrackTransferContext` to clean up. + * @param cls the `struct TrackTransferContext` to clean up. */ static void -track_transfer_cleanup (struct TM_HandlerContext *hc) +track_transfer_cleanup (void *cls) { - struct TrackTransferContext *rctx = (struct TrackTransferContext *) hc; + struct TrackTransferContext *rctx = cls; free_transfer_track_context (rctx); } @@ -511,30 +532,19 @@ check_wire_fee (struct TrackTransferContext *rctx, struct GNUNET_TIME_Absolute execution_time, const struct TALER_Amount *wire_fee) { - const struct TALER_MasterPublicKeyP *master_pub; - struct GNUNET_HashCode h_wire_method; struct TALER_Amount expected_fee; struct TALER_Amount closing_fee; struct TALER_MasterSignatureP master_sig; struct GNUNET_TIME_Absolute start_date; struct GNUNET_TIME_Absolute end_date; enum GNUNET_DB_QueryStatus qs; - const struct TALER_EXCHANGE_Keys *keys; + char *wire_method; - keys = TALER_EXCHANGE_get_keys (rctx->eh); - if (NULL == keys) - { - GNUNET_break (0); - return GNUNET_NO; - } - master_pub = &keys->master_pub; - GNUNET_CRYPTO_hash (rctx->wire_method, - strlen (rctx->wire_method) + 1, - &h_wire_method); + wire_method = TALER_payto_get_method (rctx->payto_uri); db->preflight (db->cls); qs = db->lookup_wire_fee (db->cls, - master_pub, - &h_wire_method, + &rctx->master_pub, + wire_method, execution_time, &expected_fee, &closing_fee, @@ -545,16 +555,19 @@ check_wire_fee (struct TrackTransferContext *rctx, { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to find wire fee for `%s' and method `%s' at %s in DB, accepting blindly that the fee is %s\n", - TALER_B2S (master_pub), - rctx->wire_method, + TALER_B2S (&rctx->master_pub), + wire_method, GNUNET_STRINGS_absolute_time_to_string (execution_time), TALER_amount2s (wire_fee)); + GNUNET_free (wire_method); return GNUNET_NO; } if (0 <= TALER_amount_cmp (&expected_fee, wire_fee)) + { + GNUNET_free (wire_method); return GNUNET_OK; /* expected_fee >= wire_fee */ - + } /* Wire fee check failed, export proof to client */ resume_track_transfer_with_response ( rctx, @@ -569,8 +582,9 @@ check_wire_fee (struct TrackTransferContext *rctx, "start_date", GNUNET_JSON_from_time_abs (start_date), "end_date", GNUNET_JSON_from_time_abs (end_date), "master_sig", GNUNET_JSON_from_data_auto (&master_sig), - "master_pub", GNUNET_JSON_from_data_auto (master_pub), + "master_pub", GNUNET_JSON_from_data_auto (&rctx->master_pub), "json", json)); + GNUNET_free (wire_method); return GNUNET_SYSERR; } @@ -607,7 +621,7 @@ wire_transfer_cb (void *cls, rctx->wdh = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Got response code %u from exchange for /track/transfer\n", + "Got response code %u from exchange for GET /transfers/$WTID\n", hr->http_status); if (MHD_HTTP_OK != hr->http_status) { @@ -622,36 +636,33 @@ wire_transfer_cb (void *cls, "exchange_reply", hr->reply)); return; } - for (unsigned int i = 0; i<MAX_RETRIES; i++) - { - db->preflight (db->cls); - qs = db->store_transfer_to_proof (db->cls, - rctx->url, - &rctx->wtid, - execution_time, - exchange_pub, - hr->reply); - if (GNUNET_DB_STATUS_SOFT_ERROR != qs) - break; - } + db->preflight (db->cls); + qs = db->insert_transfer_details (db->cls, + rctx->exchange_url, + rctx->payto_uri, + &rctx->wtid, + total_amount, + wire_fee, + execution_time, + details_length, + details); if (0 > qs) { /* Special report if retries insufficient */ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); /* Always report on hard error as well to enable diagnostics */ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); - resume_track_transfer_with_response - (rctx, + resume_track_transfer_with_response ( + rctx, MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_MHD_make_json_pack ("{s:I, s:s}", - "code", - (json_int_t) - TALER_EC_TRACK_TRANSFER_DB_STORE_TRANSFER_ERROR, - "details", - "failed to store response from exchange to local database")); + TALER_MHD_make_json_pack ( + "{s:I, s:s}", + "code", + (json_int_t) TALER_EC_TRACK_TRANSFER_DB_STORE_TRANSFER_ERROR, + "details", + "failed to store response from exchange to local database")); return; } - rctx->original_response = hr->reply; if (GNUNET_SYSERR == check_wire_fee (rctx, @@ -767,27 +778,11 @@ wire_transfer_cb (void *cls, return; } } - rctx->original_response = NULL; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "About to call tracks transformator.\n"); - - if (NULL == (jresponse = - transform_response (hr->reply, - rctx))) - { - resume_track_transfer_with_response - (rctx, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_MHD_make_error (TALER_EC_TRACK_TRANSFER_JSON_RESPONSE_ERROR, - "Fail to elaborate the response.")); - return; - } + /* resume processing, main function will build the response */ resume_track_transfer_with_response (rctx, - MHD_HTTP_OK, - TALER_MHD_make_json (jresponse)); - json_decref (jresponse); + 0, + NULL); } @@ -801,12 +796,12 @@ wire_transfer_cb (void *cls, * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config */ static void -process_track_transfer_with_exchange (void *cls, - const struct - TALER_EXCHANGE_HttpResponse *hr, - struct TALER_EXCHANGE_Handle *eh, - const struct TALER_Amount *wire_fee, - int exchange_trusted) +process_track_transfer_with_exchange ( + void *cls, + const struct TALER_EXCHANGE_HttpResponse *hr, + struct TALER_EXCHANGE_Handle *eh, + const struct TALER_Amount *wire_fee, + int exchange_trusted) { struct TrackTransferContext *rctx = cls; @@ -829,7 +824,20 @@ process_track_transfer_with_exchange (void *cls, "exchange_reply", hr->reply)); return; } - rctx->eh = eh; + + /* keep master key for later */ + { + const struct TALER_EXCHANGE_Keys *keys; + + keys = TALER_EXCHANGE_get_keys (eh); + if (NULL == keys) + { + GNUNET_break (0); + return GNUNET_NO; + } + rctx->master_pub = keys->master_pub; + } + rctx->wdh = TALER_EXCHANGE_transfers_get (eh, &rctx->wtid, &wire_transfer_cb, @@ -837,20 +845,48 @@ process_track_transfer_with_exchange (void *cls, if (NULL == rctx->wdh) { GNUNET_break (0); - resume_track_transfer_with_response - (rctx, + resume_track_transfer_with_response ( + rctx, MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_MHD_make_json_pack ("{s:I, s:s}", - "code", - (json_int_t) - TALER_EC_TRACK_TRANSFER_REQUEST_ERROR, - "error", - "failed to run /transfers/ GET on exchange")); + TALER_MHD_make_json_pack ( + "{s:I, s:s}", + "code", + (json_int_t) TALER_EC_TRACK_TRANSFER_REQUEST_ERROR, + "error", + "failed to run GET /transfers/ on exchange")); } } /** + * Function called with information about a wire transfer identifier. + * Generate a response array based on the given information. + * + * @param cls closure, a `json_t` array to update + * @param order_id the order to which the deposits belong + * @param deposit_value the amount deposited under @a order_id + * @param deposit_fee the fee charged for @a deposit_value + */ +static void +proof_cb (void *cls, + const char *order_id, + const struct TALER_Amount *deposit_value, + const struct TALER_Amount *deposit_fee) +{ + json_t *ja = cls; + + GNUNET_assert ( + 0 == + json_array_append_new ( + ja, + "{s:s,s:o,s:o}", + "order_id", order_id, + "deposit_value", TALER_JSON_spec_amount (deposit_value), + "deposit_fee", TALER_JSON_spec_amount (deposit_fee))); +} + + +/** * Handle a timeout for the processing of the track transfer request. * * @param cls closure @@ -861,14 +897,18 @@ handle_track_transfer_timeout (void *cls) struct TrackTransferContext *rctx = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Resuming /track/transfer with error after timeout\n"); + "Resuming POST /private/transfers with error after timeout\n"); rctx->timeout_task = NULL; - if (NULL != rctx->fo) { TMH_EXCHANGES_find_exchange_cancel (rctx->fo); rctx->fo = NULL; } + if (NULL != rctx->wdh) + { + TALER_EXCHANGE_transfers_get_cancel (rctx->wdh); + rctx->wdh = NULL; + } resume_track_transfer_with_response (rctx, MHD_HTTP_SERVICE_UNAVAILABLE, TALER_MHD_make_error ( @@ -878,81 +918,38 @@ handle_track_transfer_timeout (void *cls) /** - * Function called with information about a wire transfer identifier. - * Generate a response based on the given @a proof. - * - * @param cls closure - * @param proof proof from exchange about what the wire transfer was for. - * should match the `TrackTransactionResponse` format - * of the exchange - */ -static void -proof_cb (void *cls, - const json_t *proof) -{ - struct TrackTransferContext *rctx = cls; - json_t *transformed_response; - - if (NULL == (transformed_response = - transform_response (proof, - rctx))) - { - rctx->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - rctx->response - = TALER_MHD_make_error (TALER_EC_TRACK_TRANSFER_JSON_RESPONSE_ERROR, - "Fail to elaborate response."); - return; - } - - rctx->response_code = MHD_HTTP_OK; - rctx->response = TALER_MHD_make_json (transformed_response); - json_decref (transformed_response); -} - - -/** - * Manages a /track/transfer call, thus it calls the /track/wtid - * offered by the exchange in order to return the set of transfers + * Manages a POST /private/transfers call. It calls the /track/wtid + * offered by the exchange in order to obtain the set of transfers * (of coins) associated with a given wire transfer. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @param mi merchant backend instance, never NULL + * @param[in,out] hc context with further information about the request * @return MHD result code */ MHD_RESULT -MH_handler_track_transfer (struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size, - struct MerchantInstance *mi) +TMH_private_post_transfers (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) { - struct TrackTransferContext *rctx; + struct TrackTransferContext *rctx = hc->ctx; const char *str; const char *url; const char *wire_method; - MHD_RESULT ret; enum GNUNET_DB_QueryStatus qs; - if (NULL == *connection_cls) + if (NULL == rctx) { rctx = GNUNET_new (struct TrackTransferContext); - rctx->hc.cc = &track_transfer_cleanup; rctx->connection = connection; - *connection_cls = rctx; - } - else - { - /* not first call, recover state */ - rctx = *connection_cls; + hc->ctx = rctx; + hc->cleanup_cb = &track_transfer_cleanup; } if (0 != rctx->response_code) { + MHD_RESULT ret; + /* We are *done* processing the request, just queue the response (!) */ if (UINT_MAX == rctx->response_code) { @@ -968,13 +965,13 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh, rctx->response = NULL; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Queueing response (%u) for /track/transfer (%s).\n", + "Queueing response (%u) for POST /private/transfers (%s).\n", (unsigned int) rctx->response_code, ret ? "OK" : "FAILED"); return ret; } if ( (NULL != rctx->fo) || - (NULL != rctx->eh) ) + (NULL != rctx->wdh) ) { /* likely old MHD version */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -982,66 +979,85 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh, return MHD_YES; /* still work in progress */ } - url = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "exchange"); - if (NULL == url) - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_PARAMETER_MISSING, - "exchange"); - rctx->url = GNUNET_strdup (url); - - /* FIXME: change again: we probably don't want the wire_method - but rather the _account_ (section) here! */ - wire_method = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "wire_method"); - if (NULL == wire_method) { - if (1) + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("exchange", + &rctx->exchange_url), + GNUNET_JSON_spec_string ("payto_uri", + &rctx->payto_uri), + TALER_JSON_spec_amount ("amount", + &rctx->amount), + GNUNET_JSON_spec_fixed_auto ("wtid", + &rctx->wtid), + GNUNET_JSON_spec_end () + }; + + GNUNET_assert (NULL != mi); { - /* temporary work-around until demo is adjusted... */ - GNUNET_break (0); - wire_method = "x-taler-bank"; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Client needs fixing, see API change for #4943!\n"); + enum GNUNET_GenericReturnValue res; + + res = TALER_MHD_parse_json_data (connection, + hc->request_body, + spec); + if (GNUNET_OK != res) + return (GNUNET_NO == res) + ? MHD_YES + : MHD_NO; } - else - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_PARAMETER_MISSING, - "wire_method"); } - rctx->wire_method = GNUNET_strdup (wire_method); - rctx->mi = mi; - str = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "wtid"); - if (NULL == str) - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_PARAMETER_MISSING, - "wtid"); - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (str, - strlen (str), - &rctx->wtid, - sizeof (rctx->wtid))) + + /* Check if reply is already in database! */ { - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_PARAMETER_MALFORMED, - "wtid"); + json_t *deposit_sums; + struct GNUNET_TIME_Absolute execution_time; + struct TALER_Amount total_amount; + struct TALER_Amount wire_fee; + + deposit_sums = json_array (); + GNUNET_assert (NULL != deposit_sums); + db->preflight (db->cls); + qs = db->lookup_transfer_details (db->cls, + rctx->exchange_url, + rctx->payto_uri, + &rctx->wtid, + &total_amount, + &wire_fee, + &execution_time, + &transfer_details_cb, + deposit_sums); + if (0 > qs) + { + /* Simple select queries should not cause serialization issues */ + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); + /* Always report on hard error as well to enable diagnostics */ + GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); + json_decref (deposit_sums); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_POST_TRANSFERS_DB_LOOKUP_ERROR, + "Fail to query database about proofs"); + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs) + { + return TALER_MHD_reply_json_pack ( + connection, + MHD_HTTP_OK, + "{s:o,s:o,s:o,s:o}", + "total", TALER_JSON_from_amount (&total_amount), + "wire_fee", TALER_JSON_from_amount (&wire_fee), + "execution_time", GNUNET_JSON_from_time_abs (execution_time), + "deposit_sums", deposit_sums); + } + json_decref (deposit_sums); } - /* Check if reply is already in database! */ - db->preflight (db->cls); - qs = db->find_proof_by_wtid (db->cls, - rctx->url, - &rctx->wtid, - &proof_cb, - rctx); + /* reply not in database, ensure the POST is in the database, and + start work to obtain the reply from the exchange */ + qs = db->insert_transfer (db->cls, + rctx->exchange_url, + &rctx->wtid, + &rctx->amount, + rctx->payto_uri); if (0 > qs) { /* Simple select queries should not cause serialization issues */ @@ -1050,30 +1066,17 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh, GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_TRACK_TRANSFER_DB_FETCH_DEPOSIT_ERROR, - "Fail to query database about proofs"); - } - if (0 != rctx->response_code) - { - ret = MHD_queue_response (connection, - rctx->response_code, - rctx->response); - if (NULL != rctx->response) - { - MHD_destroy_response (rctx->response); - rctx->response = NULL; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Queueing response (%u) for /track/transfer (%s).\n", - (unsigned int) rctx->response_code, - ret ? "OK" : "FAILED"); - return ret; + TALER_EC_POST_TRANSFER_DB_STORE_ERROR, + "Fail to update database with transfer record"); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Suspending /track/transfer handling while working with the exchange\n"); + "Suspending POST /private/transfers handling while working with exchange\n"); MHD_suspend_connection (connection); - rctx->fo = TMH_EXCHANGES_find_exchange (url, + GNUNET_CONTAINER_DLL_insert (pth_head, + pth_tail, + rctx); + rctx->fo = TMH_EXCHANGES_find_exchange (rctx->exchange_url, NULL, GNUNET_NO, &process_track_transfer_with_exchange, @@ -1086,4 +1089,4 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh, } -/* end of taler-merchant-httpd_track-transfer.c */ +/* end of taler-merchant-httpd_private-post-transfers.c */ diff --git a/src/backenddb/merchant-0001.sql b/src/backenddb/merchant-0001.sql index 31903f84..6abc0554 100644 --- a/src/backenddb/merchant-0001.sql +++ b/src/backenddb/merchant-0001.sql @@ -334,11 +334,20 @@ CREATE TABLE IF NOT EXISTS merchant_refund_proofs (refund_serial BIGINT PRIMARY KEY REFERENCES merchant_refunds (refund_serial) ON DELETE CASCADE ,exchange_sig BYTEA NOT NULL CHECK (LENGTH(exchange_sig)=64) + ,execution_time INT8 NOT NULL + ,total_amount_val INT8 NOT NULL + ,total_amount_frac INT4 NOT NULL + ,wire_fee_val INT8 NOT NULL + ,wire_fee_frac INT4 NOT NULL ,signkey_serial BIGINT NOT NULL REFERENCES merchant_exchange_signing_keys (signkey_serial) ON DELETE CASCADE ); COMMENT ON TABLE merchant_refund_proofs IS 'Refunds confirmed by the exchange (not all approved refunds are grabbed by the wallet)'; +COMMENT ON COLUMN merchant_refund_proofs.execution_time + IS 'When did the exchange claim to execute the wire transfer'; +COMMENT ON COLUMN merchant_refund_proofs.total_amount_val + IS 'Amount the exchange claims to have deducted from the merchant balance; actual transfer amount is this minus the wire fee'; -------------------- Wire transfers --------------------------- @@ -408,7 +417,7 @@ CREATE TABLE IF NOT EXISTS merchant_deposit_to_transfer ,signkey_serial BIGINT NOT NULL REFERENCES merchant_exchange_signing_keys (signkey_serial) ON DELETE CASCADE ,exchange_sig BYTEA NOT NULL CHECK (LENGTH(exchange_sig)=64) - ,UNIQUE(coin_pub,wtid) + ,UNIQUE(deposit_serial,credit_serial) ); COMMENT ON TABLE merchant_deposit_to_transfer IS 'Mapping of deposits to (possibly unconfirmed) wire transfers'; diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index f95f346f..15996425 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -2444,6 +2444,45 @@ postgres_increase_refund (void *cls, } +/** + * Retrieve the order ID that was used to pay for a resource within a session. + * + * @param cls closure + * @param instance_id identifying the instance + * @param fulfillment_url URL that canonically identifies the resource + * being paid for + * @param session_id session id + * @param[out] order_id where to store the order ID that was used when + * paying for the resource URL + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +postgres_lookup_order_by_fulfillment (void *cls, + const char *instance_id, + const char *fulfillment_url, + const char *session_id, + char **order_id) +{ + struct PostgresClosure *pg = cls; + + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (fulfillment_url), + GNUNET_PQ_query_param_string (session_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("order_id", + order_id), + GNUNET_PQ_result_spec_end + }; + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_order_by_fulfillment", + params, + rs); +} + + /* ********************* OLD API ************************** */ /** @@ -2560,47 +2599,6 @@ postgres_insert_session_info (void *cls, /** - * Retrieve the order ID that was used to pay for a resource within a session. - * - * @param cls closure - * @param[out] order_id where to store the order ID that was used when - * paying for the resource URL - * @param session_id session id - * @param fulfillment_url URL that canonically identifies the resource - * being paid for - * @param merchant_pub public key of the merchant, identifying the instance - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -postgres_find_session_info (void *cls, - char **order_id, - const char *session_id, - const char *fulfillment_url, - const struct TALER_MerchantPublicKeyP *merchant_pub) -{ - struct PostgresClosure *pg = cls; - - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (fulfillment_url), - GNUNET_PQ_query_param_string (session_id), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("order_id", - order_id), - GNUNET_PQ_result_spec_end - }; - // We don't clean up the result spec since we want - // to keep around the memory for order_id. - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "find_session_info", - params, - rs); -} - - -/** * Insert mapping of @a coin_pub and @a h_contract_terms to * corresponding @a wtid. * @@ -3619,26 +3617,24 @@ postgres_put_refund_proof ( static enum GNUNET_DB_QueryStatus postgres_store_wire_fee_by_exchange ( void *cls, - const struct - TALER_MasterPublicKeyP *exchange_pub, - const struct - GNUNET_HashCode *h_wire_method, + const struct TALER_MasterPublicKeyP *master_pub, + const struct GNUNET_HashCode *h_wire_method, const struct TALER_Amount *wire_fee, const struct TALER_Amount *closing_fee, struct GNUNET_TIME_Absolute start_date, struct GNUNET_TIME_Absolute end_date, const struct - TALER_MasterSignatureP *exchange_sig) + TALER_MasterSignatureP *master_sig) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (exchange_pub), + GNUNET_PQ_query_param_auto_from_type (master_pub), GNUNET_PQ_query_param_auto_from_type (h_wire_method), TALER_PQ_query_param_amount (wire_fee), TALER_PQ_query_param_amount (closing_fee), GNUNET_PQ_query_param_absolute_time (&start_date), GNUNET_PQ_query_param_absolute_time (&end_date), - GNUNET_PQ_query_param_auto_from_type (exchange_sig), + GNUNET_PQ_query_param_auto_from_type (master_sig), GNUNET_PQ_query_param_end }; @@ -3646,7 +3642,7 @@ postgres_store_wire_fee_by_exchange ( check_connection (pg); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Storing wire fee for %s starting at %s of %s\n", - TALER_B2S (exchange_pub), + TALER_B2S (master_pub), GNUNET_STRINGS_absolute_time_to_string (start_date), TALER_amount2s (wire_fee)); return GNUNET_PQ_eval_prepared_non_select (pg->conn, @@ -5634,6 +5630,18 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) " FROM merchant_instances" " WHERE merchant_id=$1))", 2), + /* for postgres_lookup_order_by_fulfillment() */ + GNUNET_PQ_make_prepare ("lookup_order_by_fulfillment", + "SELECT" + " order_id" + " FROM merchant_contract_terms" + " WHERE fulfillment_url=$2" + " AND session_id=$3" + " AND merchant_serial=" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)", + 3), /* OLD API: */ @@ -5725,15 +5733,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) " FROM merchant_refunds" " WHERE coin_pub=$1", 1), - GNUNET_PQ_make_prepare ("find_session_info", - "SELECT" - " order_id" - " FROM merchant_session_info" - " WHERE" - " fulfillment_url=$1" - " AND session_id=$2" - " AND merchant_pub=$3", - 2), GNUNET_PQ_make_prepare ("find_refunds_from_contract_terms_hash", "SELECT" " coin_pub" @@ -6023,7 +6022,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) plugin->refund_coin = &postgres_refund_coin; plugin->lookup_order_status = &postgres_lookup_order_status; plugin->increase_refund = &postgres_increase_refund; - + plugin->lookup_order_by_fulfillment = &postgres_lookup_order_by_fulfillment; /* OLD API: */ plugin->find_contract_terms_from_hash = &postgres_find_contract_terms_from_hash; @@ -6041,8 +6040,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) plugin->lookup_wire_fee = &postgres_lookup_wire_fee; plugin->get_refund_proof = &postgres_get_refund_proof; plugin->put_refund_proof = &postgres_put_refund_proof; - plugin->insert_session_info = &postgres_insert_session_info; - plugin->find_session_info = &postgres_find_session_info; plugin->enable_tip_reserve_TR = &postgres_enable_tip_reserve_TR; plugin->authorize_tip_TR = &postgres_authorize_tip_TR; plugin->lookup_tip_by_id = &postgres_lookup_tip_by_id; diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index cefc3732..eb4b272d 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -1197,25 +1197,6 @@ struct TALER_MERCHANTDB_Plugin /** - * Store the order ID that was used to pay for a resource within a session. - * - * @param cls closure - * @param session_id session id - * @param fulfillment_url URL that canonically identifies the resource - * being paid for - * @param order_id the order ID that was used when paying for the resource URL - * @param merchant_pub public key of the merchant, identifying the instance - * @return transaction status - */ - enum GNUNET_DB_QueryStatus - (*insert_session_info)(void *cls, - const char *session_id, - const char *fulfillment_url, - const char *order_id, - const struct TALER_MerchantPublicKeyP *merchant_pub); - - - /** * Retrieve proposal data given its hashcode * * @param cls closure |