From 44bb2aa309236b4aa8fe2765a7eb030d7dfb4042 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 2 Nov 2017 15:39:00 +0100 Subject: misc bugfixes to get first /tip-pickup test to pass --- src/backend/taler-merchant-httpd_tip-pickup.c | 67 +++++++++++---- src/lib/merchant_api_tip_pickup.c | 15 +++- src/lib/test_merchant_api.c | 118 ++++++++++++++++---------- 3 files changed, 138 insertions(+), 62 deletions(-) diff --git a/src/backend/taler-merchant-httpd_tip-pickup.c b/src/backend/taler-merchant-httpd_tip-pickup.c index ce62e769..3cb73b43 100644 --- a/src/backend/taler-merchant-httpd_tip-pickup.c +++ b/src/backend/taler-merchant-httpd_tip-pickup.c @@ -93,6 +93,11 @@ struct PickupContext */ struct PlanchetDetail *planchets; + /** + * The connection we are processing. + */ + struct MHD_Connection *connection; + /** * Tip ID that was supplied by the client. */ @@ -230,7 +235,9 @@ run_pickup (struct MHD_Connection *connection, &pd->wr.purpose, &reserve_sig.eddsa_signature)); json_array_append_new (sigs, - GNUNET_JSON_from_data_auto (&reserve_sig)); + json_pack ("{s:o}", + "reserve_sig", + GNUNET_JSON_from_data_auto (&reserve_sig))); } return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, @@ -261,11 +268,14 @@ exchange_found_cb (void *cls, struct TALER_Amount total; int ae; + pc->fo = NULL; + MHD_resume_connection (pc->connection); if (NULL == eh) { pc->ec = TALER_EC_TIP_PICKUP_EXCHANGE_DOWN; pc->error_hint = "failed to contact exchange, check URL"; pc->response_code = MHD_HTTP_FAILED_DEPENDENCY; + TMH_trigger_daemon (); return; } keys = TALER_EXCHANGE_get_keys (eh); @@ -274,13 +284,17 @@ exchange_found_cb (void *cls, pc->ec = TALER_EC_TIP_PICKUP_EXCHANGE_LACKED_KEYS; pc->error_hint = "could not obtain denomination keys from exchange, check URL"; pc->response_code = MHD_HTTP_FAILED_DEPENDENCY; + TMH_trigger_daemon (); return; } - + GNUNET_assert (0 != pc->planchets_len); ae = GNUNET_NO; memset (&total, 0, sizeof (total)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Calculating tip amount over %u planchets!\n", + pc->planchets_len); hc = GNUNET_CRYPTO_hash_context_start (); for (unsigned int i=0;iplanchets_len;i++) { @@ -309,7 +323,9 @@ exchange_found_cb (void *cls, TALER_amount_add (&amount_with_fee, &dk->value, &dk->fee_withdraw)) + { ae = GNUNET_YES; + } if (0 == i) { total = amount_with_fee; @@ -320,7 +336,9 @@ exchange_found_cb (void *cls, TALER_amount_add (&total, &total, &amount_with_fee)) + { ae = GNUNET_YES; + } } TALER_amount_hton (&pd->wr.withdraw_fee, &dk->fee_withdraw); @@ -346,35 +364,44 @@ exchange_found_cb (void *cls, * Prepare (and eventually execute) a pickup. Finds the exchange * handle we need for #run_pickup(). * - * @param connection MHD connection for sending the response - * @param tip_id which tip are we picking up * @param pc pickup context * @return #MHD_YES upon success, #MHD_NO if * the connection ought to be dropped */ static int -prepare_pickup (struct MHD_Connection *connection, - struct PickupContext *pc) +prepare_pickup (struct PickupContext *pc) { - enum TALER_ErrorCode ec; + enum GNUNET_DB_QueryStatus qs; - ec = db->lookup_exchange_by_tip (db->cls, + qs = db->lookup_exchange_by_tip (db->cls, &pc->tip_id, &pc->exchange_uri); - if (TALER_EC_NONE != ec) + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { unsigned int response_code; + enum TALER_ErrorCode ec; - switch (ec) + switch (qs) { - case TALER_EC_TIP_PICKUP_TIP_ID_UNKNOWN: + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + ec = TALER_EC_TIP_PICKUP_TIP_ID_UNKNOWN; response_code = MHD_HTTP_NOT_FOUND; break; + case GNUNET_DB_STATUS_SOFT_ERROR: + ec = TALER_EC_TIP_PICKUP_DB_ERROR_SOFT; + response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + break; + case GNUNET_DB_STATUS_HARD_ERROR: + ec = TALER_EC_TIP_PICKUP_DB_ERROR_HARD; + response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + break; default: + GNUNET_break (0); + ec = TALER_EC_INTERNAL_LOGIC_ERROR; response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; break; } - return TMH_RESPONSE_reply_rc (connection, + return TMH_RESPONSE_reply_rc (pc->connection, response_code, ec, "Could not determine exchange URI for the given tip id"); @@ -386,11 +413,12 @@ prepare_pickup (struct MHD_Connection *connection, pc); if (NULL == pc->fo) { - return TMH_RESPONSE_reply_rc (connection, + return TMH_RESPONSE_reply_rc (pc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_INTERNAL_INVARIANT_FAILURE, "consult server logs"); } + MHD_suspend_connection (pc->connection); return MHD_YES; } @@ -466,6 +494,7 @@ MH_handler_tip_pickup (struct TMH_RequestHandler *rh, { pc = GNUNET_new (struct PickupContext); pc->hc.cc = &pickup_cleanup; + pc->connection = connection; *connection_cls = pc; } else @@ -511,6 +540,15 @@ MH_handler_tip_pickup (struct TMH_RequestHandler *rh, TALER_EC_TIP_PICKUP_EXCHANGE_TOO_MANY_PLANCHETS, "limit of 1024 planchets exceeded by request"); } + if (0 == pc->planchets_len) + { + GNUNET_JSON_parse_free (spec); + json_decref (root); + return TMH_RESPONSE_reply_rc (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_PARAMETER_MALFORMED, + "no planchets specified"); + } pc->planchets = GNUNET_new_array (pc->planchets_len, struct PlanchetDetail); for (unsigned int i=0;iplanchets_len;i++) @@ -527,8 +565,7 @@ MH_handler_tip_pickup (struct TMH_RequestHandler *rh, } } pc->tip_id = tip_id; - res = prepare_pickup (connection, - pc); + res = prepare_pickup (pc); GNUNET_JSON_parse_free (spec); json_decref (root); return res; diff --git a/src/lib/merchant_api_tip_pickup.c b/src/lib/merchant_api_tip_pickup.c index ec46c0f9..74bcbe18 100644 --- a/src/lib/merchant_api_tip_pickup.c +++ b/src/lib/merchant_api_tip_pickup.c @@ -224,6 +224,11 @@ TALER_MERCHANT_tip_pickup (struct GNUNET_CURL_Context *ctx, json_t *pa; json_t *tp_obj; + if (0 == num_planchets) + { + GNUNET_break (0); + return NULL; + } pa = json_array (); for (unsigned int i=0;ilabel); fail (is); return; } @@ -1911,7 +1915,11 @@ pickup_cb (void *cls, cmd->details.tip_pickup.tpo = NULL; if (http_status != cmd->expected_response_code) { - GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u/%u to command %s\n", + http_status, + ec, + cmd->label); fail (is); return; } @@ -2590,6 +2598,7 @@ interpreter_run (void *cls) icoin->denom_pub = coin_ref->details.tip_pickup.dks[ci]->key; icoin->denom_sig = coin_ref->details.tip_pickup.sigs[ci]; icoin->denom_value = coin_ref->details.tip_pickup.dks[ci]->value; + break; default: GNUNET_assert (0); } @@ -2904,55 +2913,62 @@ interpreter_run (void *cls) } case OC_TIP_PICKUP: { - unsigned int num_planchets = cmd->details.tip_pickup.num_coins; - struct TALER_PlanchetDetail planchets[num_planchets]; - - ref = find_command (is, - cmd->details.tip_pickup.authorize_ref); - GNUNET_assert (NULL != ref); - GNUNET_assert (OC_TIP_AUTHORIZE == ref->oc); - cmd->details.tip_pickup.psa = GNUNET_new_array (num_planchets, - struct TALER_PlanchetSecretsP); - cmd->details.tip_pickup.dks = GNUNET_new_array (num_planchets, - const struct TALER_EXCHANGE_DenomPublicKey *); - for (unsigned int i=0;idetails.tip_pickup.amounts[num_planchets]; + num_planchets++); + cmd->details.tip_pickup.num_coins = num_planchets; { - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount (cmd->details.tip_pickup.amounts[i], - &amount)); + struct TALER_PlanchetDetail planchets[num_planchets]; - cmd->details.tip_pickup.dks[i] - = find_pk (is->keys, - &amount); - if (NULL == cmd->details.tip_pickup.dks[i]) + ref = find_command (is, + cmd->details.tip_pickup.authorize_ref); + GNUNET_assert (NULL != ref); + GNUNET_assert (OC_TIP_AUTHORIZE == ref->oc); + cmd->details.tip_pickup.psa = GNUNET_new_array (num_planchets, + struct TALER_PlanchetSecretsP); + cmd->details.tip_pickup.dks = GNUNET_new_array (num_planchets, + const struct TALER_EXCHANGE_DenomPublicKey *); + for (unsigned int i=0;idetails.tip_pickup.amounts[i], + &amount)); + + cmd->details.tip_pickup.dks[i] + = find_pk (is->keys, + &amount); + if (NULL == cmd->details.tip_pickup.dks[i]) + { + GNUNET_break (0); + fail (is); + return; + } + if (GNUNET_OK != + TALER_planchet_prepare (&cmd->details.tip_pickup.dks[i]->key, + &cmd->details.tip_pickup.psa[i], + &planchets[i])) + { + GNUNET_break (0); + fail (is); + return; + } } - if (GNUNET_OK != - TALER_planchet_prepare (&cmd->details.tip_pickup.dks[i]->key, - &cmd->details.tip_pickup.psa[i], - &planchets[i])) + if (NULL == (cmd->details.tip_pickup.tpo + = TALER_MERCHANT_tip_pickup + (ctx, + MERCHANT_URI, + &ref->details.tip_authorize.tip_id, + num_planchets, + planchets, + &pickup_cb, + is))) { GNUNET_break (0); fail (is); - return; } } - if (NULL == (cmd->details.tip_pickup.tpo - = TALER_MERCHANT_tip_pickup - (ctx, - MERCHANT_URI, - &ref->details.tip_authorize.tip_id, - num_planchets, - planchets, - &pickup_cb, - is))) - { - GNUNET_break (0); - fail (is); - } break; } default: @@ -3097,6 +3113,10 @@ static void run (void *cls) { struct InterpreterState *is; + static const char *pickup_amounts_1[] = { + "EUR:5", + NULL + }; static struct Command commands[] = { /* Test tipping */ @@ -3115,11 +3135,13 @@ run (void *cls) .expected_response_code = MHD_HTTP_OK, .details.tip_enable.admin_add_incoming_ref = "create-reserve-tip-1", .details.tip_enable.amount = "EUR:5.01" }, + /* Test incrementing active reserve balance */ { .oc = OC_TIP_ENABLE, .label = "enable-tip-2", .expected_response_code = MHD_HTTP_OK, .details.tip_enable.admin_add_incoming_ref = "create-reserve-tip-1", .details.tip_enable.amount = "EUR:5.01" }, + /* Authorize two tips */ { .oc = OC_TIP_AUTHORIZE, .label = "authorize-tip-1", .expected_response_code = MHD_HTTP_OK, @@ -3132,6 +3154,7 @@ run (void *cls) .details.tip_authorize.instance = "tip", .details.tip_authorize.justification = "tip 2", .details.tip_authorize.amount = "EUR:5.01" }, + /* Test authorization failure modes */ { .oc = OC_TIP_AUTHORIZE, .label = "authorize-tip-3-insufficient-funds", .expected_response_code = MHD_HTTP_PRECONDITION_FAILED, @@ -3160,9 +3183,14 @@ run (void *cls) .details.tip_authorize.justification = "tip 6", .details.tip_authorize.amount = "EUR:5.01", .details.tip_authorize.expected_ec = TALER_EC_TIP_AUTHORIZE_RESERVE_NOT_ENABLED }, - - - + /* Withdraw tip */ + { .oc = OC_TIP_PICKUP, + .label = "pickup-tip-1", + .expected_response_code = MHD_HTTP_OK, + .details.tip_pickup.authorize_ref = "authorize-tip-1", + .details.tip_pickup.amounts = pickup_amounts_1 }, + + /* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */ { .oc = OC_ADMIN_ADD_INCOMING, -- cgit v1.2.3