diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/exchange_api_deposit.c | 2 | ||||
-rw-r--r-- | src/lib/exchange_api_payback.c | 100 | ||||
-rw-r--r-- | src/lib/test_auditor_api.c | 6 | ||||
-rw-r--r-- | src/lib/test_exchange_api.c | 9 | ||||
-rw-r--r-- | src/lib/test_exchange_api_revocation.c | 9 | ||||
-rw-r--r-- | src/lib/testing_api_cmd_deposit.c | 20 | ||||
-rw-r--r-- | src/lib/testing_api_cmd_payback.c | 167 | ||||
-rw-r--r-- | src/lib/testing_api_cmd_refresh.c | 11 |
8 files changed, 219 insertions, 105 deletions
diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c index 865e9b0c4..72aefca1b 100644 --- a/src/lib/exchange_api_deposit.c +++ b/src/lib/exchange_api_deposit.c @@ -172,7 +172,7 @@ auditor_cb (void *cls, static int verify_deposit_signature_ok (struct TALER_EXCHANGE_DepositHandle *dh, const json_t *json, - struct TALER_ExchangeSignatureP *exchange_sig, + struct TALER_ExchangeSignatureP *exchange_sig, struct TALER_ExchangePublicKeyP *exchange_pub) { const struct TALER_EXCHANGE_Keys *key_state; diff --git a/src/lib/exchange_api_payback.c b/src/lib/exchange_api_payback.c index a23ad7be5..64dfa3796 100644 --- a/src/lib/exchange_api_payback.c +++ b/src/lib/exchange_api_payback.c @@ -79,6 +79,11 @@ struct TALER_EXCHANGE_PaybackHandle */ struct TALER_CoinSpendPublicKeyP coin_pub; + /** + * #GNUNET_YES if the coin was refreshed + */ + int was_refreshed; + }; @@ -97,12 +102,13 @@ verify_payback_signature_ok (const struct TALER_EXCHANGE_PaybackHandle *ph, const json_t *json) { struct TALER_PaybackConfirmationPS pc; + struct TALER_PaybackRefreshConfirmationPS pr; struct TALER_ExchangePublicKeyP exchange_pub; struct TALER_ExchangeSignatureP exchange_sig; struct TALER_Amount amount; struct GNUNET_TIME_Absolute timestamp; const struct TALER_EXCHANGE_Keys *key_state; - struct GNUNET_JSON_Specification spec[] = { + struct GNUNET_JSON_Specification spec_withdraw[] = { GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig), GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub), TALER_JSON_spec_amount ("amount", &amount), @@ -110,10 +116,18 @@ verify_payback_signature_ok (const struct TALER_EXCHANGE_PaybackHandle *ph, GNUNET_JSON_spec_fixed_auto ("reserve_pub", &pc.reserve_pub), GNUNET_JSON_spec_end() }; + struct GNUNET_JSON_Specification spec_refresh[] = { + GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig), + GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub), + TALER_JSON_spec_amount ("amount", &amount), + GNUNET_JSON_spec_absolute_time ("timestamp", ×tamp), + GNUNET_JSON_spec_fixed_auto ("old_coin_pub", &pr.old_coin_pub), + GNUNET_JSON_spec_end() + }; if (GNUNET_OK != GNUNET_JSON_parse (json, - spec, + ph->was_refreshed ? spec_refresh : spec_withdraw, NULL, NULL)) { GNUNET_break_op (0); @@ -122,32 +136,54 @@ verify_payback_signature_ok (const struct TALER_EXCHANGE_PaybackHandle *ph, key_state = TALER_EXCHANGE_get_keys (ph->exchange); if (GNUNET_OK != TALER_EXCHANGE_test_signing_key (key_state, - &exchange_pub)) + &exchange_pub)) { GNUNET_break_op (0); return GNUNET_SYSERR; } - pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK); - pc.purpose.size = htonl (sizeof (pc)); - pc.timestamp = GNUNET_TIME_absolute_hton (timestamp); - TALER_amount_hton (&pc.payback_amount, - &amount); - pc.coin_pub = ph->coin_pub; - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK, - &pc.purpose, - &exchange_sig.eddsa_signature, - &exchange_pub.eddsa_pub)) + if (ph->was_refreshed) { - GNUNET_break_op (0); - return GNUNET_SYSERR; + pr.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH); + pr.purpose.size = htonl (sizeof (pr)); + pr.timestamp = GNUNET_TIME_absolute_hton (timestamp); + TALER_amount_hton (&pr.payback_amount, + &amount); + pr.coin_pub = ph->coin_pub; + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH, + &pr.purpose, + &exchange_sig.eddsa_signature, + &exchange_pub.eddsa_pub)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + } + else + { + pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK); + pc.purpose.size = htonl (sizeof (pc)); + pc.timestamp = GNUNET_TIME_absolute_hton (timestamp); + TALER_amount_hton (&pc.payback_amount, + &amount); + pc.coin_pub = ph->coin_pub; + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK, + &pc.purpose, + &exchange_sig.eddsa_signature, + &exchange_pub.eddsa_pub)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } } ph->cb (ph->cb_cls, MHD_HTTP_OK, - TALER_EC_NONE, + TALER_EC_NONE, &amount, timestamp, - &pc.reserve_pub, + ph->was_refreshed ? NULL : &pc.reserve_pub, + ph->was_refreshed ? &pr.old_coin_pub : NULL, json); return GNUNET_OK; } @@ -204,16 +240,17 @@ handle_payback_finished (void *cls, history, &total)) { - GNUNET_break_op (0); - response_code = 0; + GNUNET_break_op (0); + response_code = 0; } ph->cb (ph->cb_cls, - response_code, - TALER_JSON_get_error_code (j), - &total, - GNUNET_TIME_UNIT_FOREVER_ABS, - NULL, - j); + response_code, + TALER_JSON_get_error_code (j), + &total, + GNUNET_TIME_UNIT_FOREVER_ABS, + NULL, + NULL, + j); TALER_EXCHANGE_payback_cancel (ph); return; } @@ -245,10 +282,11 @@ handle_payback_finished (void *cls, } ph->cb (ph->cb_cls, response_code, - TALER_JSON_get_error_code (j), + TALER_JSON_get_error_code (j), NULL, GNUNET_TIME_UNIT_FOREVER_ABS, NULL, + NULL, j); TALER_EXCHANGE_payback_cancel (ph); } @@ -263,6 +301,7 @@ handle_payback_finished (void *cls, * @param pk kind of coin to pay back * @param denom_sig signature over the coin by the exchange using @a pk * @param ps secret internals of the original planchet + * @param was_refreshed #GNUNET_YES if the coin in @a ps was refreshed * @param payback_cb the callback to call when the final result for this request is available * @param payback_cb_cls closure for @a payback_cb * @return NULL @@ -274,6 +313,7 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange, const struct TALER_EXCHANGE_DenomPublicKey *pk, const struct TALER_DenominationSignature *denom_sig, const struct TALER_PlanchetSecretsP *ps, + int was_refreshed, TALER_EXCHANGE_PaybackResultCallback payback_cb, void *payback_cb_cls) { @@ -302,12 +342,13 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange, payback_obj = json_pack ("{s:o, s:o," /* denom pub/sig */ " s:o, s:o," /* coin pub/sig */ - " s:o}", /* coin_bks */ + " s:o, s:o}", /* coin_bks */ "denom_pub_hash", GNUNET_JSON_from_data_auto (&h_denom_pub), "denom_sig", GNUNET_JSON_from_rsa_signature (denom_sig->rsa_signature), "coin_pub", GNUNET_JSON_from_data_auto (&pr.coin_pub), "coin_sig", GNUNET_JSON_from_data_auto (&coin_sig), - "coin_blind_key_secret", GNUNET_JSON_from_data_auto (&ps->blinding_key) + "coin_blind_key_secret", GNUNET_JSON_from_data_auto (&ps->blinding_key), + "refreshed", json_boolean (was_refreshed) ); if (NULL == payback_obj) { @@ -323,6 +364,7 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange, ph->cb = payback_cb; ph->cb_cls = payback_cb_cls; ph->url = TEAH_path_to_url (exchange, "/payback"); + ph->was_refreshed = was_refreshed; eh = TEL_curl_easy_get (ph->url); if (GNUNET_OK != TALER_curl_easy_post (&ph->ctx, diff --git a/src/lib/test_auditor_api.c b/src/lib/test_auditor_api.c index 88548e805..6595ea767 100644 --- a/src/lib/test_auditor_api.c +++ b/src/lib/test_auditor_api.c @@ -474,7 +474,8 @@ run (void *cls, TALER_TESTING_cmd_payback ("payback-1", MHD_HTTP_OK, "payback-withdraw-coin-1", - "EUR:5"), + "EUR:5", + NULL), /** * Re-withdraw from this reserve */ @@ -536,7 +537,8 @@ run (void *cls, TALER_TESTING_cmd_payback ("payback-2", MHD_HTTP_OK, "payback-withdraw-coin-2a", - "EUR:0.5"), + "EUR:0.5", + NULL), TALER_TESTING_cmd_end () }; diff --git a/src/lib/test_exchange_api.c b/src/lib/test_exchange_api.c index e317f7a7d..dc868d1d3 100644 --- a/src/lib/test_exchange_api.c +++ b/src/lib/test_exchange_api.c @@ -688,7 +688,8 @@ run (void *cls, TALER_TESTING_cmd_payback ("payback-1", MHD_HTTP_OK, "payback-withdraw-coin-1", - "EUR:5"), + "EUR:5", + NULL), /* Check the money is back with the reserve */ TALER_TESTING_cmd_status ("payback-reserve-status-1", @@ -799,11 +800,13 @@ run (void *cls, TALER_TESTING_cmd_payback ("payback-2", MHD_HTTP_OK, "payback-withdraw-coin-2a", - "EUR:0.5"), + "EUR:0.5", + NULL), TALER_TESTING_cmd_payback ("payback-2b", MHD_HTTP_FORBIDDEN, "payback-withdraw-coin-2a", - "EUR:0.5"), + "EUR:0.5", + NULL), TALER_TESTING_cmd_deposit ("payback-deposit-revoked", diff --git a/src/lib/test_exchange_api_revocation.c b/src/lib/test_exchange_api_revocation.c index e2e3e4b4f..090b38b25 100644 --- a/src/lib/test_exchange_api_revocation.c +++ b/src/lib/test_exchange_api_revocation.c @@ -162,7 +162,8 @@ run (void *cls, TALER_TESTING_cmd_payback ("payback-1", MHD_HTTP_OK, "refresh-reveal-1", - "EUR:5"), + "EUR:5", + "refresh-melt-1"), /** * Melt original coin AGAIN * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */ @@ -189,12 +190,14 @@ run (void *cls, TALER_TESTING_cmd_payback ("payback-2", MHD_HTTP_OK, "refresh-melt-2", - "EUR:5"), + "EUR:5", + "refresh-melt-2"), /* Refund original coin to reserve */ TALER_TESTING_cmd_payback ("payback-3", MHD_HTTP_OK, "withdraw-coin-1", - "EUR:5"), + "EUR:5", + NULL), /* Check the money is back with the reserve */ TALER_TESTING_cmd_status ("payback-reserve-status-1", "create-reserve-1", diff --git a/src/lib/testing_api_cmd_deposit.c b/src/lib/testing_api_cmd_deposit.c index 6fa2310d3..1868e8bd6 100644 --- a/src/lib/testing_api_cmd_deposit.c +++ b/src/lib/testing_api_cmd_deposit.c @@ -449,8 +449,8 @@ deposit_traits (void *cls, if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv (coin_cmd, - ds->coin_index, - &coin_spent_priv)) + ds->coin_index, + &coin_spent_priv)) { GNUNET_break (0); TALER_TESTING_interpreter_fail (ds->is); @@ -461,26 +461,26 @@ deposit_traits (void *cls, /* First two traits are only available if ds->traits is #GNUNET_YES */ TALER_TESTING_make_trait_exchange_pub (0, - &ds->exchange_pub), + &ds->exchange_pub), TALER_TESTING_make_trait_exchange_sig (0, - &ds->exchange_sig), + &ds->exchange_sig), /* These traits are always available */ TALER_TESTING_make_trait_coin_priv (0, - coin_spent_priv), + coin_spent_priv), TALER_TESTING_make_trait_wire_details (0, - ds->wire_details), + ds->wire_details), TALER_TESTING_make_trait_contract_terms (0, - ds->contract_terms), + ds->contract_terms), TALER_TESTING_make_trait_peer_key (0, - &ds->merchant_priv.eddsa_priv), + &ds->merchant_priv.eddsa_priv), TALER_TESTING_make_trait_amount (0, ds->amount), TALER_TESTING_trait_end () }; return TALER_TESTING_get_trait ((ds->traits_ready) - ? traits - : &traits[2], + ? traits + : &traits[2], ret, trait, index); diff --git a/src/lib/testing_api_cmd_payback.c b/src/lib/testing_api_cmd_payback.c index ac4fd6419..9f81c706e 100644 --- a/src/lib/testing_api_cmd_payback.c +++ b/src/lib/testing_api_cmd_payback.c @@ -98,6 +98,13 @@ struct PaybackState * Handle to the ongoing operation. */ struct TALER_EXCHANGE_PaybackHandle *ph; + + /** + * NULL if coin was not refreshed, otherwise reference + * to the melt operation underlying @a coin_reference. + */ + const char *melt_reference; + }; /** @@ -111,8 +118,8 @@ struct PaybackState * @param amount amount the exchange will wire back for this coin. * @param timestamp what time did the exchange receive the * /payback request - * @param reserve_pub public key of the reserve affected by the - * payback. + * @param reserve_pub public key of the reserve receiving the payback, NULL if refreshed or on error + * @param old_coin_pub public key of the dirty coin, NULL if not refreshed or on error * @param full_response raw response from the exchange. */ static void @@ -122,15 +129,13 @@ payback_cb (void *cls, const struct TALER_Amount *amount, struct GNUNET_TIME_Absolute timestamp, const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, const json_t *full_response) { struct PaybackState *ps = cls; struct TALER_TESTING_Interpreter *is = ps->is; struct TALER_TESTING_Command *cmd = &is->commands[is->ip]; const struct TALER_TESTING_Command *reserve_cmd; - const struct TALER_ReservePrivateKeyP *reserve_priv; - struct TALER_ReservePublicKeyP rp; - struct TALER_Amount expected_amount; char *cref; const char *index; unsigned int idx; @@ -150,7 +155,7 @@ payback_cb (void *cls, return; } - /* We allow command referneces of the form "$LABEL#$INDEX" or + /* We allow command references of the form "$LABEL#$INDEX" or just "$LABEL", which implies the index is 0. Figure out which one it is. */ index = strchr (ps->coin_reference, '#'); @@ -189,41 +194,90 @@ payback_cb (void *cls, return; } - if (GNUNET_OK != TALER_TESTING_get_trait_reserve_priv - (reserve_cmd, idx, &reserve_priv)) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (is); - return; - } - - GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, - &rp.eddsa_pub); - switch (http_status) { case MHD_HTTP_OK: - if (GNUNET_OK != TALER_string_to_amount - (ps->amount, &expected_amount)) + /* first, check amount */ { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (is); - return; + struct TALER_Amount expected_amount; + + if (GNUNET_OK != + TALER_string_to_amount (ps->amount, &expected_amount)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (0 != TALER_amount_cmp (amount, &expected_amount)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Total amount missmatch to command %s\n", + cmd->label); + json_dumpf (full_response, stderr, 0); + TALER_TESTING_interpreter_fail (is); + return; + } } - if (0 != TALER_amount_cmp (amount, &expected_amount)) + /* now, check old_coin_pub or reserve_pub, respectively */ + if (NULL != ps->melt_reference) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Total amount missmatch to command %s\n", - cmd->label); - json_dumpf (full_response, stderr, 0); - TALER_TESTING_interpreter_fail (is); - return; + const struct TALER_TESTING_Command *melt_cmd; + const struct TALER_CoinSpendPrivateKeyP *dirty_priv; + struct TALER_CoinSpendPublicKeyP oc; + + melt_cmd = TALER_TESTING_interpreter_lookup_command (is, + ps->melt_reference); + if (NULL == melt_cmd) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (GNUNET_OK != + TALER_TESTING_get_trait_coin_priv (melt_cmd, + 0, + &dirty_priv)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + GNUNET_CRYPTO_eddsa_key_get_public (&dirty_priv->eddsa_priv, + &oc.eddsa_pub); + if (0 != GNUNET_memcmp (&oc, + old_coin_pub)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } } - if (0 != GNUNET_memcmp (reserve_pub, &rp)) + else { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (is); - return; + const struct TALER_ReservePrivateKeyP *reserve_priv; + struct TALER_ReservePublicKeyP rp; + + if (NULL == reserve_priv) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (GNUNET_OK != TALER_TESTING_get_trait_reserve_priv + (reserve_cmd, idx, &reserve_priv)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, + &rp.eddsa_pub); + if (0 != GNUNET_memcmp (reserve_pub, &rp)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } } break; default: @@ -309,6 +363,7 @@ payback_run (void *cls, denom_pub, coin_sig, &planchet, + NULL != ps->melt_reference, payback_cb, ps); GNUNET_assert (NULL != ps->ph); @@ -465,14 +520,15 @@ revoke_run (void *cls, * @param coin_reference reference to any command which * offers a coin & reserve private key. * @param amount denomination to pay back. - * + * @param melt_reference NULL if coin was not refreshed * @return the command. */ struct TALER_TESTING_Command TALER_TESTING_cmd_payback (const char *label, unsigned int expected_response_code, const char *coin_reference, - const char *amount) + const char *amount, + const char *melt_reference) { struct PaybackState *ps; @@ -480,15 +536,17 @@ TALER_TESTING_cmd_payback (const char *label, ps->expected_response_code = expected_response_code; ps->coin_reference = coin_reference; ps->amount = amount; - - struct TALER_TESTING_Command cmd = { - .cls = ps, - .label = label, - .run = &payback_run, - .cleanup = &payback_cleanup - }; - - return cmd; + ps->melt_reference = melt_reference; + { + struct TALER_TESTING_Command cmd = { + .cls = ps, + .label = label, + .run = &payback_run, + .cleanup = &payback_cleanup + }; + + return cmd; + } } @@ -516,14 +574,15 @@ TALER_TESTING_cmd_revoke (const char *label, rs->expected_response_code = expected_response_code; rs->coin_reference = coin_reference; rs->config_filename = config_filename; - - struct TALER_TESTING_Command cmd = { - .cls = rs, - .label = label, - .run = &revoke_run, - .cleanup = &revoke_cleanup, - .traits = &revoke_traits - }; - - return cmd; + { + struct TALER_TESTING_Command cmd = { + .cls = rs, + .label = label, + .run = &revoke_run, + .cleanup = &revoke_cleanup, + .traits = &revoke_traits + }; + + return cmd; + } } diff --git a/src/lib/testing_api_cmd_refresh.c b/src/lib/testing_api_cmd_refresh.c index 2bbf189b6..bc67af7f9 100644 --- a/src/lib/testing_api_cmd_refresh.c +++ b/src/lib/testing_api_cmd_refresh.c @@ -88,6 +88,11 @@ struct RefreshMeltState struct TALER_EXCHANGE_DenomPublicKey *fresh_pks; /** + * Private key of the dirty coin being melted. + */ + const struct TALER_CoinSpendPrivateKeyP *melt_priv; + + /** * Task scheduled to try later. */ struct GNUNET_SCHEDULER_Task *retry_task; @@ -889,7 +894,6 @@ refresh_melt_run (void *cls, (num_fresh_coins, struct TALER_EXCHANGE_DenomPublicKey); { - const struct TALER_CoinSpendPrivateKeyP *melt_priv; struct TALER_Amount melt_amount; struct TALER_Amount fresh_amount; const struct TALER_DenominationSignature *melt_sig; @@ -907,7 +911,7 @@ refresh_melt_run (void *cls, } if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv - (coin_command, 0, &melt_priv)) + (coin_command, 0, &rms->melt_priv)) { GNUNET_break (0); TALER_TESTING_interpreter_fail (rms->is); @@ -969,7 +973,7 @@ refresh_melt_run (void *cls, rms->fresh_pks[i] = *fresh_pk; } rms->refresh_data = TALER_EXCHANGE_refresh_prepare - (melt_priv, &melt_amount, melt_sig, melt_denom_pub, + (rms->melt_priv, &melt_amount, melt_sig, melt_denom_pub, GNUNET_YES, num_fresh_coins, rms->fresh_pks, &rms->refresh_data_length); @@ -1053,6 +1057,7 @@ refresh_melt_traits (void *cls, { struct TALER_TESTING_Trait traits[] = { TALER_TESTING_make_trait_denom_pub (index, &rms->fresh_pks[index]), + TALER_TESTING_make_trait_coin_priv (0, rms->melt_priv), TALER_TESTING_trait_end () }; |