merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit b7c3585b77bd3f04f03568e72a2642ea43143d80
parent ee32930916d3d3c947ec7d3cf94acd01afb3921b
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 26 Dec 2017 10:15:15 +0100

first refactoring for #5158: allow multiple exchange URLs to be in database per /pay operation, plus other minor clean ups

Diffstat:
Msrc/backend/taler-merchant-httpd.c | 27+++++++++++++++++++++++----
Msrc/backend/taler-merchant-httpd_pay.c | 131+++++++++++++++++++++++++++++++------------------------------------------------
Msrc/backend/taler-merchant-httpd_track-transaction.c | 266++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/backend/taler-merchant-httpd_track-transfer.c | 2++
Msrc/backenddb/plugin_merchantdb_postgres.c | 137+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/backenddb/test_merchantdb.c | 103+++++++++++++++++++++++++++++++++----------------------------------------------
Msrc/include/taler_merchant_service.h | 4++++
Msrc/include/taler_merchantdb_plugin.h | 36++++++++++++++++++++----------------
8 files changed, 371 insertions(+), 335 deletions(-)

diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c @@ -404,6 +404,12 @@ prepare_daemon (void); /** + * Set if we should immediately #MHD_run again. + */ +static int triggered; + + +/** * Call MHD to process pending requests and then go back * and schedule the next run. * @@ -413,7 +419,10 @@ static void run_daemon (void *cls) { mhd_task = NULL; - GNUNET_assert (MHD_YES == MHD_run (mhd)); + do { + triggered = 0; + GNUNET_assert (MHD_YES == MHD_run (mhd)); + } while (0 != triggered); mhd_task = prepare_daemon (); } @@ -427,8 +436,16 @@ run_daemon (void *cls) void TMH_trigger_daemon () { - GNUNET_SCHEDULER_cancel (mhd_task); - run_daemon (NULL); + if (NULL != mhd_task) + { + GNUNET_SCHEDULER_cancel (mhd_task); + mhd_task = NULL; + run_daemon (NULL); + } + else + { + triggered = 1; + } } @@ -802,6 +819,7 @@ iterate_instances (const struct GNUNET_CONFIGURATION_Handle *config, return GNUNET_SYSERR; } + /** * Main function that will be run by the scheduler. * @@ -1217,7 +1235,8 @@ run (void *cls, * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) +main (int argc, + char *const *argv) { struct GNUNET_GETOPT_CommandLineOption options[] = { diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c @@ -520,6 +520,7 @@ deposit_cb (void *cls, &pc->h_contract_terms, &pc->mi->pubkey, &dc->coin_pub, + pc->chosen_exchange, &dc->amount_with_fee, &dc->deposit_fee, &dc->refund_fee, @@ -642,52 +643,6 @@ pay_context_cleanup (struct TM_HandlerContext *hc) /** - * Check if the existing transaction matches our transaction. - * Update `transaction_exists` accordingly. - * - * @param cls closure with the `struct PayContext` - * @param merchant_pub merchant's public key - * @param exchange_uri URI of the exchange - * @param h_contract_terms hashed proposal data - * @param h_xwire hash of our wire details - * @param timestamp time of the confirmation - * @param refund refund deadline - * @param total_amount total amount we receive for the contract after fees - */ -static void -check_transaction_exists (void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const char *exchange_uri, - const struct GNUNET_HashCode *h_contract_terms, - const struct GNUNET_HashCode *h_xwire, - struct GNUNET_TIME_Absolute timestamp, - struct GNUNET_TIME_Absolute refund, - const struct TALER_Amount *total_amount) -{ - struct PayContext *pc = cls; - - if ( (0 == memcmp (h_contract_terms, - &pc->h_contract_terms, - sizeof (struct GNUNET_HashCode))) && - (0 == memcmp (h_xwire, - &pc->mi->h_wire, - sizeof (struct GNUNET_HashCode))) && - (timestamp.abs_value_us == pc->timestamp.abs_value_us) && - (refund.abs_value_us == pc->refund_deadline.abs_value_us) && - (0 == TALER_amount_cmp (total_amount, - &pc->amount) ) ) - { - pc->transaction_exists = GNUNET_YES; - } - else - { - GNUNET_break_op (0); - pc->transaction_exists = GNUNET_SYSERR; - } -} - - -/** * Function called with the result of our exchange lookup. * * @param cls the `struct PayContext` @@ -953,40 +908,55 @@ process_pay_with_exchange (void *cls, } /* Check if transaction is already known, if not store it. */ - /* FIXME: What if transaction exists, with a failed payment at - a different exchange? */ - qs = db->find_transaction (db->cls, - &pc->h_contract_terms, - &pc->mi->pubkey, - &check_transaction_exists, - pc); - if (0 > qs) { - /* single, read-only SQL statements should never cause - serialization problems */ - 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); - /* FIXME: factor common logic of these calls into a function! */ - resume_pay_with_response (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TMH_RESPONSE_make_json_pack ("{s:I, s:s}", - "code", (json_int_t) TALER_EC_PAY_DB_FETCH_TRANSACTION_ERROR, - "hint", "Merchant database error")); - return; - } - if (GNUNET_SYSERR == pc->transaction_exists) - { - GNUNET_break (0); - /* FIXME: factor common logic of these calls into a function! */ - resume_pay_with_response (pc, - MHD_HTTP_BAD_REQUEST, - TMH_RESPONSE_make_json_pack ("{s:I, s:s}", - "code", (json_int_t) TALER_EC_PAY_DB_TRANSACTION_ID_CONFLICT, - "hint", "Transaction ID reused with different transaction details")); - return; + struct GNUNET_HashCode h_xwire; + struct GNUNET_TIME_Absolute xtimestamp; + struct GNUNET_TIME_Absolute xrefund; + struct TALER_Amount xtotal_amount; + + qs = db->find_transaction (db->cls, + &pc->h_contract_terms, + &pc->mi->pubkey, + &h_xwire, + &xtimestamp, + &xrefund, + &xtotal_amount); + if (0 > qs) + { + /* single, read-only SQL statements should never cause + serialization problems */ + 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); + /* FIXME: factor common logic of these calls into a function! */ + resume_pay_with_response (pc, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TMH_RESPONSE_make_json_pack ("{s:I, s:s}", + "code", (json_int_t) TALER_EC_PAY_DB_FETCH_TRANSACTION_ERROR, + "hint", "Merchant database error")); + return; + } + if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == pc->transaction_exists) && + ( (0 != memcmp (&h_xwire, + &pc->mi->h_wire, + sizeof (struct GNUNET_HashCode))) || + (xtimestamp.abs_value_us != pc->timestamp.abs_value_us) || + (xrefund.abs_value_us != pc->refund_deadline.abs_value_us) || + (0 != TALER_amount_cmp (&xtotal_amount, + &pc->amount) ) ) ) + { + GNUNET_break (0); + /* FIXME: factor common logic of these calls into a function! */ + resume_pay_with_response (pc, + MHD_HTTP_BAD_REQUEST, + TMH_RESPONSE_make_json_pack ("{s:I, s:s}", + "code", (json_int_t) TALER_EC_PAY_DB_TRANSACTION_ID_CONFLICT, + "hint", "Transaction ID reused with different transaction details")); + return; + } } - if (GNUNET_NO == pc->transaction_exists) + + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == pc->transaction_exists) { struct GNUNET_TIME_Absolute now; enum GNUNET_DB_QueryStatus qs_st; @@ -1016,7 +986,6 @@ process_pay_with_exchange (void *cls, qs_st = db->store_transaction (db->cls, &pc->h_contract_terms, &pc->mi->pubkey, - pc->chosen_exchange, &pc->mi->h_wire, pc->timestamp, pc->refund_deadline, @@ -1061,7 +1030,7 @@ process_pay_with_exchange (void *cls, "hint", "Merchant database error: failed to store transaction")); return; } - } /* end of if (GNUNET_NO == pc->transaction_esists) */ + } /* end of if (GNUNET_NO == pc->transaction_exists) */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found transaction data for proposal `%s' of merchant `%s', initiating deposits\n", @@ -1147,6 +1116,7 @@ handle_pay_timeout (void *cls) * @param cls closure * @param h_contract_terms hashed proposal data * @param coin_pub public key of the coin + * @param exchange_url URL of the exchange that issued @a coin_pub * @param amount_with_fee amount the exchange will deposit for this coin * @param deposit_fee fee the exchange will charge for this coin * @param refund_fee fee the exchange will charge for refunding this coin @@ -1156,6 +1126,7 @@ static void check_coin_paid (void *cls, const struct GNUNET_HashCode *h_contract_terms, const struct TALER_CoinSpendPublicKeyP *coin_pub, + const char *exchange_url, const struct TALER_Amount *amount_with_fee, const struct TALER_Amount *deposit_fee, const struct TALER_Amount *refund_fee, diff --git a/src/backend/taler-merchant-httpd_track-transaction.c b/src/backend/taler-merchant-httpd_track-transaction.c @@ -33,6 +33,41 @@ /** + * Information about a wire transfer for a /track/transaction response. + */ +struct TransactionWireTransfer +{ + + /** + * Wire transfer identifier this struct is about. + */ + struct TALER_WireTransferIdentifierRawP wtid; + + /** + * When was this wire transfer executed? + */ + struct GNUNET_TIME_Absolute execution_time; + + /** + * Number of coins of the selected transaction that + * is covered by this wire transfer. + */ + unsigned int num_coins; + + /** + * Information about the coins of the selected transaction + * that are part of the wire transfer. + */ + struct TALER_MERCHANT_CoinWireTransfer *coins; + + /** + * URL of the exchange that executed the wire transfer. + */ + char *exchange_url; +}; + + +/** * Map containing all the known merchant instances */ extern struct GNUNET_CONTAINER_MultiHashMap *by_id_map; @@ -53,13 +88,11 @@ extern struct GNUNET_CONTAINER_MultiHashMap *by_id_map; * * @param num_transfers how many wire transfers make up the transaction * @param transfers data on each wire transfer - * @param exchange_uri URI of the exchange that made the transfer * @return MHD response object */ static struct MHD_Response * make_track_transaction_ok (unsigned int num_transfers, - const struct TALER_MERCHANT_TransactionWireTransfer *transfers, - const char *exchange_uri) + const struct TransactionWireTransfer *transfers) { struct MHD_Response *ret; json_t *j_transfers; @@ -68,7 +101,7 @@ make_track_transaction_ok (unsigned int num_transfers, j_transfers = json_array (); for (unsigned int i=0;i<num_transfers;i++) { - const struct TALER_MERCHANT_TransactionWireTransfer *transfer = &transfers[i]; + const struct TransactionWireTransfer *transfer = &transfers[i]; sum = transfer->coins[0].amount_with_fee; for (unsigned int j=1;j<transfer->num_coins;j++) @@ -84,7 +117,7 @@ make_track_transaction_ok (unsigned int num_transfers, GNUNET_assert (0 == json_array_append_new (j_transfers, json_pack ("{s:s, s:o, s:o, s:o}", - "exchange", exchange_uri, + "exchange", transfer->exchange_url, "wtid", GNUNET_JSON_from_data_auto (&transfer->wtid), "execution_time", GNUNET_JSON_from_time_abs (transfer->execution_time), "amount", TALER_JSON_from_amount (&sum)))); @@ -121,7 +154,7 @@ struct TrackCoinContext struct TrackCoinContext *prev; /** - * Our Context for a /track/transaction operation. + * Our context for a /track/transaction operation. */ struct TrackTransactionContext *tctx; @@ -131,6 +164,11 @@ struct TrackCoinContext struct TALER_CoinSpendPublicKeyP coin_pub; /** + * Exchange that was used for the transaction. + */ + char *exchange_url; + + /** * Handle for the request to resolve the WTID for this coin. */ struct TALER_EXCHANGE_TrackTransactionHandle *dwh; @@ -190,11 +228,6 @@ struct TrackTransactionContext struct TrackCoinContext *tcc_tail; /** - * Exchange that was used for the transaction. - */ - char *exchange_uri; - - /** * Task run on timeout. */ struct GNUNET_SCHEDULER_Task *timeout_task; @@ -212,6 +245,11 @@ struct TrackTransactionContext struct TALER_EXCHANGE_Handle *eh; /** + * URL of the exchange we currently have in @e eh. + */ + const char *current_exchange; + + /** * Handle we use to resolve transactions for a given WTID. */ struct TALER_EXCHANGE_TrackTransferHandle *wdh; @@ -300,6 +338,11 @@ free_tctx (struct TrackTransactionContext *tctx) TALER_EXCHANGE_track_transaction_cancel (tcc->dwh); tcc->dwh = NULL; } + if (NULL != tcc->exchange_url) + { + GNUNET_free (tcc->exchange_url); + tcc->exchange_url = NULL; + } GNUNET_free (tcc); } if (NULL != tctx->wdh) @@ -317,11 +360,6 @@ free_tctx (struct TrackTransactionContext *tctx) GNUNET_SCHEDULER_cancel (tctx->timeout_task); tctx->timeout_task = NULL; } - if (NULL != tctx->exchange_uri) - { - GNUNET_free (tctx->exchange_uri); - tctx->exchange_uri = NULL; - } GNUNET_free (tctx); } @@ -435,7 +473,7 @@ wire_deposits_cb (void *cls, for (unsigned int i=0;i<MAX_RETRIES;i++) { qs = db->store_transfer_to_proof (db->cls, - tctx->exchange_uri, + tctx->current_exchange, &tctx->current_wtid, tctx->current_execution_time, exchange_pub, @@ -587,8 +625,9 @@ wtid_cb (void *cls, tctx->current_wtid = *wtid; tctx->current_execution_time = execution_time; pcc.p_ret = NULL; + /* FIXME: change to avoid using callback! */ qs = db->find_proof_by_wtid (db->cls, - tctx->exchange_uri, + tctx->current_exchange, wtid, &proof_cb, &pcc); @@ -630,35 +669,16 @@ wtid_cb (void *cls, /** - * This function is called to trace the wire transfers for - * all of the coins of the transaction of the @a tctx. Once - * we have traced all coins, we build the response. + * We have obtained all WTIDs, now prepare the response * - * @param tctx track context with established connection to exchange + * @param tctx handle for the operation */ static void -trace_coins (struct TrackTransactionContext *tctx) +generate_response (struct TrackTransactionContext *tctx) { struct TrackCoinContext *tcc; unsigned int num_wtid; - GNUNET_assert (NULL != tctx->eh); - for (tcc = tctx->tcc_head; NULL != tcc; tcc = tcc->next) - if (GNUNET_YES != tcc->have_wtid) - break; - if (NULL != tcc) - { - /* we are not done requesting WTIDs, do the next one */ - tcc->dwh = TALER_EXCHANGE_track_transaction (tctx->eh, - &tctx->mi->privkey, - &tctx->h_wire, - &tctx->h_contract_terms, - &tcc->coin_pub, - &wtid_cb, - tcc); - return; - } - /* We have obtained all WTIDs, now prepare the response */ num_wtid = 0; /* count how many disjoint wire transfer identifiers there are; note that there should only usually be one, so while this @@ -687,7 +707,7 @@ trace_coins (struct TrackTransactionContext *tctx) /* on-stack allocation is fine, as the number of coins and the number of wire-transfers per-transaction is expected to be tiny. */ struct MHD_Response *resp; - struct TALER_MERCHANT_TransactionWireTransfer wts[num_wtid]; + struct TransactionWireTransfer wts[num_wtid]; unsigned int wtid_off; wtid_off = 0; @@ -710,10 +730,11 @@ trace_coins (struct TrackTransactionContext *tctx) if (GNUNET_NO == found) { unsigned int num_coins; - struct TALER_MERCHANT_TransactionWireTransfer *wt; + struct TransactionWireTransfer *wt; wt = &wts[wtid_off++]; wt->wtid = tcc->wtid; + wt->exchange_url = tcc->exchange_url; wt->execution_time = tcc->execution_time; /* count number of coins with this wtid */ num_coins = 0; @@ -751,8 +772,7 @@ trace_coins (struct TrackTransactionContext *tctx) GNUNET_assert (wtid_off == num_wtid); resp = make_track_transaction_ok (num_wtid, - wts, - tctx->exchange_uri); + wts); for (wtid_off=0;wtid_off < num_wtid; wtid_off++) GNUNET_free (wts[wtid_off].coins); resume_track_transaction_with_response (tctx, @@ -763,6 +783,59 @@ trace_coins (struct TrackTransactionContext *tctx) /** + * Find the exchange to trace the next coin(s). + * + * @param tctx operation context + */ +static void +find_exchange (struct TrackTransactionContext *tctx); + + +/** + * This function is called to trace the wire transfers for + * all of the coins of the transaction of the @a tctx. Once + * we have traced all coins, we build the response. + * + * @param tctx track context with established connection to exchange + */ +static void +trace_coins (struct TrackTransactionContext *tctx) +{ + struct TrackCoinContext *tcc; + + GNUNET_assert (NULL != tctx->eh); + for (tcc = tctx->tcc_head; NULL != tcc; tcc = tcc->next) + if (GNUNET_YES != tcc->have_wtid) + break; + if (NULL != tcc) + { + if (0 != strcmp (tcc->exchange_url, + tctx->current_exchange)) + { + /* exchange changed, find matching one first! */ + tctx->eh = NULL; + tctx->current_exchange = NULL; + find_exchange (tctx); + return; + } + /* we are not done requesting WTIDs from the current + exchange; do the next one */ + tcc->dwh = TALER_EXCHANGE_track_transaction (tctx->eh, + &tctx->mi->privkey, + &tctx->h_wire, + &tctx->h_contract_terms, + &tcc->coin_pub, + &wtid_cb, + tcc); + return; + } + tctx->current_exchange = NULL; + tctx->eh = NULL; + generate_response (tctx); +} + + +/** * Function called with the result of our exchange lookup. * * @param cls the `struct TrackTransactionContext` @@ -811,42 +884,6 @@ handle_track_transaction_timeout (void *cls) /** - * Function called with information about a transaction. - * Responsible to fill up the "context" for the whole - * tracking operation. - * - * @param cls closure - * @param transaction_id of the contract - * @param merchant's public key - * @param exchange_uri URI of the exchange - * @param h_contract hash of the contract - * @param h_wire hash of our wire details - * @param timestamp time of the confirmation - * @param refund refund deadline - * @param total_amount total amount we receive for the contract after fees - */ -static void -transaction_cb (void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const char *exchange_uri, - const struct GNUNET_HashCode *h_contract_terms, - const struct GNUNET_HashCode *h_wire, - struct GNUNET_TIME_Absolute timestamp, - struct GNUNET_TIME_Absolute refund, - const struct TALER_Amount *total_amount) -{ - struct TrackTransactionContext *tctx = cls; - - tctx->h_contract_terms = *h_contract_terms; - tctx->exchange_uri = GNUNET_strdup (exchange_uri); - tctx->h_wire = *h_wire; - tctx->timestamp = timestamp; - tctx->refund_deadline = refund; - tctx->total_amount = *total_amount; -} - - -/** * Information about the wire transfer corresponding to * a deposit operation. Note that it is in theory possible * that we have a @a transaction_id and @a coin_pub in the @@ -865,7 +902,7 @@ transaction_cb (void *cls, */ static void transfer_cb (void *cls, - const struct GNUNET_HashCode *h_contract_terms, + const struct GNUNET_HashCode *h_contract_terms, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute execution_time, @@ -889,6 +926,7 @@ transfer_cb (void *cls, * @param cls closure * @param transaction_id of the contract * @param coin_pub public key of the coin + * @param exchange_url URL of exchange that issued @a coin_pub * @param amount_with_fee amount the exchange will deposit for this coin * @param deposit_fee fee the exchange will charge for this coin * @param refund_fee fee the exchange will charge for refunding this coin @@ -898,6 +936,7 @@ static void coin_cb (void *cls, const struct GNUNET_HashCode *h_contract_terms, const struct TALER_CoinSpendPublicKeyP *coin_pub, + const char *exchange_url, const struct TALER_Amount *amount_with_fee, const struct TALER_Amount *deposit_fee, const struct TALER_Amount *refund_fee, @@ -910,6 +949,7 @@ coin_cb (void *cls, tcc = GNUNET_new (struct TrackCoinContext); tcc->tctx = tctx; tcc->coin_pub = *coin_pub; + tcc->exchange_url = GNUNET_strdup (exchange_url); tcc->amount_with_fee = *amount_with_fee; tcc->deposit_fee = *deposit_fee; @@ -929,6 +969,35 @@ coin_cb (void *cls, /** + * Find the exchange to trace the next coin(s). + * + * @param tctx operation context + */ +static void +find_exchange (struct TrackTransactionContext *tctx) +{ + struct TrackCoinContext *tcc = tctx->tcc_head; + + while ( (NULL != tcc) && + (GNUNET_YES == tcc->have_wtid) ) + tcc = tcc->next; + if (NULL != tcc) + { + tctx->current_exchange = tcc->exchange_url; + tctx->fo = TMH_EXCHANGES_find_exchange (tctx->current_exchange, + NULL, + &process_track_transaction_with_exchange, + tctx); + + } + else + { + generate_response (tctx); + } +} + + +/** * Handle a "/track/transaction" request. * * @param rh context of the handler @@ -951,7 +1020,6 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh, int ret; enum GNUNET_DB_QueryStatus qs; struct GNUNET_HashCode h_instance; - struct GNUNET_HashCode h_contract_terms; struct json_t *contract_terms; if (NULL == *connection_cls) @@ -1042,7 +1110,7 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh, "Given order_id doesn't map to any proposal"); if (GNUNET_OK != TALER_JSON_hash (contract_terms, - &h_contract_terms)) + &tctx->h_contract_terms)) { json_decref (contract_terms); return TMH_RESPONSE_reply_internal_error (connection, @@ -1053,14 +1121,15 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to track h_contract_terms '%s'\n", - GNUNET_h2s (&h_contract_terms)); - + GNUNET_h2s (&tctx->h_contract_terms)); qs = db->find_transaction (db->cls, - &h_contract_terms, + &tctx->h_contract_terms, &tctx->mi->pubkey, - &transaction_cb, - tctx); - if (0 > qs) + &tctx->h_wire, + &tctx->timestamp, + &tctx->refund_deadline, + &tctx->total_amount); + if (0 > qs) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); return TMH_RESPONSE_reply_internal_error (connection, @@ -1075,19 +1144,9 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh, TALER_EC_TRACK_TRANSACTION_TRANSACTION_UNKNOWN, "h_contract_terms is unknown"); } - if ( (0 != memcmp (&tctx->h_contract_terms, - &h_contract_terms, - sizeof (struct GNUNET_HashCode))) || - (NULL == tctx->exchange_uri) ) - { - GNUNET_break (0); - return TMH_RESPONSE_reply_internal_error (connection, - TALER_EC_TRACK_TRANSACTION_DB_FETCH_TRANSACTION_ERROR, - "Database error: failed to obtain correct data from database"); - } tctx->qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; qs = db->find_payments (db->cls, - &h_contract_terms, + &tctx->h_contract_terms, &tctx->mi->pubkey, &coin_cb, tctx); @@ -1111,16 +1170,13 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending /track/transaction handling while working with the exchange\n"); MHD_suspend_connection (connection); - tctx->fo = TMH_EXCHANGES_find_exchange (tctx->exchange_uri, - NULL, - &process_track_transaction_with_exchange, - tctx); - tctx->timeout_task = GNUNET_SCHEDULER_add_delayed (TRACK_TIMEOUT, &handle_track_transaction_timeout, tctx); + find_exchange (tctx); return MHD_YES; } + /* end of taler-merchant-httpd_track-transaction.c */ diff --git a/src/backend/taler-merchant-httpd_track-transfer.c b/src/backend/taler-merchant-httpd_track-transfer.c @@ -433,6 +433,7 @@ track_transfer_cleanup (struct TM_HandlerContext *hc) * @param cls closure with our `struct TrackTransferContext *` * @param transaction_id of the contract * @param coin_pub public key of the coin + * @param exchange_url URL of the exchange that issued @a coin_pub * @param amount_with_fee amount the exchange will transfer for this coin * @param deposit_fee fee the exchange will charge for this coin * @param refund_fee fee the exchange will charge for refunding this coin @@ -442,6 +443,7 @@ static void check_transfer (void *cls, const struct GNUNET_HashCode *h_contract_terms, const struct TALER_CoinSpendPublicKeyP *coin_pub, + const char *exchange_url, const struct TALER_Amount *amount_with_fee, const struct TALER_Amount *deposit_fee, const struct TALER_Amount *refund_fee, diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c @@ -107,10 +107,9 @@ postgres_initialize (void *cls) ",PRIMARY KEY (order_id, merchant_pub)" ",UNIQUE (h_contract_terms, merchant_pub)" ");"), - /* Contracts that were paid via some exchange (or attempted to be paid???) */ + /* Contracts that were paid */ GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_transactions (" " h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64)" - ",exchange_uri VARCHAR NOT NULL" ",merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)" ",h_wire BYTEA NOT NULL CHECK (LENGTH(h_wire)=64)" ",timestamp INT8 NOT NULL" @@ -126,6 +125,7 @@ postgres_initialize (void *cls) " h_contract_terms BYTEA NOT NULL" ",merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)" ",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)" + ",exchange_url VARCHAR NOT NULL" ",amount_with_fee_val INT8 NOT NULL" ",amount_with_fee_frac INT4 NOT NULL" ",amount_with_fee_curr VARCHAR(" TALER_CURRENCY_LEN_STR ") NOT NULL" @@ -141,12 +141,12 @@ postgres_initialize (void *cls) ",FOREIGN KEY (h_contract_terms, merchant_pub) REFERENCES merchant_transactions (h_contract_terms, merchant_pub)" ");"), GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_proofs (" - " exchange_uri VARCHAR NOT NULL" + " exchange_url VARCHAR NOT NULL" ",wtid BYTEA CHECK (LENGTH(wtid)=32)" ",execution_time INT8 NOT NULL" ",signkey_pub BYTEA NOT NULL CHECK (LENGTH(signkey_pub)=32)" ",proof BYTEA NOT NULL" - ",PRIMARY KEY (wtid, exchange_uri)" + ",PRIMARY KEY (wtid, exchange_url)" ");"), /* Note that h_contract_terms + coin_pub may actually be unknown to us, e.g. someone else deposits something for us at the exchange. @@ -211,7 +211,7 @@ postgres_initialize (void *cls) GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_tips (" " reserve_priv BYTEA NOT NULL CHECK (LENGTH(reserve_priv)=32)" ",tip_id BYTEA NOT NULL CHECK (LENGTH(tip_id)=64)" - ",exchange_uri VARCHAR NOT NULL" + ",exchange_url VARCHAR NOT NULL" ",justification VARCHAR NOT NULL" ",timestamp INT8 NOT NULL" ",amount_val INT8 NOT NULL" /* overall tip amount */ @@ -237,7 +237,6 @@ postgres_initialize (void *cls) GNUNET_PQ_make_prepare ("insert_transaction", "INSERT INTO merchant_transactions" "(h_contract_terms" - ",exchange_uri" ",merchant_pub" ",h_wire" ",timestamp" @@ -246,13 +245,14 @@ postgres_initialize (void *cls) ",total_amount_frac" ",total_amount_curr" ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9)", - 9), + "($1, $2, $3, $4, $5, $6, $7, $8)", + 8), GNUNET_PQ_make_prepare ("insert_deposit", "INSERT INTO merchant_deposits" "(h_contract_terms" ",merchant_pub" ",coin_pub" + ",exchange_url" ",amount_with_fee_val" ",amount_with_fee_frac" ",amount_with_fee_curr" @@ -264,8 +264,8 @@ postgres_initialize (void *cls) ",refund_fee_curr" ",signkey_pub" ",exchange_proof) VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)", - 14), + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)", + 15), GNUNET_PQ_make_prepare ("insert_transfer", "INSERT INTO merchant_transfers" "(h_contract_terms" @@ -290,7 +290,7 @@ postgres_initialize (void *cls) 10), GNUNET_PQ_make_prepare ("insert_proof", "INSERT INTO merchant_proofs" - "(exchange_uri" + "(exchange_url" ",wtid" ",execution_time" ",signkey_pub" @@ -440,8 +440,7 @@ postgres_initialize (void *cls) 4), GNUNET_PQ_make_prepare ("find_transaction", "SELECT" - " exchange_uri" - ",h_wire" + " h_wire" ",timestamp" ",refund_deadline" ",total_amount_val" @@ -454,6 +453,7 @@ postgres_initialize (void *cls) GNUNET_PQ_make_prepare ("find_deposits", "SELECT" " coin_pub" + ",exchange_url" ",amount_with_fee_val" ",amount_with_fee_frac" ",amount_with_fee_curr" @@ -479,6 +479,7 @@ postgres_initialize (void *cls) ",refund_fee_val" ",refund_fee_frac" ",refund_fee_curr" + ",exchange_url" ",exchange_proof" " FROM merchant_deposits" " WHERE h_contract_terms=$1" @@ -508,6 +509,7 @@ postgres_initialize (void *cls) ",merchant_deposits.refund_fee_val" ",merchant_deposits.refund_fee_frac" ",merchant_deposits.refund_fee_curr" + ",merchant_deposits.exchange_url" ",merchant_deposits.exchange_proof" " FROM merchant_transfers" " JOIN merchant_deposits" @@ -521,7 +523,7 @@ postgres_initialize (void *cls) " proof" " FROM merchant_proofs" " WHERE wtid=$1" - " AND exchange_uri=$2", + " AND exchange_url=$2", 2), GNUNET_PQ_make_prepare ("lookup_tip_reserve_balance", "SELECT" @@ -554,7 +556,7 @@ postgres_initialize (void *cls) "INSERT INTO merchant_tips" "(reserve_priv" ",tip_id" - ",exchange_uri" + ",exchange_url" ",justification" ",timestamp" ",amount_val" @@ -586,7 +588,7 @@ postgres_initialize (void *cls) 2), GNUNET_PQ_make_prepare ("find_tip_by_id", "SELECT" - " exchange_uri" + " exchange_url" ",timestamp" ",amount_val" ",amount_frac" @@ -907,7 +909,7 @@ postgres_mark_proposal_paid (void *cls, * @param h_contract_terms hashcode of the proposal data associated with the * transaction being stored * @param merchant_pub merchant's public key - * @param exchange_uri URI of the exchange + * @param exchange_url URL of the exchange * @param h_wire hash of our wire details * @param timestamp time of the confirmation * @param refund refund deadline @@ -918,7 +920,6 @@ static enum GNUNET_DB_QueryStatus postgres_store_transaction (void *cls, const struct GNUNET_HashCode *h_contract_terms, const struct TALER_MerchantPublicKeyP *merchant_pub, - const char *exchange_uri, const struct GNUNET_HashCode *h_wire, struct GNUNET_TIME_Absolute timestamp, struct GNUNET_TIME_Absolute refund, @@ -927,7 +928,6 @@ postgres_store_transaction (void *cls, struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_string (exchange_uri), GNUNET_PQ_query_param_auto_from_type (merchant_pub), GNUNET_PQ_query_param_auto_from_type (h_wire), GNUNET_PQ_query_param_absolute_time (&timestamp), @@ -966,6 +966,7 @@ postgres_store_deposit (void *cls, const struct GNUNET_HashCode *h_contract_terms, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub, + const char *exchange_url, const struct TALER_Amount *amount_with_fee, const struct TALER_Amount *deposit_fee, const struct TALER_Amount *refund_fee, @@ -977,6 +978,7 @@ postgres_store_deposit (void *cls, GNUNET_PQ_query_param_auto_from_type (h_contract_terms), GNUNET_PQ_query_param_auto_from_type (merchant_pub), GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_string (exchange_url), TALER_PQ_query_param_amount (amount_with_fee), TALER_PQ_query_param_amount (deposit_fee), TALER_PQ_query_param_amount (refund_fee), @@ -1036,7 +1038,7 @@ postgres_store_coin_to_transfer (void *cls, * Insert wire transfer confirmation from the exchange into the database. * * @param cls closure - * @param exchange_uri URI of the exchange + * @param exchange_url URL of the exchange * @param wtid identifier of the wire transfer * @param execution_time when was @a wtid executed * @param signkey_pub public key used by the exchange for @a exchange_proof @@ -1045,7 +1047,7 @@ postgres_store_coin_to_transfer (void *cls, */ static enum GNUNET_DB_QueryStatus postgres_store_transfer_to_proof (void *cls, - const char *exchange_uri, + const char *exchange_url, const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute execution_time, const struct TALER_ExchangePublicKeyP *signkey_pub, @@ -1053,7 +1055,7 @@ postgres_store_transfer_to_proof (void *cls, { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (exchange_uri), + GNUNET_PQ_query_param_string (exchange_url), GNUNET_PQ_query_param_auto_from_type (wtid), GNUNET_PQ_query_param_absolute_time (&execution_time), GNUNET_PQ_query_param_auto_from_type (signkey_pub), @@ -1306,16 +1308,20 @@ postgres_find_contract_terms_by_date (void *cls, * @param cls our plugin handle * @param h_contract_terms value used to perform the lookup * @param merchant_pub merchant's public key - * @param cb function to call with transaction data - * @param cb_cls closure for @a cb + * @param[out] h_wire set to hash of wire details + * @param[out] timestamp set to timestamp + * @param[out] refund_deadline set to refund deadline + * @param[out] total_amount set to total amount * @return transaction status */ static enum GNUNET_DB_QueryStatus postgres_find_transaction (void *cls, const struct GNUNET_HashCode *h_contract_terms, const struct TALER_MerchantPublicKeyP *merchant_pub, - TALER_MERCHANTDB_TransactionCallback cb, - void *cb_cls) + struct GNUNET_HashCode *h_wire, + struct GNUNET_TIME_Absolute *timestamp, + struct GNUNET_TIME_Absolute *refund_deadline, + struct TALER_Amount *total_amount) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -1323,25 +1329,17 @@ postgres_find_transaction (void *cls, GNUNET_PQ_query_param_auto_from_type (merchant_pub), GNUNET_PQ_query_param_end }; - char *exchange_uri; - struct GNUNET_HashCode h_wire; - struct GNUNET_TIME_Absolute timestamp; - struct GNUNET_TIME_Absolute refund_deadline; - struct TALER_Amount total_amount; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("exchange_uri", - &exchange_uri), GNUNET_PQ_result_spec_auto_from_type ("h_wire", - &h_wire), + h_wire), GNUNET_PQ_result_spec_absolute_time ("timestamp", - &timestamp), + timestamp), GNUNET_PQ_result_spec_absolute_time ("refund_deadline", - &refund_deadline), + refund_deadline), TALER_PQ_result_spec_amount ("total_amount", - &total_amount), + total_amount), GNUNET_PQ_result_spec_end }; - enum GNUNET_DB_QueryStatus qs; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finding transaction for h_contract_terms '%s', merchant_pub: '%s'.\n", @@ -1349,23 +1347,10 @@ postgres_find_transaction (void *cls, TALER_B2S (merchant_pub)); check_connection (pg); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "find_transaction", - params, - rs); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) - { - cb (cb_cls, - merchant_pub, - exchange_uri, - h_contract_terms, - &h_wire, - timestamp, - refund_deadline, - &total_amount); - GNUNET_PQ_cleanup_result (rs); - } - return qs; + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "find_transaction", + params, + rs); } @@ -1418,9 +1403,12 @@ find_payments_cb (void *cls, struct TALER_Amount deposit_fee; struct TALER_Amount refund_fee; json_t *exchange_proof; + char *exchange_url; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_auto_from_type ("coin_pub", &coin_pub), + GNUNET_PQ_result_spec_string ("exchange_url", + &exchange_url), TALER_PQ_result_spec_amount ("amount_with_fee", &amount_with_fee), TALER_PQ_result_spec_amount ("deposit_fee", @@ -1445,6 +1433,7 @@ find_payments_cb (void *cls, fpc->cb (fpc->cb_cls, fpc->h_contract_terms, &coin_pub, + exchange_url, &amount_with_fee, &deposit_fee, &refund_fee, @@ -1552,6 +1541,7 @@ find_payments_by_coin_cb (void *cls, struct TALER_Amount amount_with_fee; struct TALER_Amount deposit_fee; struct TALER_Amount refund_fee; + char *exchange_url; json_t *exchange_proof; struct GNUNET_PQ_ResultSpec rs[] = { TALER_PQ_result_spec_amount ("amount_with_fee", @@ -1560,6 +1550,8 @@ find_payments_by_coin_cb (void *cls, &deposit_fee), TALER_PQ_result_spec_amount ("refund_fee", &refund_fee), + GNUNET_PQ_result_spec_string ("exchange_url", + &exchange_url), TALER_PQ_result_spec_json ("exchange_proof", &exchange_proof), GNUNET_PQ_result_spec_end @@ -1578,6 +1570,7 @@ find_payments_by_coin_cb (void *cls, fpc->cb (fpc->cb_cls, fpc->h_contract_terms, fpc->coin_pub, + exchange_url, &amount_with_fee, &deposit_fee, &refund_fee, @@ -1803,6 +1796,7 @@ find_deposits_cb (void *cls, struct TALER_Amount amount_with_fee; struct TALER_Amount deposit_fee; struct TALER_Amount refund_fee; + char *exchange_url; json_t *exchange_proof; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", @@ -1815,6 +1809,8 @@ find_deposits_cb (void *cls, &deposit_fee), TALER_PQ_result_spec_amount ("refund_fee", &refund_fee), + GNUNET_PQ_result_spec_string ("exchange_url", + &exchange_url), TALER_PQ_result_spec_json ("exchange_proof", &exchange_proof), GNUNET_PQ_result_spec_end @@ -1833,6 +1829,7 @@ find_deposits_cb (void *cls, fdc->cb (fdc->cb_cls, &h_contract_terms, &coin_pub, + exchange_url, &amount_with_fee, &deposit_fee, &refund_fee, @@ -2566,7 +2563,7 @@ postgres_increase_refund_for_contract (void *cls, * Lookup proof information about a wire transfer. * * @param cls closure - * @param exchange_uri from which exchange are we looking for proof + * @param exchange_url from which exchange are we looking for proof * @param wtid wire transfer identifier for the search * @param cb function to call with proof data * @param cb_cls closure for @a cb @@ -2574,7 +2571,7 @@ postgres_increase_refund_for_contract (void *cls, */ static enum GNUNET_DB_QueryStatus postgres_find_proof_by_wtid (void *cls, - const char *exchange_uri, + const char *exchange_url, const struct TALER_WireTransferIdentifierRawP *wtid, TALER_MERCHANTDB_ProofCallback cb, void *cb_cls) @@ -2582,7 +2579,7 @@ postgres_find_proof_by_wtid (void *cls, struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (wtid), - GNUNET_PQ_query_param_string (exchange_uri), + GNUNET_PQ_query_param_string (exchange_url), GNUNET_PQ_query_param_end }; json_t *proof; @@ -2781,7 +2778,7 @@ postgres_enable_tip_reserve (void *cls, * @param justification why was the tip approved * @param amount how high is the tip (with fees) * @param reserve_priv which reserve is debited - * @param exchange_uri which exchange manages the tip + * @param exchange_url which exchange manages the tip * @param[out] expiration set to when the tip expires * @param[out] tip_id set to the unique ID for the tip * @return taler error code @@ -2797,7 +2794,7 @@ postgres_authorize_tip (void *cls, const char *justification, const struct TALER_Amount *amount, const struct TALER_ReservePrivateKeyP *reserve_priv, - const char *exchange_uri, + const char *exchange_url, struct GNUNET_TIME_Absolute *expiration, struct GNUNET_HashCode *tip_id) { @@ -2888,7 +2885,7 @@ postgres_authorize_tip (void *cls, struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (reserve_priv), GNUNET_PQ_query_param_auto_from_type (tip_id), - GNUNET_PQ_query_param_string (exchange_uri), + GNUNET_PQ_query_param_string (exchange_url), GNUNET_PQ_query_param_string (justification), GNUNET_PQ_query_param_absolute_time (&now), TALER_PQ_query_param_amount (amount), /* overall amount */ @@ -2922,7 +2919,7 @@ postgres_authorize_tip (void *cls, * * @param cls closure, typically a connection to the d * @param tip_id the unique ID for the tip - * @param[out] exchange_uri set to the URI of the exchange (unless NULL) + * @param[out] exchange_url set to the URL of the exchange (unless NULL) * @param[out] amount set to the authorized amount (unless NULL) * @param[out] timestamp set to the timestamp of the tip authorization (unless NULL) * @return transaction status, usually @@ -2932,11 +2929,11 @@ postgres_authorize_tip (void *cls, static enum GNUNET_DB_QueryStatus postgres_lookup_tip_by_id (void *cls, const struct GNUNET_HashCode *tip_id, - char **exchange_uri, + char **exchange_url, struct TALER_Amount *amount, struct GNUNET_TIME_Absolute *timestamp) { - char *res_exchange_uri; + char *res_exchange_url; struct TALER_Amount res_amount; struct GNUNET_TIME_Absolute res_timestamp; @@ -2946,8 +2943,8 @@ postgres_lookup_tip_by_id (void *cls, GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("exchange_uri", - &res_exchange_uri), + GNUNET_PQ_result_spec_string ("exchange_url", + &res_exchange_url), GNUNET_PQ_result_spec_absolute_time ("timestamp", &res_timestamp), TALER_PQ_result_spec_amount ("amount", @@ -2962,12 +2959,12 @@ postgres_lookup_tip_by_id (void *cls, rs); if (0 >= qs) { - if (NULL != exchange_uri) - *exchange_uri = NULL; + if (NULL != exchange_url) + *exchange_url = NULL; return qs; } - if (NULL != exchange_uri) - *exchange_uri = strdup (res_exchange_uri); + if (NULL != exchange_url) + *exchange_url = strdup (res_exchange_url); if (NULL != amount) *amount = res_amount; if (NULL != timestamp) diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c @@ -14,7 +14,7 @@ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** - * @file merchant/test_merchantdb_postgres.c + * @file merchant/test_merchantdb.c * @brief testcase for merchant's postgres db plugin * @author Marcello Stanisci * @author Christian Grothoff @@ -44,11 +44,11 @@ #define CURRENCY "EUR" /** - * URI we use for the exchange in the database. + * URL we use for the exchange in the database. * Note that an exchange does not actually have * to run at this address. */ -#define EXCHANGE_URI "http://localhost:8888/" +#define EXCHANGE_URL "http://localhost:8888/" /** * Global return value for the test. Initially -1, set to 0 upon @@ -190,47 +190,6 @@ static json_t *contract_terms_future; /** - * Function called with information about a transaction. - * - * @param cls closure - * @param transaction_id of the contract - * @param merchant_pub public key of the merchant - * @param exchange_uri URI of the exchange - * @param h_wire hash of our wire details - * @param timestamp time of the confirmation - * @param refund_deadline refund deadline - * @param total_amount total amount we receive for the contract after fees - */ -static void -transaction_cb (void *cls, - const struct TALER_MerchantPublicKeyP *amerchant_pub, - const char *aexchange_uri, - const struct GNUNET_HashCode *ah_contract_terms, - const struct GNUNET_HashCode *ah_wire, - struct GNUNET_TIME_Absolute atimestamp, - struct GNUNET_TIME_Absolute arefund_deadline, - const struct TALER_Amount *atotal_amount) -{ -#define CHECK(a) do { if (! (a)) { GNUNET_break (0); result = 3; } } while (0) - CHECK (0 == memcmp (amerchant_pub, - &merchant_pub, - sizeof (struct TALER_MerchantPublicKeyP))); - CHECK (0 == memcmp (ah_contract_terms, - &h_contract_terms, - sizeof (struct GNUNET_HashCode))); - CHECK (0 == strcmp (aexchange_uri, - EXCHANGE_URI)); - CHECK (0 == memcmp (ah_wire, - &h_wire, - sizeof (struct GNUNET_HashCode))); - CHECK (atimestamp.abs_value_us == timestamp.abs_value_us); - CHECK (arefund_deadline.abs_value_us == refund_deadline.abs_value_us); - CHECK (0 == TALER_amount_cmp (atotal_amount, - &amount_with_fee)); -} - - -/** * Function called with information about a refund. * * @param cls closure @@ -272,12 +231,16 @@ pd_cb (void *cls, } +#define CHECK(a) do { if (! (a)) { GNUNET_break (0); result = 3; } } while (0) + + /** * Function called with information about a coin that was deposited. * * @param cls closure * @param transaction_id of the contract - * @param coin_pub public key of the coin + * @param acoin_pub public key of the coin + * @param aexchange_url exchange associated with @a acoin_pub in DB * @param aamount_with_fee amount the exchange will deposit for this coin * @param adeposit_fee fee the exchange will charge for this coin * @param adeposit_fee fee the exchange will charge for refunding this coin @@ -287,6 +250,7 @@ static void deposit_cb (void *cls, const struct GNUNET_HashCode *ah_contract_terms, const struct TALER_CoinSpendPublicKeyP *acoin_pub, + const char *aexchange_url, const struct TALER_Amount *aamount_with_fee, const struct TALER_Amount *adeposit_fee, const struct TALER_Amount *arefund_fee, @@ -298,6 +262,8 @@ deposit_cb (void *cls, CHECK (0 == memcmp (acoin_pub, &coin_pub, sizeof (struct TALER_CoinSpendPublicKeyP))); + CHECK (0 == strcmp (aexchange_url, + EXCHANGE_URL)); CHECK (0 == TALER_amount_cmp (aamount_with_fee, &amount_with_fee)); CHECK (0 == TALER_amount_cmp (adeposit_fee, @@ -529,7 +495,7 @@ test_tipping () struct TALER_Amount total; struct TALER_Amount amount; struct TALER_Amount inc; - char *uri; + char *url; RND_BLK (&tip_reserve_priv); if (TALER_EC_TIP_AUTHORIZE_RESERVE_NOT_ENABLED != @@ -641,20 +607,20 @@ test_tipping () if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->lookup_tip_by_id (plugin->cls, &tip_id, - &uri, + &url, NULL, NULL)) { GNUNET_break (0); return GNUNET_SYSERR; } if (0 != strcmp ("http://localhost:8081/", - uri)) + url)) { - GNUNET_free (uri); + GNUNET_free (url); GNUNET_break (0); return GNUNET_SYSERR; } - GNUNET_free (uri); + GNUNET_free (url); if (TALER_EC_NONE != plugin->authorize_tip (plugin->cls, "testing tips more", @@ -935,8 +901,7 @@ run (void *cls) FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->store_transaction (plugin->cls, &h_contract_terms, - &merchant_pub, - EXCHANGE_URI, + &merchant_pub, &h_wire, timestamp, refund_deadline, @@ -946,6 +911,7 @@ run (void *cls) &h_contract_terms, &merchant_pub, &coin_pub, + EXCHANGE_URL, &amount_with_fee, &deposit_fee, &refund_fee, @@ -958,18 +924,35 @@ run (void *cls) &wtid)); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->store_transfer_to_proof (plugin->cls, - EXCHANGE_URI, + EXCHANGE_URL, &wtid, GNUNET_TIME_UNIT_ZERO_ABS, &signkey_pub, transfer_proof)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->find_transaction (plugin->cls, - &h_contract_terms, - &merchant_pub, - &transaction_cb, - NULL)); + { + struct GNUNET_HashCode ah_wire; + struct GNUNET_TIME_Absolute atimestamp; + struct GNUNET_TIME_Absolute arefund_deadline; + struct TALER_Amount atotal_amount; + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->find_transaction (plugin->cls, + &h_contract_terms, + &merchant_pub, + &ah_wire, + &atimestamp, + &arefund_deadline, + &atotal_amount)); + FAILIF (0 != memcmp (&ah_wire, + &h_wire, + sizeof (struct GNUNET_HashCode))); + FAILIF (atimestamp.abs_value_us != timestamp.abs_value_us); + FAILIF (arefund_deadline.abs_value_us != refund_deadline.abs_value_us); + FAILIF (0 != TALER_amount_cmp (&atotal_amount, + &amount_with_fee)); + } + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->find_payments (plugin->cls, &h_contract_terms, @@ -988,7 +971,7 @@ run (void *cls) NULL)); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->find_proof_by_wtid (plugin->cls, - EXCHANGE_URI, + EXCHANGE_URL, &wtid, &proof_cb, NULL)); diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h @@ -606,6 +606,10 @@ struct TALER_MERCHANT_TransactionWireTransfer */ struct TALER_MERCHANT_CoinWireTransfer *coins; + /** + * URL of the exchange that executed the wire transfer. + */ + char *exchange_url; }; diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h @@ -51,7 +51,6 @@ struct TALER_MERCHANTDB_Plugin; * * @param cls closure * @param merchant_pub merchant's public key - * @param exchange_uri URI of the exchange * @param h_contract_terms proposal data's hashcode * @param h_wire hash of our wire details * @param timestamp time of the confirmation @@ -61,7 +60,6 @@ struct TALER_MERCHANTDB_Plugin; typedef void (*TALER_MERCHANTDB_TransactionCallback)(void *cls, const struct TALER_MerchantPublicKeyP *merchant_pub, - const char *exchange_uri, const struct GNUNET_HashCode *h_contract_terms, const struct GNUNET_HashCode *h_wire, struct GNUNET_TIME_Absolute timestamp, @@ -75,6 +73,7 @@ typedef void * @param cls closure * @param h_contract_terms proposal data's hashcode * @param coin_pub public key of the coin + * @param exchange_url URL of the exchange that issued the coin * @param amount_with_fee amount the exchange will deposit for this coin * @param deposit_fee fee the exchange will charge for this coin * @param refund_fee fee the exchange will charge for refunding this coin @@ -85,6 +84,7 @@ typedef void (*TALER_MERCHANTDB_CoinDepositCallback)(void *cls, const struct GNUNET_HashCode *h_contract_terms, const struct TALER_CoinSpendPublicKeyP *coin_pub, + const char *exchange_url, const struct TALER_Amount *amount_with_fee, const struct TALER_Amount *deposit_fee, const struct TALER_Amount *refund_fee, @@ -329,7 +329,6 @@ struct TALER_MERCHANTDB_Plugin * @param cls closure * @param h_contract_terms proposal data's hashcode * @param merchant_pub merchant's public key - * @param exchange_uri URI of the exchange * @param h_wire hash of our wire details * @param timestamp time of the confirmation * @param refund refund deadline @@ -340,7 +339,6 @@ struct TALER_MERCHANTDB_Plugin (*store_transaction) (void *cls, const struct GNUNET_HashCode *h_contract_terms, const struct TALER_MerchantPublicKeyP *merchant_pub, - const char *exchange_uri, const struct GNUNET_HashCode *h_wire, struct GNUNET_TIME_Absolute timestamp, struct GNUNET_TIME_Absolute refund, @@ -354,6 +352,7 @@ struct TALER_MERCHANTDB_Plugin * @param h_contract_terms proposal data's hashcode * @param merchant_pub merchant's public key * @param coin_pub public key of the coin + * @param exchange_url URL of the exchange that issued @a coin_pub * @param amount_with_fee amount the exchange will deposit for this coin * @param deposit_fee fee the exchange will charge for this coin * @param signkey_pub public key used by the exchange for @a exchange_proof @@ -365,6 +364,7 @@ struct TALER_MERCHANTDB_Plugin const struct GNUNET_HashCode *h_contract_terms, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub, + const char *exchange_url, const struct TALER_Amount *amount_with_fee, const struct TALER_Amount *deposit_fee, const struct TALER_Amount *refund_fee, @@ -394,7 +394,7 @@ struct TALER_MERCHANTDB_Plugin * Insert wire transfer confirmation from the exchange into the database. * * @param cls closure - * @param exchange_uri from which exchange did we get the @a exchange_proof + * @param exchange_url from which exchange did we get the @a exchange_proof * @param wtid identifier of the wire transfer * @param execution_time when was @a wtid executed * @param signkey_pub public key used by the exchange for @a exchange_proof @@ -403,7 +403,7 @@ struct TALER_MERCHANTDB_Plugin */ enum GNUNET_DB_QueryStatus (*store_transfer_to_proof) (void *cls, - const char *exchange_uri, + const char *exchange_url, const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute execution_time, const struct TALER_ExchangePublicKeyP *signkey_pub, @@ -458,16 +458,20 @@ struct TALER_MERCHANTDB_Plugin * @param cls our plugin handle * @param h_contract_terms proposal data's hashcode * @param merchant_pub merchant's public key. - * @param cb function to call with transaction data - * @param cb_cls closure for @a cb + * @param[out] h_wire set to hash of wire details + * @param[out] timestamp set to timestamp + * @param[out] refund_deadline set to refund deadline + * @param[out] total_amount set to total amount * @return transaction status */ enum GNUNET_DB_QueryStatus (*find_transaction) (void *cls, const struct GNUNET_HashCode *h_contract_terms, const struct TALER_MerchantPublicKeyP *merchant_pub, - TALER_MERCHANTDB_TransactionCallback cb, - void *cb_cls); + struct GNUNET_HashCode *h_wire, + struct GNUNET_TIME_Absolute *timestamp, + struct GNUNET_TIME_Absolute *refund_deadline, + struct TALER_Amount *total_amount); /** @@ -550,7 +554,7 @@ struct TALER_MERCHANTDB_Plugin * Lookup proof information about a wire transfer. * * @param cls closure - * @param exchange_uri from which exchange are we looking for proof + * @param exchange_url from which exchange are we looking for proof * @param wtid wire transfer identifier for the search * @param cb function to call with proof data * @param cb_cls closure for @a cb @@ -558,7 +562,7 @@ struct TALER_MERCHANTDB_Plugin */ enum GNUNET_DB_QueryStatus (*find_proof_by_wtid) (void *cls, - const char *exchange_uri, + const char *exchange_url, const struct TALER_WireTransferIdentifierRawP *wtid, TALER_MERCHANTDB_ProofCallback cb, void *cb_cls); @@ -663,7 +667,7 @@ struct TALER_MERCHANTDB_Plugin * @param justification why was the tip approved * @param amount how high is the tip (with fees) * @param reserve_priv which reserve is debited - * @param exchange_uri which exchange manages the tip + * @param exchange_url which exchange manages the tip * @param[out] expiration set to when the tip expires * @param[out] tip_id set to the unique ID for the tip * @return transaction status, @@ -679,7 +683,7 @@ struct TALER_MERCHANTDB_Plugin const char *justification, const struct TALER_Amount *amount, const struct TALER_ReservePrivateKeyP *reserve_priv, - const char *exchange_uri, + const char *exchange_url, struct GNUNET_TIME_Absolute *expiration, struct GNUNET_HashCode *tip_id); @@ -689,7 +693,7 @@ struct TALER_MERCHANTDB_Plugin * * @param cls closure, typically a connection to the d * @param tip_id the unique ID for the tip - * @param[out] exchange_uri set to the URI of the exchange (unless NULL) + * @param[out] exchange_url set to the URL of the exchange (unless NULL) * @param[out] amount set to the authorized amount (unless NULL) * @param[out] timestamp set to the timestamp of the tip authorization (unless NULL) * @return transaction status, usually @@ -699,7 +703,7 @@ struct TALER_MERCHANTDB_Plugin enum GNUNET_DB_QueryStatus (*lookup_tip_by_id)(void *cls, const struct GNUNET_HashCode *tip_id, - char **exchange_uri, + char **exchange_url, struct TALER_Amount *amount, struct GNUNET_TIME_Absolute *timestamp);