diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-06-19 00:00:21 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-06-19 00:17:16 +0200 |
commit | dea0f7c411d6ae5c5410d30f6072478e905cabb4 (patch) | |
tree | 63fd5490d62d991f47148c5147c51d249d9d61b8 /src/exchange/taler-exchange-httpd_db.c | |
parent | 4cb035cd298139f606562ed88f60ba89dff0febc (diff) | |
download | exchange-dea0f7c411d6ae5c5410d30f6072478e905cabb4.tar.gz exchange-dea0f7c411d6ae5c5410d30f6072478e905cabb4.tar.bz2 exchange-dea0f7c411d6ae5c5410d30f6072478e905cabb4.zip |
fixing #5010 for /reserve/withdraw
Diffstat (limited to 'src/exchange/taler-exchange-httpd_db.c')
-rw-r--r-- | src/exchange/taler-exchange-httpd_db.c | 344 |
1 files changed, 0 insertions, 344 deletions
diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c index 4131e1230..ebe19a9b5 100644 --- a/src/exchange/taler-exchange-httpd_db.c +++ b/src/exchange/taler-exchange-httpd_db.c @@ -553,350 +553,6 @@ TEH_DB_execute_refund (struct MHD_Connection *connection, /** - * Try to execute /reserve/withdraw transaction. - * - * @param connection request we are handling - * @param session database session we are using - * @param key_state key state to lookup denomination pubs - * @param reserve reserve to withdraw from - * @param denomination_pub public key of the denomination requested - * @param dki denomination to withdraw - * @param blinded_msg blinded message to be signed - * @param blinded_msg_len number of bytes in @a blinded_msg - * @param h_blind hash of @a blinded_msg - * @param signature signature over the withdraw request, to be stored in DB - * @param[out] denom_sig where to write the resulting signature - * (used to release memory in case of transaction failure - * @return MHD result code - */ -static int -execute_reserve_withdraw_transaction (struct MHD_Connection *connection, - struct TALER_EXCHANGEDB_Session *session, - struct TEH_KS_StateHandle *key_state, - const struct TALER_ReservePublicKeyP *reserve, - const struct TALER_DenominationPublicKey *denomination_pub, - const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki, - const char *blinded_msg, - size_t blinded_msg_len, - const struct GNUNET_HashCode *h_blind, - const struct TALER_ReserveSignatureP *signature, - struct TALER_DenominationSignature *denom_sig) -{ - struct TALER_EXCHANGEDB_ReserveHistory *rh; - const struct TALER_EXCHANGEDB_ReserveHistory *pos; - struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *tdki; - struct TALER_EXCHANGEDB_CollectableBlindcoin collectable; - struct TALER_Amount amount_required; - struct TALER_Amount deposit_total; - struct TALER_Amount withdraw_total; - struct TALER_Amount balance; - struct TALER_Amount value; - struct TALER_Amount fee_withdraw; - int res; - int ret; - enum GNUNET_DB_QueryStatus qs; - - /* Check if balance is sufficient */ - START_TRANSACTION (session, connection); - qs = TEH_plugin->get_reserve_history (TEH_plugin->cls, - session, - reserve, - &rh); - (void) qs; - /* qs: #5010! */ - if (NULL == rh) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_arg_unknown (connection, - TALER_EC_WITHDRAW_RESERVE_UNKNOWN, - "reserve_pub"); - } - - /* calculate amount required including fees */ - TALER_amount_ntoh (&value, - &dki->issue.properties.value); - TALER_amount_ntoh (&fee_withdraw, - &dki->issue.properties.fee_withdraw); - - if (GNUNET_OK != - TALER_amount_add (&amount_required, - &value, - &fee_withdraw)) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_AMOUNT_FEE_OVERFLOW); - } - - /* calculate balance of the reserve */ - res = 0; - for (pos = rh; NULL != pos; pos = pos->next) - { - switch (pos->type) - { - case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE: - if (0 == (res & 1)) - deposit_total = pos->details.bank->amount; - else - if (GNUNET_OK != - TALER_amount_add (&deposit_total, - &deposit_total, - &pos->details.bank->amount)) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_AMOUNT_DEPOSITS_OVERFLOW); - } - res |= 1; - break; - case TALER_EXCHANGEDB_RO_WITHDRAW_COIN: - tdki = TEH_KS_denomination_key_lookup (key_state, - &pos->details.withdraw->denom_pub, - TEH_KS_DKU_WITHDRAW); - if (NULL == tdki) - { - GNUNET_break (0); - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_HISTORIC_DENOMINATION_KEY_NOT_FOUND); - } - TALER_amount_ntoh (&value, - &tdki->issue.properties.value); - if (0 == (res & 2)) - withdraw_total = value; - else - if (GNUNET_OK != - TALER_amount_add (&withdraw_total, - &withdraw_total, - &value)) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_AMOUNT_WITHDRAWALS_OVERFLOW); - } - res |= 2; - break; - - case TALER_EXCHANGEDB_RO_PAYBACK_COIN: - if (0 == (res & 1)) - deposit_total = pos->details.payback->value; - else - if (GNUNET_OK != - TALER_amount_add (&deposit_total, - &deposit_total, - &pos->details.payback->value)) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_AMOUNT_DEPOSITS_OVERFLOW); - } - res |= 1; - break; - - case TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK: - if (0 == (res & 2)) - withdraw_total = pos->details.bank->amount; - else - if (GNUNET_OK != - TALER_amount_add (&withdraw_total, - &withdraw_total, - &pos->details.bank->amount)) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_AMOUNT_WITHDRAWALS_OVERFLOW); - } - res |= 2; - break; - } - } - if (0 == (res & 1)) - { - /* did not encounter any wire transfer operations, how can we have a reserve? */ - GNUNET_break (0); - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_RESERVE_WITHOUT_WIRE_TRANSFER); - } - if (0 == (res & 2)) - { - /* did not encounter any withdraw operations, set to zero */ - TALER_amount_get_zero (deposit_total.currency, - &withdraw_total); - } - /* All reserve balances should be non-negative */ - if (GNUNET_SYSERR == - TALER_amount_subtract (&balance, - &deposit_total, - &withdraw_total)) - { - GNUNET_break (0); /* database inconsistent */ - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_RESERVE_HISTORY_IMPOSSIBLE); - } - if (0 < TALER_amount_cmp (&amount_required, - &balance)) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - res = TEH_RESPONSE_reply_reserve_withdraw_insufficient_funds (connection, - rh); - TEH_plugin->free_reserve_history (TEH_plugin->cls, - rh); - return res; - } - TEH_plugin->free_reserve_history (TEH_plugin->cls, - rh); - - /* Balance is good, sign the coin! */ - denom_sig->rsa_signature - = GNUNET_CRYPTO_rsa_sign_blinded (dki->denom_priv.rsa_private_key, - blinded_msg, - blinded_msg_len); - if (NULL == denom_sig->rsa_signature) - { - GNUNET_break (0); - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_WITHDRAW_SIGNATURE_FAILED, - "Internal error"); - } - collectable.sig = *denom_sig; - collectable.denom_pub = *denomination_pub; - collectable.amount_with_fee = amount_required; - collectable.withdraw_fee = fee_withdraw; - collectable.reserve_pub = *reserve; - collectable.h_coin_envelope = *h_blind; - collectable.reserve_sig = *signature; - ret = TEH_plugin->insert_withdraw_info (TEH_plugin->cls, - session, - &collectable); - if (GNUNET_SYSERR == ret) - { - GNUNET_break (0); - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_DB_STORE_ERROR); - } - if (GNUNET_NO == ret) - RETRY_TRANSACTION(session, connection); - COMMIT_TRANSACTION (session, connection); - - return TEH_RESPONSE_reply_reserve_withdraw_success (connection, - &collectable); -} - - - -/** - * Execute a "/reserve/withdraw". Given a reserve and a properly signed - * request to withdraw a coin, check the balance of the reserve and - * if it is sufficient, store the request and return the signed - * blinded envelope. - * - * @param connection the MHD connection to handle - * @param reserve public key of the reserve - * @param denomination_pub public key of the denomination requested - * @param blinded_msg blinded message to be signed - * @param blinded_msg_len number of bytes in @a blinded_msg - * @param signature signature over the withdraw request, to be stored in DB - * @return MHD result code - */ -int -TEH_DB_execute_reserve_withdraw (struct MHD_Connection *connection, - const struct TALER_ReservePublicKeyP *reserve, - const struct TALER_DenominationPublicKey *denomination_pub, - const char *blinded_msg, - size_t blinded_msg_len, - const struct TALER_ReserveSignatureP *signature) -{ - struct TALER_EXCHANGEDB_Session *session; - struct TEH_KS_StateHandle *key_state; - struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; - struct TALER_EXCHANGEDB_CollectableBlindcoin collectable; - struct TALER_DenominationSignature denom_sig; - struct GNUNET_HashCode h_blind; - int res; - - GNUNET_CRYPTO_hash (blinded_msg, - blinded_msg_len, - &h_blind); - if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls))) - { - GNUNET_break (0); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DB_SETUP_FAILED); - } - res = TEH_plugin->get_withdraw_info (TEH_plugin->cls, - session, - &h_blind, - &collectable); - if (GNUNET_SYSERR == res) - { - GNUNET_break (0); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_DB_FETCH_ERROR); - } - - /* Don't sign again if we have already signed the coin */ - if (GNUNET_YES == res) - { - res = TEH_RESPONSE_reply_reserve_withdraw_success (connection, - &collectable); - GNUNET_CRYPTO_rsa_signature_free (collectable.sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_free (collectable.denom_pub.rsa_public_key); - return res; - } - GNUNET_assert (GNUNET_NO == res); - - /* FIXME: do we have to do this a second time here? */ - key_state = TEH_KS_acquire (); - dki = TEH_KS_denomination_key_lookup (key_state, - denomination_pub, - TEH_KS_DKU_WITHDRAW); - if (NULL == dki) - { - TEH_KS_release (key_state); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s, s:I}", - "error", - "Denomination not found", - "code", - (json_int_t) TALER_EC_WITHDRAW_DENOMINATION_KEY_NOT_FOUND); - } - denom_sig.rsa_signature = NULL; - res = execute_reserve_withdraw_transaction (connection, - session, - key_state, - reserve, - denomination_pub, - dki, - blinded_msg, - blinded_msg_len, - &h_blind, - signature, - &denom_sig); - if (NULL != denom_sig.rsa_signature) - GNUNET_CRYPTO_rsa_signature_free (denom_sig.rsa_signature); - TEH_KS_release (key_state); - return res; -} - - -/** * Parse coin melt requests from a JSON object and write them to * the database. * |