diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-06-05 14:10:21 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-06-05 14:10:21 +0200 |
commit | 148de70dd07591d40a5fa123dcbf4c3b1701cab2 (patch) | |
tree | bacdb10e8a731fd4b75e030905a40b8e671837b9 | |
parent | 94d8d6b48e7fdaf7c7caf47a39faa8a33a72915f (diff) | |
download | merchant-148de70dd07591d40a5fa123dcbf4c3b1701cab2.tar.gz merchant-148de70dd07591d40a5fa123dcbf4c3b1701cab2.tar.bz2 merchant-148de70dd07591d40a5fa123dcbf4c3b1701cab2.zip |
more work on tracking, do store exchange_uri with transaction data
-rw-r--r-- | src/backend/taler-merchant-httpd.c | 11 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd.h | 4 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_contract.c | 2 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_pay.c | 3 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_track-transaction.c | 186 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 16 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 4 |
7 files changed, 168 insertions, 58 deletions
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index 5f0a887c..afff8285 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -60,7 +60,7 @@ struct GNUNET_HashCode h_wire; /** * Merchant's private key */ -struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; +struct TALER_MerchantPrivateKeyP privkey; /** * Merchant's public key @@ -276,8 +276,6 @@ do_shutdown (void *cls) } TMH_EXCHANGES_done (); TMH_AUDITORS_done (); - if (NULL != keyfile) - GNUNET_free (privkey); if (NULL != j_wire) { json_decref (j_wire); @@ -491,6 +489,7 @@ run (void *cls, { char *wireformat; int fh; + struct GNUNET_CRYPTO_EddsaPrivateKey *pk; wireformat = NULL; result = GNUNET_SYSERR; @@ -575,15 +574,17 @@ run (void *cls, "Merchant private key `%s' does not exist yet, creating it!\n", keyfile); if (NULL == - (privkey = + (pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile))) { GNUNET_break (0); GNUNET_SCHEDULER_shutdown (); return; } - GNUNET_CRYPTO_eddsa_key_get_public (privkey, + privkey.eddsa_priv = *pk; + GNUNET_CRYPTO_eddsa_key_get_public (pk, &pubkey.eddsa_pub); + GNUNET_free (pk); if (NULL == (db = TALER_MERCHANTDB_plugin_load (config))) { diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h index 4446a7df..7fcfba02 100644 --- a/src/backend/taler-merchant-httpd.h +++ b/src/backend/taler-merchant-httpd.h @@ -162,9 +162,9 @@ extern json_t *j_wire; extern struct GNUNET_HashCode h_wire; /** - * Our private key (for the merchant to sign contracts). + * Our private key, corresponds to #pubkey. */ -extern struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; +extern struct TALER_MerchantPrivateKeyP privkey; /** * Our public key, corresponds to #privkey. diff --git a/src/backend/taler-merchant-httpd_contract.c b/src/backend/taler-merchant-httpd_contract.c index 0278a7f7..969c0c9e 100644 --- a/src/backend/taler-merchant-httpd_contract.c +++ b/src/backend/taler-merchant-httpd_contract.c @@ -213,7 +213,7 @@ MH_handler_contract (struct TMH_RequestHandler *rh, GNUNET_assert (GNUNET_OK == TALER_JSON_hash (jcontract, &contract.h_contract)); - GNUNET_CRYPTO_eddsa_sign (privkey, + GNUNET_CRYPTO_eddsa_sign (&privkey.eddsa_priv, &contract.purpose, &contract_sig); diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c index 50cbe79f..f32d3dbb 100644 --- a/src/backend/taler-merchant-httpd_pay.c +++ b/src/backend/taler-merchant-httpd_pay.c @@ -748,6 +748,7 @@ check_coin_paid (void *cls, * * @param cls closure with the `struct PayContext` * @param transaction_id of the contract + * @param exchange_uri URI of the exchange * @param h_contract hash of the contract * @param h_xwire hash of our wire details * @param timestamp time of the confirmation @@ -757,6 +758,7 @@ check_coin_paid (void *cls, static void check_transaction_exists (void *cls, uint64_t transaction_id, + const char *exchange_uri, const struct GNUNET_HashCode *h_contract, const struct GNUNET_HashCode *h_xwire, struct GNUNET_TIME_Absolute timestamp, @@ -1053,6 +1055,7 @@ MH_handler_pay (struct TMH_RequestHandler *rh, if (GNUNET_OK != db->store_transaction (db->cls, pc->transaction_id, + pc->chosen_exchange, &pc->h_contract, &h_wire, pc->timestamp, diff --git a/src/backend/taler-merchant-httpd_track-transaction.c b/src/backend/taler-merchant-httpd_track-transaction.c index b64e8204..96c677dd 100644 --- a/src/backend/taler-merchant-httpd_track-transaction.c +++ b/src/backend/taler-merchant-httpd_track-transaction.c @@ -40,6 +40,11 @@ extern char *TMH_merchant_currency_string; +/** + * Context for a /track/transaction operation. + */ +struct TrackTransactionContext; + /** * Information we keep for each coin in a /track/transaction operation. @@ -57,6 +62,11 @@ struct TrackCoinContext struct TrackCoinContext *prev; /** + * Our Context for a /track/transaction operation. + */ + struct TrackTransactionContext *tctx; + + /** * Public key of the coin. */ struct TALER_CoinSpendPublicKeyP coin_pub; @@ -66,6 +76,16 @@ struct TrackCoinContext */ struct TALER_EXCHANGE_DepositWtidHandle *dwh; + /** + * Wire transfer identifier for this coin. + */ + struct TALER_WireTransferIdentifierRawP wtid; + + /** + * Have we obtained the WTID for this coin yet? + */ + int have_wtid; + }; @@ -97,6 +117,16 @@ struct TrackTransactionContext struct TrackCoinContext *tcc_tail; /** + * Exchange that was used for the transaction. + */ + char *exchange_uri; + + /** + * Wire transfer identifier we are currently looking up in @e wdh + */ + struct TALER_WireTransferIdentifierRawP current_wtid; + + /** * Transaction this request is about. */ uint64_t transaction_id; @@ -184,6 +214,11 @@ free_tctx (struct TrackTransactionContext *tctx) } GNUNET_free (tcc); } + if (NULL != tctx->wdh) + { + TALER_EXCHANGE_wire_deposits_cancel (tctx->wdh); + tctx->wdh = NULL; + } if (NULL != tctx->fo) { TMH_EXCHANGES_find_exchange_cancel (tctx->fo); @@ -194,6 +229,11 @@ 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); } @@ -222,21 +262,21 @@ track_transaction_cleanup (struct TM_HandlerContext *hc) * @param response response data to send back */ static void -resume_track_transaction_with_response (struct TrackTransactionContext *ttc, +resume_track_transaction_with_response (struct TrackTransactionContext *tctx, unsigned int response_code, struct MHD_Response *response) { - ttc->response_code = response_code; - ttc->response = response; + tctx->response_code = response_code; + tctx->response = response; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Resuming /track/transaction handling as exchange interaction is done (%u)\n", response_code); - if (NULL != ttc->timeout_task) + if (NULL != tctx->timeout_task) { - GNUNET_SCHEDULER_cancel (ttc->timeout_task); - ttc->timeout_task = NULL; + GNUNET_SCHEDULER_cancel (tctx->timeout_task); + tctx->timeout_task = NULL; } - MHD_resume_connection (ttc->connection); + MHD_resume_connection (tctx->connection); TMH_trigger_daemon (); /* we resumed, kick MHD */ } @@ -280,15 +320,58 @@ wire_deposits_cb (void *cls, const struct TALER_WireDepositDetails *details) { struct TrackTransactionContext *tctx = cls; + struct TrackCoinContext *tcc; + unsigned int i; - /* FIXME: store data in database */ - /* FIXME: check which coins of 'tctx' are now covered */ - GNUNET_break (0); + tctx->wdh = NULL; + if (MHD_HTTP_OK != http_status) + { + resume_track_transaction_with_response + (tctx, + MHD_HTTP_FAILED_DEPENDENCY, + TMH_RESPONSE_make_json_pack ("{s:I, s:o}", + "exchange_status", (json_int_t) http_status, + "details", json)); + return; + } + if (GNUNET_OK != + db->store_transfer_to_proof (db->cls, + &tctx->current_wtid, + json)) + { + /* Not good, but not fatal either, log error and continue */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to store transfer-to-proof mapping in DB\n"); + } + for (tcc=tctx->tcc_head;NULL != tcc;tcc=tcc->next) + { + if (GNUNET_YES == tcc->have_wtid) + continue; + for (i=0;i<details_length;i++) + { + if (0 != memcmp (&details[i].coin_pub, + &tcc->coin_pub, + sizeof (struct TALER_CoinSpendPublicKeyP))) + continue; + tcc->wtid = tctx->current_wtid; + tcc->have_wtid = GNUNET_YES; + if (GNUNET_OK != + db->store_coin_to_transfer (db->cls, + tctx->transaction_id, + &tcc->coin_pub, + &tctx->current_wtid)) + { + /* Not good, but not fatal either, log error and continue */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to store coin-to-transfer mapping in DB\n"); + } + } + } + /* Continue traceing (will also handle case that we are done) */ trace_coins (tctx); } - /** * Function called with detailed wire transfer data. * We were trying to find out in which wire transfer one of the @@ -296,7 +379,7 @@ wire_deposits_cb (void *cls, * obtain the inverse: all other coins of that wire transfer, * which is what we prefer to store. * - * @param cls closure + * @param cls closure with a `struct TrackCoinContext` * @param http_status HTTP status code we got, 0 on exchange protocol violation * @param json original json reply (may include signatures, those have then been * validated already) @@ -313,8 +396,11 @@ wtid_cb (void *cls, struct GNUNET_TIME_Absolute execution_time, const struct TALER_Amount *coin_contribution) { - struct TrackTransactionContext *tctx = cls; + struct TrackCoinContext *tcc = cls; + struct TrackTransactionContext *tctx = tcc->tctx; + tcc->dwh = NULL; + tctx->current_wtid = *wtid; tctx->wdh = TALER_EXCHANGE_wire_deposits (tctx->eh, wtid, &wire_deposits_cb, @@ -332,29 +418,30 @@ wtid_cb (void *cls, static void trace_coins (struct TrackTransactionContext *tctx) { - GNUNET_assert (NULL != tctx->eh); + struct TrackCoinContext *tcc; - GNUNET_break (0); -#if ALL_COINS_DONE - if (0) + 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 ALL_COINS_DONE_FIXME generate_response (); resume_track_transaction_with_response (tctx, MHD_HTTP_OK, response); +#endif return; } -#endif -#if FOR_NEXT_COIN_IN_ORDER_ONE_AT_A_TIME_UNTIL_ALL_ARE_DONE - tctx->dwh = TALER_EXCHANGE_deposit_wtid (eh, - merchant_priv, - &tctx->h_wire, - &tctx->h_contract, - &coin_pub, - tctx->transaction_id, - &wtid_cb, - tctx); -#endif + tcc->dwh = TALER_EXCHANGE_deposit_wtid (tctx->eh, + &privkey, + &tctx->h_wire, + &tctx->h_contract, + &tcc->coin_pub, + tctx->transaction_id, + &wtid_cb, + tcc); } @@ -386,18 +473,18 @@ process_track_transaction_with_exchange (void *cls, static void handle_track_transaction_timeout (void *cls) { - struct TrackTransactionContext *ttc = cls; + struct TrackTransactionContext *tctx = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Resuming /track/transaction with error after timeout\n"); - ttc->timeout_task = NULL; + tctx->timeout_task = NULL; - if (NULL != ttc->fo) + if (NULL != tctx->fo) { - TMH_EXCHANGES_find_exchange_cancel (ttc->fo); - ttc->fo = NULL; + TMH_EXCHANGES_find_exchange_cancel (tctx->fo); + tctx->fo = NULL; } - resume_track_transaction_with_response (ttc, + resume_track_transaction_with_response (tctx, MHD_HTTP_SERVICE_UNAVAILABLE, TMH_RESPONSE_make_internal_error ("exchange not reachable")); } @@ -408,6 +495,7 @@ handle_track_transaction_timeout (void *cls) * * @param cls closure * @param transaction_id of the contract + * @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 @@ -417,20 +505,22 @@ handle_track_transaction_timeout (void *cls) static void transaction_cb (void *cls, uint64_t transaction_id, + const char *exchange_uri, const struct GNUNET_HashCode *h_contract, const struct GNUNET_HashCode *h_wire, struct GNUNET_TIME_Absolute timestamp, struct GNUNET_TIME_Absolute refund, const struct TALER_Amount *total_amount) { - struct TrackTransactionContext *ttc = cls; - - ttc->transaction_id = transaction_id; - ttc->h_contract = *h_contract; - ttc->h_wire = *h_wire; - ttc->timestamp = timestamp; - ttc->refund_deadline = refund; - ttc->total_amount = *total_amount; + struct TrackTransactionContext *tctx = cls; + + tctx->transaction_id = transaction_id; + tctx->exchange_uri = GNUNET_strdup (exchange_uri); + tctx->h_contract = *h_contract; + tctx->h_wire = *h_wire; + tctx->timestamp = timestamp; + tctx->refund_deadline = refund; + tctx->total_amount = *total_amount; } @@ -452,13 +542,14 @@ coin_cb (void *cls, const struct TALER_Amount *deposit_fee, const json_t *exchange_proof) { - struct TrackTransactionContext *ttc = cls; + struct TrackTransactionContext *tctx = cls; struct TrackCoinContext *tcc; tcc = GNUNET_new (struct TrackCoinContext); + tcc->tctx = tctx; tcc->coin_pub = *coin_pub; - GNUNET_CONTAINER_DLL_insert (ttc->tcc_head, - ttc->tcc_tail, + GNUNET_CONTAINER_DLL_insert (tctx->tcc_head, + tctx->tcc_tail, tcc); } @@ -545,7 +636,8 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh, "Unknown transaction ID"); } if ( (GNUNET_SYSERR == ret) || - (tctx->transaction_id != (uint64_t) transaction_id) ) + (tctx->transaction_id != (uint64_t) transaction_id) || + (NULL == tctx->exchange_uri) ) { GNUNET_break (0); free_tctx (tctx); @@ -575,7 +667,7 @@ 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 (NULL, /* FIXME: tctx->chosen_exchange */ + tctx->fo = TMH_EXCHANGES_find_exchange (tctx->exchange_uri, &process_track_transaction_with_exchange, tctx); diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 46435790..bfd0c55f 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -156,6 +156,7 @@ postgres_initialize (void *cls) PG_EXEC (pg, "CREATE TABLE IF NOT EXISTS merchant_transactions (" " transaction_id INT8 PRIMARY KEY" + ",exchange_uri VARCHAR NOT NULL" ",h_contract BYTEA NOT NULL CHECK (LENGTH(h_contract)=64)" ",h_wire BYTEA NOT NULL CHECK (LENGTH(h_wire)=64)" ",timestamp INT8 NOT NULL" @@ -203,6 +204,7 @@ postgres_initialize (void *cls) "insert_transaction", "INSERT INTO merchant_transactions" "(transaction_id" + ",exchange_uri" ",h_contract" ",h_wire" ",timestamp" @@ -211,8 +213,8 @@ postgres_initialize (void *cls) ",total_amount_frac" ",total_amount_curr" ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8)", - 8); + "($1, $2, $3, $4, $5, $6, $7, $8, $9)", + 9); PG_PREPARE (pg, "insert_deposit", "INSERT INTO merchant_deposits" @@ -247,7 +249,8 @@ postgres_initialize (void *cls) PG_PREPARE (pg, "find_transaction", "SELECT" - " h_contract" + " exchange_uri" + ",h_contract" ",h_wire" ",timestamp" ",refund_deadline" @@ -309,6 +312,7 @@ postgres_initialize (void *cls) * * @param cls closure * @param transaction_id of the contract + * @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 @@ -319,6 +323,7 @@ postgres_initialize (void *cls) static int postgres_store_transaction (void *cls, uint64_t transaction_id, + const char *exchange_uri, const struct GNUNET_HashCode *h_contract, const struct GNUNET_HashCode *h_wire, struct GNUNET_TIME_Absolute timestamp, @@ -331,6 +336,7 @@ postgres_store_transaction (void *cls, struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&transaction_id), + GNUNET_PQ_query_param_string (exchange_uri), GNUNET_PQ_query_param_auto_from_type (h_contract), GNUNET_PQ_query_param_auto_from_type (h_wire), GNUNET_PQ_query_param_absolute_time (×tamp), @@ -535,12 +541,15 @@ postgres_find_transaction_by_id (void *cls, } { + char *exchange_uri; struct GNUNET_HashCode h_contract; 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_contract", &h_contract), GNUNET_PQ_result_spec_auto_from_type ("h_wire", @@ -565,6 +574,7 @@ postgres_find_transaction_by_id (void *cls, } cb (cb_cls, transaction_id, + exchange_uri, &h_contract, &h_wire, timestamp, diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index 16064448..1b3013dd 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -36,6 +36,7 @@ struct TALER_MERCHANTDB_Plugin; * * @param cls closure * @param transaction_id of the contract + * @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 @@ -45,6 +46,7 @@ struct TALER_MERCHANTDB_Plugin; typedef void (*TALER_MERCHANTDB_TransactionCallback)(void *cls, uint64_t transaction_id, + const char *exchange_uri, const struct GNUNET_HashCode *h_contract, const struct GNUNET_HashCode *h_wire, struct GNUNET_TIME_Absolute timestamp, @@ -136,6 +138,7 @@ struct TALER_MERCHANTDB_Plugin * * @param cls closure * @param transaction_id of the contract + * @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 @@ -146,6 +149,7 @@ struct TALER_MERCHANTDB_Plugin int (*store_transaction) (void *cls, uint64_t transaction_id, + const char *exchange_uri, const struct GNUNET_HashCode *h_contract, const struct GNUNET_HashCode *h_wire, struct GNUNET_TIME_Absolute timestamp, |