diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-07-08 21:24:10 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-07-08 21:24:10 +0200 |
commit | 92ac6dd11a35f3c484a54ecb47ef3ca66cf30d0f (patch) | |
tree | 8053e3afe268f0c6998b4be135273a89feb5a66f /src/lib/exchange_api_common.c | |
parent | 8a1402a5d56907a01ca64a6f7a3a82c5591d8007 (diff) |
implement new behavior in exchange httpd and libtalerexchange (for #6416)
Diffstat (limited to 'src/lib/exchange_api_common.c')
-rw-r--r-- | src/lib/exchange_api_common.c | 155 |
1 files changed, 151 insertions, 4 deletions
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c index 17be0d51b..feaef7b3d 100644 --- a/src/lib/exchange_api_common.c +++ b/src/lib/exchange_api_common.c @@ -447,6 +447,7 @@ TALER_EXCHANGE_free_reserve_history ( * @param currency expected currency for the coin * @param coin_pub public key of the coin * @param history history of the coin in json encoding + * @param[out] h_denom_pub set to the hash of the coin's denomination (if available) * @param[out] total how much of the coin has been spent according to @a history * @return #GNUNET_OK if @a history is valid, #GNUNET_SYSERR if not */ @@ -456,6 +457,7 @@ TALER_EXCHANGE_verify_coin_history ( const char *currency, const struct TALER_CoinSpendPublicKeyP *coin_pub, json_t *history, + struct GNUNET_HashCode *h_denom_pub, struct TALER_Amount *total) { size_t len; @@ -558,6 +560,7 @@ TALER_EXCHANGE_verify_coin_history ( GNUNET_break_op (0); return GNUNET_SYSERR; } + *h_denom_pub = dr.h_denom_pub; if (NULL != dk) { /* check that deposit fee matches our expectations from /keys! */ @@ -615,6 +618,7 @@ TALER_EXCHANGE_verify_coin_history ( GNUNET_break_op (0); return GNUNET_SYSERR; } + *h_denom_pub = rm.h_denom_pub; if (NULL != dk) { /* check that melt fee matches our expectations from /keys! */ @@ -703,16 +707,159 @@ TALER_EXCHANGE_verify_coin_history ( else if (0 == strcasecmp (type, "RECOUP")) { - struct TALER_RecoupConfirmationPS pc; + struct TALER_RecoupConfirmationPS pc = { + .purpose.size = htonl (sizeof (pc)), + .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP), + .coin_pub = *coin_pub + }; + struct TALER_RecoupRequestPS rr = { + .purpose.size = htonl (sizeof (pc)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP), + .coin_pub = *coin_pub + }; struct TALER_ExchangePublicKeyP exchange_pub; struct TALER_ExchangeSignatureP exchange_sig; + struct TALER_CoinSpendSignatureP coin_sig; struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_amount_nbo ("amount", + &pc.recoup_amount), GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig), GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub), GNUNET_JSON_spec_fixed_auto ("reserve_pub", &pc.reserve_pub), + GNUNET_JSON_spec_fixed_auto ("coin_sig", + &coin_sig), + GNUNET_JSON_spec_fixed_auto ("coin_blind", + &rr.coin_blind), + GNUNET_JSON_spec_fixed_auto ("h_denom_pub", + &rr.h_denom_pub), + TALER_JSON_spec_absolute_time_nbo ("timestamp", + &pc.timestamp), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (transaction, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + TALER_amount_hton (&pc.recoup_amount, + &amount); + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP, + &pc, + &exchange_sig.eddsa_signature, + &exchange_pub.eddsa_pub)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP, + &rr, + &coin_sig.eddsa_signature, + &coin_pub->eddsa_pub)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + *h_denom_pub = rr.h_denom_pub; + add = GNUNET_YES; + } + else if (0 == strcasecmp (type, + "RECOUP-REFRESH")) + { + struct TALER_RecoupRefreshConfirmationPS pc = { + .purpose.size = htonl (sizeof (pc)), + .purpose.purpose = htonl ( + TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH), + .coin_pub = *coin_pub + }; + struct TALER_RecoupRequestPS rr = { + .purpose.size = htonl (sizeof (pc)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP), + .coin_pub = *coin_pub + }; + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_ExchangeSignatureP exchange_sig; + struct TALER_CoinSpendSignatureP coin_sig; + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_amount_nbo ("amount", + &pc.recoup_amount), + GNUNET_JSON_spec_fixed_auto ("exchange_sig", + &exchange_sig), + GNUNET_JSON_spec_fixed_auto ("exchange_pub", + &exchange_pub), + GNUNET_JSON_spec_fixed_auto ("coin_sig", + &coin_sig), + GNUNET_JSON_spec_fixed_auto ("old_coin_pub", + &pc.old_coin_pub), + GNUNET_JSON_spec_fixed_auto ("coin_blind", + &rr.coin_blind), + GNUNET_JSON_spec_fixed_auto ("h_denom_pub", + &rr.h_denom_pub), + TALER_JSON_spec_absolute_time_nbo ("timestamp", + &pc.timestamp), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (transaction, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + TALER_amount_hton (&pc.recoup_amount, + &amount); + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify ( + TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH, + &pc, + &exchange_sig.eddsa_signature, + &exchange_pub.eddsa_pub)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP, + &rr, + &coin_sig.eddsa_signature, + &coin_pub->eddsa_pub)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + *h_denom_pub = rr.h_denom_pub; + add = GNUNET_YES; + } + else if (0 == strcasecmp (type, + "OLD-COIN-RECOUP")) + { + struct TALER_RecoupRefreshConfirmationPS pc = { + .purpose.size = htonl (sizeof (pc)), + .purpose.purpose = htonl ( + TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH), + .old_coin_pub = *coin_pub + }; + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_ExchangeSignatureP exchange_sig; + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_amount_nbo ("amount", + &pc.recoup_amount), + GNUNET_JSON_spec_fixed_auto ("exchange_sig", + &exchange_sig), + GNUNET_JSON_spec_fixed_auto ("exchange_pub", + &exchange_pub), + GNUNET_JSON_spec_fixed_auto ("coin_pub", + &pc.coin_pub), TALER_JSON_spec_absolute_time_nbo ("timestamp", &pc.timestamp), GNUNET_JSON_spec_end () @@ -726,9 +873,6 @@ TALER_EXCHANGE_verify_coin_history ( GNUNET_break_op (0); return GNUNET_SYSERR; } - pc.purpose.size = htonl (sizeof (pc)); - pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP); - pc.coin_pub = *coin_pub; TALER_amount_hton (&pc.recoup_amount, &amount); if (GNUNET_OK != @@ -749,6 +893,7 @@ TALER_EXCHANGE_verify_coin_history ( GNUNET_assert (GNUNET_SYSERR == add); return GNUNET_SYSERR; } + if (GNUNET_YES == add) { /* This amount should be added to the total */ @@ -779,9 +924,11 @@ TALER_EXCHANGE_verify_coin_history ( GNUNET_break_op (0); return GNUNET_SYSERR; } + } } + /* Finally, subtract 'rtotal' from total to handle the subtractions */ if (0 > TALER_amount_subtract (total, |