diff options
author | Marcello Stanisci <marcello.stanisci@inria.fr> | 2017-02-03 18:41:45 +0100 |
---|---|---|
committer | Marcello Stanisci <marcello.stanisci@inria.fr> | 2017-02-03 18:41:45 +0100 |
commit | d9a1d781e072847e51b7fb731c544eeb8bfe5cee (patch) | |
tree | 302a082c8119def67bc2e3349b48df732228469c /src | |
parent | 36d68f9f47240cfb691644ab003122e5e0fa3915 (diff) | |
download | merchant-d9a1d781e072847e51b7fb731c544eeb8bfe5cee.tar.gz merchant-d9a1d781e072847e51b7fb731c544eeb8bfe5cee.tar.bz2 merchant-d9a1d781e072847e51b7fb731c544eeb8bfe5cee.zip |
renaming: proposal logic ported
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/Makefile.am | 3 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd.c | 18 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_pay.c | 10 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_proposal.c | 148 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_proposal.h (renamed from src/backend/taler-merchant-httpd_propose.h) | 35 | ||||
-rw-r--r-- | src/lib/test_merchant_api.c | 77 |
6 files changed, 186 insertions, 105 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index db782fe7..c635ef03 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -23,8 +23,7 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_pay.c taler-merchant-httpd_pay.h \ taler-merchant-httpd_history.c taler-merchant-httpd_history.h \ taler-merchant-httpd_track-transaction.c taler-merchant-httpd_track-transaction.h \ - taler-merchant-httpd_track-transfer.c taler-merchant-httpd_track-transfer.h \ - taler-merchant-httpd_map.c taler-merchant-httpd_map.h + taler-merchant-httpd_track-transfer.c taler-merchant-httpd_track-transfer.h taler_merchant_httpd_LDADD = \ diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index e571ee62..35894fde 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -35,7 +35,7 @@ #include "taler-merchant-httpd_mhd.h" #include "taler-merchant-httpd_auditors.h" #include "taler-merchant-httpd_exchanges.h" -#include "taler-merchant-httpd_propose.h" +#include "taler-merchant-httpd_proposal.h" #include "taler-merchant-httpd_pay.h" #include "taler-merchant-httpd_track-transaction.h" #include "taler-merchant-httpd_track-transfer.h" @@ -164,13 +164,9 @@ url_handler (void *cls, { "/", MHD_HTTP_METHOD_GET, "text/plain", "Hello, I'm a merchant's Taler backend. This HTTP server is not for humans.\n", 0, &TMH_MHD_handler_static_response, MHD_HTTP_OK }, - { "/contract", MHD_HTTP_METHOD_POST, "application/json", + { "/proposal", MHD_HTTP_METHOD_PUT, "application/json", NULL, 0, - &MH_handler_propose, MHD_HTTP_OK }, - { "/contract/propose", NULL, "text/plain", - "Only POST is allowed", 0, - &TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - + &MH_handler_proposal_put, MHD_HTTP_OK }, { "/pay", MHD_HTTP_METHOD_POST, "application/json", NULL, 0, &MH_handler_pay, MHD_HTTP_OK }, @@ -192,9 +188,13 @@ url_handler (void *cls, { "/history", MHD_HTTP_METHOD_GET, "text/plain", "Only GET is allowed", 0, &MH_handler_history, MHD_HTTP_OK}, - { "/contract/lookup", MHD_HTTP_METHOD_GET, "text/plain", + { "/proposal", MHD_HTTP_METHOD_GET, "text/plain", "Only GET is allowed", 0, - &MH_handler_map_out, MHD_HTTP_OK}, + &MH_handler_proposal_lookup, MHD_HTTP_OK}, + { "/proposal", NULL, "text/plain", + "Only GET/PUT are allowed", 0, + &TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, + {NULL, NULL, NULL, NULL, 0, 0 } }; static struct TMH_RequestHandler h404 = diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c index f9810746..17c31c7b 100644 --- a/src/backend/taler-merchant-httpd_pay.c +++ b/src/backend/taler-merchant-httpd_pay.c @@ -941,7 +941,7 @@ MH_handler_pay (struct TMH_RequestHandler *rh, json_t *coin; unsigned int coins_index; struct TALER_MerchantSignatureP merchant_sig; - struct TALER_ContractPS cp; + struct TALER_ProposalDataPS pdps; const char *chosen_exchange; struct GNUNET_JSON_Specification spec[] = { TALER_JSON_spec_amount ("amount", &pc->amount), @@ -988,12 +988,12 @@ MH_handler_pay (struct TMH_RequestHandler *rh, pc->chosen_exchange = GNUNET_strdup (chosen_exchange); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsed JSON for /pay.\n"); - cp.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT); - cp.purpose.size = htonl (sizeof (struct TALER_ContractPS)); - cp.h_contract = pc->h_contract; + pdps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT); + pdps.purpose.size = htonl (sizeof (pdps)); + pdps.h_proposal_data = pc->h_contract; if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_CONTRACT, - &cp.purpose, + &pdps.purpose, &merchant_sig.eddsa_sig, &pc->mi->pubkey.eddsa_pub)) { diff --git a/src/backend/taler-merchant-httpd_proposal.c b/src/backend/taler-merchant-httpd_proposal.c index ed222c97..2a59ae5e 100644 --- a/src/backend/taler-merchant-httpd_proposal.c +++ b/src/backend/taler-merchant-httpd_proposal.c @@ -120,15 +120,11 @@ get_instance (struct json_t *json); /** - * Manage a contract request. In practical terms, it adds the fields - * 'exchanges', 'merchant_pub', and 'H_wire' to the contract 'proposition' - * gotten from the frontend. Finally, it adds (outside of the - * contract) a signature of the (hashed stringification) of the - * contract (and the hashed stringification of this contract as well - * to aid diagnostics) to the final bundle, which is then send back to - * the frontend. + * Generate a proposal, given its order. In practical terms, it adds the + * fields 'exchanges', 'merchant_pub', and 'H_wire' to the order gotten + * from the frontend. Finally, it signs this data, and returns it to the + * frontend. * - * @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 @@ -136,23 +132,24 @@ get_instance (struct json_t *json); * @return MHD result code */ int -MH_handler_propose (struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) +MH_handler_proposal_put (struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + void **connection_cls, + const char *upload_data, + size_t *upload_data_size) { json_t *root; - json_t *jcontract; + json_t *order; int res; struct MerchantInstance *mi; struct TMH_JsonParseContext *ctx; - struct TALER_ContractPS contract; - struct GNUNET_CRYPTO_EddsaSignature contract_sig; + struct TALER_ProposalDataPS pdps; + struct GNUNET_CRYPTO_EddsaSignature merchant_sig; struct TALER_Amount total; struct TALER_Amount max_fee; - uint64_t transaction_id; + const char *transaction_id; + struct GNUNET_HashCode h_tid; json_t *products; json_t *merchant; struct GNUNET_TIME_Absolute timestamp; @@ -161,9 +158,9 @@ MH_handler_propose (struct TMH_RequestHandler *rh, struct GNUNET_JSON_Specification spec[] = { TALER_JSON_spec_amount ("amount", &total), TALER_JSON_spec_amount ("max_fee", &max_fee), - GNUNET_JSON_spec_uint64 ("transaction_id", &transaction_id), + GNUNET_JSON_spec_string ("transaction_id", &transaction_id), /* The following entries we don't actually need, except to check that - the contract is well-formed */ + the order is well-formed */ GNUNET_JSON_spec_json ("products", &products), GNUNET_JSON_spec_json ("merchant", &merchant), GNUNET_JSON_spec_absolute_time ("timestamp", ×tamp), @@ -194,18 +191,18 @@ MH_handler_propose (struct TMH_RequestHandler *rh, if ((GNUNET_NO == res) || (NULL == root)) return MHD_YES; - jcontract = json_object_get (root, - "contract"); - if (NULL == jcontract) + order = json_object_get (root, + "order"); + if (NULL == order) { json_decref (root); return TMH_RESPONSE_reply_arg_missing (connection, TALER_EC_PARAMETER_MISSING, - "contract"); + "order"); } /* extract fields we need to sign separately */ res = TMH_PARSE_json_data (connection, - jcontract, + order, spec); if (GNUNET_NO == res) { @@ -217,7 +214,7 @@ MH_handler_propose (struct TMH_RequestHandler *rh, json_decref (root); return TMH_RESPONSE_reply_internal_error (connection, TALER_EC_NONE, - "Impossible to parse contract"); + "Impossible to parse the order"); } /* check contract is well-formed */ if (GNUNET_OK != check_products (products)) @@ -226,7 +223,7 @@ MH_handler_propose (struct TMH_RequestHandler *rh, json_decref (root); return TMH_RESPONSE_reply_arg_invalid (connection, TALER_EC_PARAMETER_MALFORMED, - "contract:products"); + "order:products"); } mi = get_instance (merchant); @@ -243,39 +240,108 @@ MH_handler_propose (struct TMH_RequestHandler *rh, "Signing contract on behalf of instance '%s'\n", mi->id); /* add fields to the contract that the backend should provide */ - json_object_set (jcontract, + json_object_set (order, "exchanges", trusted_exchanges); - json_object_set (jcontract, + json_object_set (order, "auditors", j_auditors); - json_object_set_new (jcontract, + json_object_set_new (order, "H_wire", GNUNET_JSON_from_data_auto (&mi->h_wire)); - json_object_set_new (jcontract, + json_object_set_new (order, "merchant_pub", GNUNET_JSON_from_data_auto (&mi->pubkey)); - /* create contract signature */ - contract.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT); - contract.purpose.size = htonl (sizeof (contract)); + /* create proposal signature */ + pdps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT); + pdps.purpose.size = htonl (sizeof (pdps)); GNUNET_assert (GNUNET_OK == - TALER_JSON_hash (jcontract, - &contract.h_contract)); + TALER_JSON_hash (order, + &pdps.h_proposal_data)); GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv, - &contract.purpose, - &contract_sig); + &pdps.purpose, + &merchant_sig); + + + GNUNET_CRYPTO_hash (transaction_id, + strlen (transaction_id), + &h_tid); + if (GNUNET_OK != + db->insert_proposal_data (db->cls, + &h_tid, + order)) + return TMH_RESPONSE_reply_internal_error (connection, + TALER_EC_PROPOSAL_STORE_DB_ERROR, + "db error: could not store this proposal's data into db"); + - /* return final response */ res = TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, "{s:O, s:o s:o}", - "contract", jcontract, - "merchant_sig", GNUNET_JSON_from_data_auto (&contract_sig), - "H_contract", GNUNET_JSON_from_data_auto (&contract.h_contract)); + "data", order, + "merchant_sig", GNUNET_JSON_from_data_auto (&merchant_sig), + "hash", GNUNET_JSON_from_data_auto (&pdps.h_proposal_data)); GNUNET_JSON_parse_free (spec); json_decref (root); return res; } +/** + * Manage a GET /proposal request. Query the db and returns the + * proposal's data related to the transaction id given as the URL's + * parameter. + * + * @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 + * @return MHD result code + */ +int +MH_handler_proposal_lookup (struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + void **connection_cls, + const char *upload_data, + size_t *upload_data_size) +{ + const char *transaction_id; + struct GNUNET_HashCode h_tid; + int res; + json_t *proposal_data; + + transaction_id = MHD_lookup_connection_value (connection, + MHD_GET_ARGUMENT_KIND, + "transaction_id"); + if (NULL == transaction_id) + return TMH_RESPONSE_reply_arg_missing (connection, + TALER_EC_PARAMETER_MISSING, + "transaction_id"); + GNUNET_CRYPTO_hash (transaction_id, + strlen (transaction_id), + &h_tid); + + res = db->find_proposal_data (db->cls, + &proposal_data, + &h_tid); + if (GNUNET_NO == res) + return TMH_RESPONSE_reply_not_found (connection, + TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND, + "unknown transaction id"); + + if (GNUNET_SYSERR == res) + return TMH_RESPONSE_reply_internal_error (connection, + TALER_EC_PROPOSAL_LOOKUP_DB_ERROR, + "An error occurred while retrieving proposal data from db"); + + + return TMH_RESPONSE_reply_json (connection, + proposal_data, + MHD_HTTP_OK); + + +} + + /* end of taler-merchant-httpd_contract.c */ diff --git a/src/backend/taler-merchant-httpd_propose.h b/src/backend/taler-merchant-httpd_proposal.h index ad3e1dcd..fe5b319a 100644 --- a/src/backend/taler-merchant-httpd_propose.h +++ b/src/backend/taler-merchant-httpd_proposal.h @@ -24,9 +24,11 @@ #include "taler-merchant-httpd.h" /** - * Manage a contract request + * Generate a proposal, given its order. In practical terms, it adds the + * fields 'exchanges', 'merchant_pub', and 'H_wire' to the order gotten + * from the frontend. Finally, it signs this data, and returns it to the + * frontend. * - * @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 @@ -34,10 +36,29 @@ * @return MHD result code */ int -MH_handler_propose (struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); +MH_handler_proposal_put (struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + void **connection_cls, + const char *upload_data, + size_t *upload_data_size); + +/** + * Manage a GET /proposal request. Query the db and returns the + * proposal's data related to the transaction id given as the URL's + * parameter. + * + * @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 + * @return MHD result code + */ +int +MH_handler_proposal_lookup (struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + void **connection_cls, + const char *upload_data, + size_t *upload_data_size); #endif diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c index 0d9d3b66..0e2ea5c7 100644 --- a/src/lib/test_merchant_api.c +++ b/src/lib/test_merchant_api.c @@ -409,7 +409,7 @@ struct Command * It's dynamically generated because we need different transaction_id * for different merchant instances. */ - char order[OFFER_MAX_SIZE]; + char order[ORDER_MAX_SIZE]; /** * Handle to the active PUT /proposal operation, or NULL. @@ -1497,14 +1497,13 @@ interpreter_run (void *cls) case OC_PROPOSAL_LOOKUP: { - char *transaction_id; - json_error_t error; + const char *transaction_id; GNUNET_assert (NULL != cmd->details.proposal_lookup.proposal_reference); ref = find_command (is, cmd->details.proposal_lookup.proposal_reference); GNUNET_assert (NULL != ref); - transaction_id = json_object_get (ref->details.proposal.proposal, "transaction_id"); + transaction_id = json_string_value (json_object_get (ref->details.proposal.proposal_data, "transaction_id")); GNUNET_assert (NULL != (cmd->details.proposal_lookup.plo = TALER_MERCHANT_proposal_lookup (ctx, @@ -1677,7 +1676,7 @@ interpreter_run (void *cls) json_t *order; json_error_t error; - order = json_loads (cmd->details.contract.order, + order = json_loads (cmd->details.proposal.order, JSON_REJECT_DUPLICATES, &error); if (NULL != instance) @@ -1695,21 +1694,21 @@ interpreter_run (void *cls) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to parse the order `%s' at command #%u: %s at %u\n", - cmd->details.contract.order, + cmd->details.proposal.order, is->ip, error.text, (unsigned int) error.column); fail (is); return; } - cmd->details.contract.po - = TALER_MERCHANT_proposal (ctx, - MERCHANT_URI, - order, - &proposal_cb, - is); + cmd->details.proposal.po + = TALER_MERCHANT_order_put (ctx, + MERCHANT_URI, + order, + &proposal_cb, + is); json_decref (order); - if (NULL == cmd->details.contract.po) + if (NULL == cmd->details.proposal.po) { GNUNET_break (0); fail (is); @@ -1727,7 +1726,6 @@ interpreter_run (void *cls) struct GNUNET_HashCode h_wire; struct TALER_MerchantPublicKeyP merchant_pub; struct TALER_MerchantSignatureP merchant_sig; - struct GNUNET_HashCode h_contract; struct TALER_Amount total_amount; struct TALER_Amount max_fee; const char *error_name; @@ -1737,8 +1735,8 @@ interpreter_run (void *cls) ref = find_command (is, cmd->details.pay.contract_ref); GNUNET_assert (NULL != ref); - merchant_sig = ref->details.contract.merchant_sig; - GNUNET_assert (NULL != ref->details.contract.contract); + merchant_sig = ref->details.proposal.merchant_sig; + GNUNET_assert (NULL != ref->details.proposal.proposal_data); { /* Get information that need to be replied in the deposit permission */ struct GNUNET_JSON_Specification spec[] = { @@ -1754,7 +1752,7 @@ interpreter_run (void *cls) }; if (GNUNET_OK != - GNUNET_JSON_parse (ref->details.contract.contract, + GNUNET_JSON_parse (ref->details.proposal.proposal_data, spec, &error_name, &error_line)) @@ -1771,9 +1769,6 @@ interpreter_run (void *cls) cmd->details.pay.merchant_pub = merchant_pub; } - TALER_JSON_hash (ref->details.contract.contract, - &h_contract); - /* initialize 'pc' (FIXME: to do in a loop later...) */ { memset (&pc, 0, sizeof (pc)); @@ -1820,7 +1815,7 @@ interpreter_run (void *cls) = TALER_MERCHANT_pay_wallet (ctx, MERCHANT_URI, instance, - &h_contract, + &ref->details.proposal.h_proposal_data, transaction_id, &total_amount, &max_fee, @@ -2007,7 +2002,7 @@ do_shutdown (void *cls) "Command %u (%s) did not complete\n", i, cmd->label); - TALER_MERCHANT_map_cancel (cmd->details.proposal_lookup.plo); + TALER_MERCHANT_proposal_lookup_cancel (cmd->details.proposal_lookup.plo); } break; @@ -2059,10 +2054,10 @@ do_shutdown (void *cls) TALER_MERCHANT_proposal_cancel (cmd->details.proposal.po); cmd->details.proposal.po = NULL; } - if (NULL != cmd->details.proposal.proposal) + if (NULL != cmd->details.proposal.proposal_data) { - json_decref (cmd->details.proposal.proposal); - cmd->details.proposal.proposal = NULL; + json_decref (cmd->details.proposal.proposal_data); + cmd->details.proposal.proposal_data = NULL; } break; case OC_PAY: @@ -2244,11 +2239,11 @@ run (void *cls) .expected_response_code = MHD_HTTP_OK, .details.reserve_status.reserve_reference = "create-reserve-1", .details.reserve_status.expected_balance = "EUR:0" }, - /* Create contract */ - { .oc = OC_CONTRACT, - .label = "create-contract-1", + /* Create proposal */ + { .oc = OC_PROPOSAL, + .label = "create-proposal-1", .expected_response_code = MHD_HTTP_OK, - .details.contract.order = "{\ + .details.proposal.order = "{\ \"max_fee\":\ {\"currency\":\"EUR\", \"value\":0, \"fraction\":50000000},\ \"transaction_id\":1,\ @@ -2269,10 +2264,10 @@ run (void *cls) /* Create another contract */ - { .oc = OC_CONTRACT, - .label = "create-contract-2", + { .oc = OC_PROPOSAL, + .label = "create-proposal-2", .expected_response_code = MHD_HTTP_OK, - .details.contract.order = "{\ + .details.proposal.order = "{\ \"max_fee\":\ {\"currency\":\"EUR\", \"value\":0, \"fraction\":50000000},\ \"transaction_id\":2,\ @@ -2319,10 +2314,10 @@ run (void *cls) /* Fetch contract-1 */ { - .oc = OC_MAP_OUT, - .label = "fetch-contract-2", + .oc = OC_PROPOSAL_LOOKUP, + .label = "fetch-proposal-2", .expected_response_code = MHD_HTTP_OK, - .details.map.contract_reference = "create-contract-2" }, + .details.proposal_lookup.proposal_reference = "create-proposal-2" }, /* Check nothing happened on the bank side so far */ { .oc = OC_CHECK_BANK_TRANSFERS_EMPTY, @@ -2455,16 +2450,16 @@ run (void *cls) }, /* Retrieve via /map/out a contract NOT stored previously. */ { - .oc = OC_MAP_OUT, - .label = "fetch-contract-not-found", + .oc = OC_PROPOSAL_LOOKUP, + .label = "fetch-proposal-not-found", .expected_response_code = MHD_HTTP_NOT_FOUND, - .details.map.contract_reference = "create-contract-3" }, + .details.proposal_lookup.proposal_reference = "create-proposal-3" }, /* Create another contract, NOT to be stored. */ - { .oc = OC_CONTRACT, - .label = "create-contract-3", + { .oc = OC_PROPOSAL, + .label = "create-proposal-3", .expected_response_code = MHD_HTTP_OK, - .details.contract.order = "{\ + .details.proposal.order = "{\ \"max_fee\":\ {\"currency\":\"EUR\", \"value\":0, \"fraction\":10000},\ \"transaction_id\":3,\ |