diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-01-30 13:49:29 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-01-30 13:49:29 +0100 |
commit | a396f4e7fa39f17aec35360eb12098629649c831 (patch) | |
tree | e3e94b05bd85f548e52859af50660e5aea44d456 /src/mint/taler-mint-httpd_db.c | |
parent | 3bb757b3a7bddbd132805dc1147158b40238e543 (diff) | |
parent | ae45b7ac9579cc9fcb9c3008162e07b694eb52f8 (diff) | |
download | exchange-a396f4e7fa39f17aec35360eb12098629649c831.tar.gz exchange-a396f4e7fa39f17aec35360eb12098629649c831.tar.bz2 exchange-a396f4e7fa39f17aec35360eb12098629649c831.zip |
Merge branch 'master' of ssh://taler.net:/var/git/mint
Diffstat (limited to 'src/mint/taler-mint-httpd_db.c')
-rw-r--r-- | src/mint/taler-mint-httpd_db.c | 297 |
1 files changed, 284 insertions, 13 deletions
diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 2b4ade595..b93ead3af 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015, 2016 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1552,9 +1552,214 @@ TMH_DB_execute_admin_add_incoming (struct MHD_Connection *connection, /** + * Closure for #handle_transaction_data. + */ +struct WtidTransactionContext +{ + + /** + * Total amount of the wire transfer, as calculated by + * summing up the individual amounts. To be rounded down + * to calculate the real transfer amount at the end. + * Only valid if @e is_valid is #GNUNET_YES. + */ + struct TALER_Amount total; + + /** + * Value we find in the DB for the @e total; only valid if @e is_valid + * is #GNUNET_YES. + */ + struct TALER_Amount db_transaction_value; + + /** + * Public key of the merchant, only valid if @e is_valid + * is #GNUNET_YES. + */ + struct TALER_MerchantPublicKeyP merchant_pub; + + /** + * Hash of the wire details of the merchant (identical for all + * deposits), only valid if @e is_valid is #GNUNET_YES. + */ + struct GNUNET_HashCode h_wire; + + /** + * JSON array with details about the individual deposits. + */ + json_t *deposits; + + /** + * Initially #GNUNET_NO, if we found no deposits so far. Set to + * #GNUNET_YES if we got transaction data, and the database replies + * remained consistent with respect to @e merchant_pub and @e h_wire + * (as they should). Set to #GNUNET_SYSERR if we encountered an + * internal error. + */ + int is_valid; + +}; + + +/** + * Function called with the results of the lookup of the + * transaction data for the given wire transfer identifier. + * + * @param cls our context for transmission + * @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls) + * @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls) + * @param h_contract which contract was this payment about + * @param transaction_id merchant's transaction ID for the payment + * @param coin_pub which public key was this payment about + * @param deposit_value amount contributed by this coin in total + * @param deposit_fee deposit fee charged by mint for this coin + * @param transaction_value total value of the wire transaction + */ +static void +handle_transaction_data (void *cls, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct GNUNET_HashCode *h_wire, + const struct GNUNET_HashCode *h_contract, + uint64_t transaction_id, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *deposit_value, + const struct TALER_Amount *deposit_fee, + const struct TALER_Amount *transaction_value) +{ + struct WtidTransactionContext *ctx = cls; + struct TALER_Amount delta; + + if (GNUNET_SYSERR == ctx->is_valid) + return; + if (GNUNET_NO == ctx->is_valid) + { + ctx->merchant_pub = *merchant_pub; + ctx->h_wire = *h_wire; + ctx->db_transaction_value = *transaction_value; + ctx->is_valid = GNUNET_YES; + if (GNUNET_OK != + TALER_amount_subtract (&ctx->total, + deposit_value, + deposit_fee)) + { + GNUNET_break (0); + ctx->is_valid = GNUNET_SYSERR; + return; + } + } + else + { + if ( (0 != memcmp (&ctx->merchant_pub, + merchant_pub, + sizeof (struct TALER_MerchantPublicKeyP))) || + (0 != memcmp (&ctx->h_wire, + h_wire, + sizeof (struct GNUNET_HashCode))) || + (0 != TALER_amount_cmp (transaction_value, + &ctx->db_transaction_value)) ) + { + GNUNET_break (0); + ctx->is_valid = GNUNET_SYSERR; + return; + } + if (GNUNET_OK != + TALER_amount_subtract (&delta, + deposit_value, + deposit_fee)) + { + GNUNET_break (0); + ctx->is_valid = GNUNET_SYSERR; + return; + } + if (GNUNET_OK != + TALER_amount_add (&ctx->total, + &ctx->total, + &delta)) + { + GNUNET_break (0); + ctx->is_valid = GNUNET_SYSERR; + return; + } + } + /* NOTE: We usually keep JSON stuff out of the _DB file, and this + is also ugly if we ever add signatures over this data. (#4135) */ + json_array_append (ctx->deposits, + json_pack ("{s:o, s:o, s:o, s:I, s:o}", + "deposit_value", TALER_json_from_amount (deposit_value), + "deposit_fee", TALER_json_from_amount (deposit_fee), + "H_contract", TALER_json_from_data (h_contract, + sizeof (struct GNUNET_HashCode)), + "transaction_id", (json_int_t) transaction_id, + "coin_pub", TALER_json_from_data (coin_pub, + sizeof (struct TALER_CoinSpendPublicKeyP)))); +} + + +/** + * Execute a "/wire/deposits". Returns the transaction information + * associated with the given wire transfer identifier. + * + * @param connection the MHD connection to handle + * @param wtid wire transfer identifier to resolve + * @return MHD result code + */ +int +TMH_DB_execute_wire_deposits (struct MHD_Connection *connection, + const struct TALER_WireTransferIdentifierRawP *wtid) +{ + int ret; + struct WtidTransactionContext ctx; + struct TALER_MINTDB_Session *session; + + if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls, + TMH_test_mode))) + { + GNUNET_break (0); + return TMH_RESPONSE_reply_internal_db_error (connection); + } + ctx.is_valid = GNUNET_NO; + ctx.deposits = json_array (); + ret = TMH_plugin->lookup_wire_transfer (TMH_plugin->cls, + session, + wtid, + &handle_transaction_data, + &ctx); + if (GNUNET_SYSERR == ret) + { + GNUNET_break (0); + json_decref (ctx.deposits); + return TMH_RESPONSE_reply_internal_db_error (connection); + } + if (GNUNET_SYSERR == ctx.is_valid) + { + GNUNET_break (0); + json_decref (ctx.deposits); + return TMH_RESPONSE_reply_internal_db_error (connection); + } + if (GNUNET_NO == ctx.is_valid) + { + json_decref (ctx.deposits); + return TMH_RESPONSE_reply_arg_unknown (connection, + "wtid"); + } + if (0 != TALER_amount_cmp (&ctx.total, + &ctx.db_transaction_value)) + { + /* FIXME: this CAN actually differ, due to rounding + down. But we should still check that the values + do match after rounding 'total' down! */ + } + return TMH_RESPONSE_reply_wire_deposit_details (connection, + &ctx.db_transaction_value, + &ctx.merchant_pub, + &ctx.h_wire, + ctx.deposits); +} + + +/** * Closure for #handle_wtid_data. */ -struct DepositWtidContext +struct DepositWtidContext { /** @@ -1563,6 +1768,26 @@ struct DepositWtidContext struct MHD_Connection *connection; /** + * Hash of the contract we are looking up. + */ + struct GNUNET_HashCode h_contract; + + /** + * Hash of the wire transfer details we are looking up. + */ + struct GNUNET_HashCode h_wire; + + /** + * Public key we are looking up. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + /** + * Transaction ID we are looking up. + */ + uint64_t transaction_id; + + /** * MHD result code to return. */ int res; @@ -1572,10 +1797,13 @@ struct DepositWtidContext /** * Function called with the results of the lookup of the * wire transfer identifier information. - * + * * @param cls our context for transmission - * @param wtid base32-encoded wire transfer identifier, NULL + * @param wtid raw wire transfer identifier, NULL * if the transaction was not yet done + * @param coin_contribution how much did the coin we asked about + * contribute to the total transfer value? (deposit value including fee) + * @param coin_fee how much did the mint charge for the deposit fee * @param execution_time when was the transaction done, or * when we expect it to be done (if @a wtid was NULL); * #GNUNET_TIME_UNIT_FOREVER_ABS if the /deposit is unknown @@ -1583,23 +1811,41 @@ struct DepositWtidContext */ static void handle_wtid_data (void *cls, - const char *wtid, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_Amount *coin_contribution, + const struct TALER_Amount *coin_fee, struct GNUNET_TIME_Absolute execution_time) { struct DepositWtidContext *ctx = cls; + struct TALER_Amount coin_delta; if (NULL == wtid) { - if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us == - execution_time.abs_value_us) - ctx->res = TMH_RESPONSE_reply_deposit_unknown (ctx->connection); - else - ctx->res = TMH_RESPONSE_reply_deposit_pending (ctx->connection); + ctx->res = TMH_RESPONSE_reply_deposit_pending (ctx->connection, + execution_time); } else { - ctx->res = TMH_RESPONSE_reply_deposit_wtid (ctx->connection); - } + if (GNUNET_SYSERR == + TALER_amount_subtract (&coin_delta, + coin_contribution, + coin_fee)) + { + GNUNET_break (0); + ctx->res = TMH_RESPONSE_reply_internal_db_error (ctx->connection); + } + else + { + ctx->res = TMH_RESPONSE_reply_deposit_wtid (ctx->connection, + &ctx->h_contract, + &ctx->h_wire, + &ctx->coin_pub, + &coin_delta, + ctx->transaction_id, + wtid, + execution_time); + } + } } @@ -1625,21 +1871,46 @@ TMH_DB_execute_deposit_wtid (struct MHD_Connection *connection, { int ret; struct DepositWtidContext ctx; + struct TALER_MINTDB_Session *session; + if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls, + TMH_test_mode))) + { + GNUNET_break (0); + return TMH_RESPONSE_reply_internal_db_error (connection); + } ctx.connection = connection; + ctx.h_contract = *h_contract; + ctx.h_wire = *h_wire; + ctx.coin_pub = *coin_pub; + ctx.transaction_id = transaction_id; + ctx.res = GNUNET_SYSERR; ret = TMH_plugin->wire_lookup_deposit_wtid (TMH_plugin->cls, + session, h_contract, h_wire, coin_pub, merchant_pub, transaction_id, &handle_wtid_data, - connection); + &ctx); if (GNUNET_SYSERR == ret) { GNUNET_break (0); + GNUNET_break (GNUNET_SYSERR == ctx.res); return TMH_RESPONSE_reply_internal_db_error (connection); } + if (GNUNET_NO == ret) + { + GNUNET_break (GNUNET_SYSERR == ctx.res); + return TMH_RESPONSE_reply_deposit_unknown (connection); + } + if (GNUNET_SYSERR == ctx.res) + { + GNUNET_break (0); + return TMH_RESPONSE_reply_internal_error (connection, + "bug resolving deposit wtid"); + } return ctx.res; } |