diff options
author | Özgür Kesim <oec-taler@kesim.org> | 2023-05-01 14:05:58 +0200 |
---|---|---|
committer | Özgür Kesim <oec-taler@kesim.org> | 2023-05-01 14:05:58 +0200 |
commit | 1a63275d9804762f0bcdc1cd23060c2e9b364fbb (patch) | |
tree | 2ac8d645d80089cb4674c9878c217025c0a984de /src/exchange | |
parent | af3c92f9d5a9e0d674ab2b1d8028268552ab9f5b (diff) | |
download | exchange-1a63275d9804762f0bcdc1cd23060c2e9b364fbb.tar.gz exchange-1a63275d9804762f0bcdc1cd23060c2e9b364fbb.tar.bz2 exchange-1a63275d9804762f0bcdc1cd23060c2e9b364fbb.zip |
WiP: age-withdraw, finished reveal-request, 10/n
- /age-withdraw/$ACH/reveal handler now fully implemented
- for consistency with api: rename of tables from withdraw_age_... to
age_withdraw
Diffstat (limited to 'src/exchange')
-rw-r--r-- | src/exchange/taler-exchange-httpd_age-withdraw_reveal.c | 163 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_metrics.h | 3 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_refreshes_reveal.c | 10 |
3 files changed, 154 insertions, 22 deletions
diff --git a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c index 5cee7277a..931463cbd 100644 --- a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c +++ b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c @@ -22,6 +22,8 @@ #include <gnunet/gnunet_util_lib.h> #include <jansson.h> #include <microhttpd.h> +#include "taler-exchange-httpd_metrics.h" +#include "taler_exchangedb_plugin.h" #include "taler_mhd_lib.h" #include "taler-exchange-httpd_mhd.h" #include "taler-exchange-httpd_age-withdraw_reveal.h" @@ -387,12 +389,10 @@ denomination_is_valid ( struct TEH_DenominationKey *dks, MHD_RESULT *result) { - dks = TEH_keys_denomination_by_hash2 ( - ksh, - denom_h, - connection, - result); - + dks = TEH_keys_denomination_by_hash2 (ksh, + denom_h, + connection, + result); if (NULL == dks) { /* The denomination doesn't exist */ @@ -785,6 +785,43 @@ verify_commitment_and_max_age ( /** + * @brief Send a response for "/age-withdraw/$RCH/reveal" + * + * @param connection The http connection to the client to send the reponse to + * @param num_coins Number of new coins with age restriction for which we reveal data + * @param awrcs array of @a num_coins signatures revealed + * @return a MHD result code + */ +static MHD_RESULT +reply_age_withdraw_reveal_success ( + struct MHD_Connection *connection, + unsigned int num_coins, + const struct TALER_EXCHANGEDB_AgeWithdrawRevealedCoin *awrcs) +{ + json_t *list = json_array (); + GNUNET_assert (NULL != list); + + for (unsigned int index = 0; + index < num_coins; + index++) + { + json_t *obj = GNUNET_JSON_PACK ( + TALER_JSON_pack_blinded_denom_sig ("ev_sig", + &awrcs[index].coin_sig)); + GNUNET_assert (0 == + json_array_append_new (list, + obj)); + } + + return TALER_MHD_REPLY_JSON_PACK ( + connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_array_steal ("ev_sigs", + list)); +} + + +/** * @brief Signs and persists the undisclosed coins * * @param connection HTTP-connection to the client @@ -796,7 +833,7 @@ verify_commitment_and_max_age ( * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ static enum GNUNET_GenericReturnValue -finalize_age_withdraw_and_sign ( +sign_and_finalize_age_withdraw ( struct MHD_Connection *connection, const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, const uint32_t num_coins, @@ -806,7 +843,9 @@ finalize_age_withdraw_and_sign ( { enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR; struct TEH_CoinSignData csds[num_coins]; - struct TALER_BlindedDenominationSignature bss[num_coins]; + struct TALER_BlindedDenominationSignature bds[num_coins]; + struct TALER_EXCHANGEDB_AgeWithdrawRevealedCoin awrcs[num_coins]; + enum GNUNET_DB_QueryStatus qs; for (uint32_t i = 0; i<num_coins; i++) { @@ -814,13 +853,13 @@ finalize_age_withdraw_and_sign ( csds[i].bp = &coin_evs[i]; } - /* First, sign the the blinded coins */ + /* Sign the the blinded coins first */ { enum TALER_ErrorCode ec; ec = TEH_keys_denomination_batch_sign (csds, num_coins, false, - bss); + bds); if (TALER_EC_NONE != ec) { GNUNET_break (0); @@ -831,12 +870,104 @@ finalize_age_withdraw_and_sign ( } } - /* TODO[oec]: - * - in a transaction: save the coins. - * - add signature response - */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Signatures ready, starting DB interaction\n"); + + /* Prepare the data for insertion */ + for (uint32_t i = 0; i<num_coins; i++) + { + TALER_coin_ev_hash (&coin_evs[i], + csds[i].h_denom_pub, + &awrcs[i].h_coin_ev); + awrcs[i].h_denom_pub = *csds[i].h_denom_pub; + awrcs[i].coin_sig = bds[i]; + } + + /* Persist operation result in DB, transactionally */ + for (unsigned int r = 0; r < MAX_TRANSACTION_COMMIT_RETRIES; r++) + { + bool changed = false; + + /* Transaction start */ + if (GNUNET_OK != + TEH_plugin->start (TEH_plugin->cls, + "insert_age_withdraw_reveal batch")) + { + GNUNET_break (0); + ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_START_FAILED, + NULL); + goto cleanup; + } + + qs = TEH_plugin->insert_age_withdraw_reveal (TEH_plugin->cls, + h_commitment, + num_coins, + awrcs); + + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + { + TEH_plugin->rollback (TEH_plugin->cls); + continue; + } + else if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + GNUNET_break (0); + TEH_plugin->rollback (TEH_plugin->cls); + ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "insert_age_withdraw_reveal"); + goto cleanup; + } + + changed = (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); + + /* Commit the transaction */ + qs = TEH_plugin->commit (TEH_plugin->cls); + if (qs >= 0) + { + if (changed) + TEH_METRICS_num_success[TEH_MT_SUCCESS_AGE_WITHDRAW_REVEAL]++; + + break; /* success */ -#pragma message "FIXME[oec]: implement finalize_age_withdraw_and_sign" + } + else if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + GNUNET_break (0); + TEH_plugin->rollback (TEH_plugin->cls); + ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_COMMIT_FAILED, + NULL); + goto cleanup; + } + else + { + TEH_plugin->rollback (TEH_plugin->cls); + } + } /* end of retry */ + + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + { + GNUNET_break (0); + TEH_plugin->rollback (TEH_plugin->cls); + ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_SOFT_FAILURE, + NULL); + goto cleanup; + } + + /* Generate final (positive) response */ + ret = reply_age_withdraw_reveal_success (connection, + num_coins, + awrcs); +cleanup: + // TODO[oec]: handle error cases + // TODO[oec]: cleanup! return ret; } @@ -922,7 +1053,7 @@ TEH_handler_age_withdraw_reveal ( break; /* Finally, sign and persist the coins */ - if (GNUNET_OK != finalize_age_withdraw_and_sign ( + if (GNUNET_OK != sign_and_finalize_age_withdraw ( rc->connection, &actx.commitment.h_commitment, actx.num_coins, diff --git a/src/exchange/taler-exchange-httpd_metrics.h b/src/exchange/taler-exchange-httpd_metrics.h index 8f6804355..318113c1f 100644 --- a/src/exchange/taler-exchange-httpd_metrics.h +++ b/src/exchange/taler-exchange-httpd_metrics.h @@ -61,7 +61,8 @@ enum TEH_MetricTypeSuccess TEH_MT_SUCCESS_BATCH_WITHDRAW = 3, TEH_MT_SUCCESS_MELT = 4, TEH_MT_SUCCESS_REFRESH_REVEAL = 5, - TEH_MT_SUCCESS_COUNT = 6 /* MUST BE LAST! */ + TEH_MT_SUCCESS_AGE_WITHDRAW_REVEAL = 6, + TEH_MT_SUCCESS_COUNT = 7 /* MUST BE LAST! */ }; /** diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c b/src/exchange/taler-exchange-httpd_refreshes_reveal.c index 08a85265c..89bdf2724 100644 --- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c +++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c @@ -773,12 +773,17 @@ clean_age: NULL); goto cleanup; } + for (unsigned int i = 0; i<rctx->num_fresh_coins; i++) + { rrcs[i].coin_sig = bss[i]; + rrcs[i].blinded_planchet = rcds[i].blinded_planchet; + } } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Signatures ready, starting DB interaction\n"); + for (unsigned int r = 0; r<MAX_TRANSACTION_COMMIT_RETRIES; r++) { bool changed; @@ -795,12 +800,7 @@ clean_age: NULL); goto cleanup; } - for (unsigned int i = 0; i<rctx->num_fresh_coins; i++) - { - struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i]; - rrc->blinded_planchet = rcds[i].blinded_planchet; - } qs = TEH_plugin->insert_refresh_reveal ( TEH_plugin->cls, melt_serial_id, |