From c12a899f32e1ce432181fa428ebe77bd72ce4394 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 21 Jan 2016 12:09:17 +0100 Subject: finish implementation of DB tracing functions --- src/include/taler_mintdb_plugin.h | 57 ++++---- src/mint/taler-mint-httpd_db.c | 78 ++++++---- src/mintdb/plugin_mintdb_postgres.c | 277 ++++++++++++++++++++++++++++++++---- 3 files changed, 332 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 2ffde2285..e5cf6d6f1 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -570,23 +570,24 @@ typedef void /** * Function called with the results of the lookup of the - * wire transfer identifier information. + * wire transfer identifier information. Only called if + * we are at least aware of the transaction existing. * * @param cls closure * @param wtid 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 minus fee) + * contribute to the total transfer value? (deposit value including fee) + * @param coin_fee how much did the mint charge for the deposit fee * @param total_amount how much was the total wire transfer? * @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 - * to the mint + * when we expect it to be done (if @a wtid was NULL) */ typedef void (*TALER_MINTDB_DepositWtidCallback)(void *cls, const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_Amount *coin_contribution, + const struct TALER_Amount *coin_fee, const struct TALER_Amount *total_amount, struct GNUNET_TIME_Absolute execution_time); @@ -601,18 +602,20 @@ typedef void * @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 coin_value amount contributed by this coin in total (with fee) + * @param coin_fee applicable fee for this coin + * @param transfer_value total amount of the wire transfer */ typedef void -(*TALER_MINTDB_TransactionDataCallback)(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); +(*TALER_MINTDB_WireTransferDataCallback)(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 *coin_value, + const struct TALER_Amount *coin_fee, + const struct TALER_Amount *transfer_value); /** @@ -1233,14 +1236,15 @@ struct TALER_MINTDB_Plugin * @param wtid the raw wire transfer identifier we used * @param cb function to call on each transaction found * @param cb_cls closure for @a cb - * @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors + * @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors, + * #GNUNET_NO if we found no results */ int - (*lookup_wire_transactions) (void *cls, - struct TALER_MINTDB_Session *session, - const struct TALER_WireTransferIdentifierRawP *wtid, - TALER_MINTDB_TransactionDataCallback cb, - void *cb_cls); + (*lookup_wire_transfer) (void *cls, + struct TALER_MINTDB_Session *session, + const struct TALER_WireTransferIdentifierRawP *wtid, + TALER_MINTDB_WireTransferDataCallback cb, + void *cb_cls); /** @@ -1257,7 +1261,8 @@ struct TALER_MINTDB_Plugin * @param transaction_id transaction identifier * @param cb function to call with the result * @param cb_cls closure to pass to @a cb - * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors + * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors, + * #GNUNET_NO if nothing was found */ int (*wire_lookup_deposit_wtid)(void *cls, @@ -1283,8 +1288,9 @@ struct TALER_MINTDB_Plugin * @param transaction_id merchant's transaction ID for the payment * @param execution_time when did we execute the transaction * @param coin_pub which public key was this payment about - * @param coin_value amount contributed by this coin to the total - * @param transaction_value total amount of the wire transaction + * @param coin_value amount contributed by this coin in total + * @param coin_fee deposit fee charged by mint for this coin + * @param transfer_value total amount of the wire transfer * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors */ int @@ -1298,7 +1304,8 @@ struct TALER_MINTDB_Plugin struct GNUNET_TIME_Absolute execution_time, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, - const struct TALER_Amount *transaction_value); + const struct TALER_Amount *coin_fee, + const struct TALER_Amount *transfer_value); }; diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index cc1642202..fb4ee1b7a 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -1565,6 +1565,12 @@ struct WtidTransactionContext */ 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. @@ -1606,6 +1612,7 @@ struct WtidTransactionContext * @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, @@ -1615,7 +1622,8 @@ handle_transaction_data (void *cls, 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 *deposit_fee, + const struct TALER_Amount *transaction_value) { struct WtidTransactionContext *ctx = cls; struct TALER_Amount delta; @@ -1626,6 +1634,7 @@ handle_transaction_data (void *cls, { 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, @@ -1644,7 +1653,9 @@ handle_transaction_data (void *cls, sizeof (struct TALER_MerchantPublicKeyP))) || (0 != memcmp (&ctx->h_wire, h_wire, - sizeof (struct GNUNET_HashCode))) ) + sizeof (struct GNUNET_HashCode))) || + (0 != TALER_amount_cmp (transaction_value, + &ctx->db_transaction_value)) ) { GNUNET_break (0); ctx->is_valid = GNUNET_SYSERR; @@ -1707,11 +1718,11 @@ TMH_DB_execute_wire_deposits (struct MHD_Connection *connection, } ctx.is_valid = GNUNET_NO; ctx.deposits = json_array (); - ret = TMH_plugin->lookup_wire_transactions (TMH_plugin->cls, - session, - &wtid->raw, - &handle_transaction_data, - &ctx); + ret = TMH_plugin->lookup_wire_transfer (TMH_plugin->cls, + session, + &wtid->raw, + &handle_transaction_data, + &ctx); if (GNUNET_SYSERR == ret) { GNUNET_break (0); @@ -1730,8 +1741,15 @@ TMH_DB_execute_wire_deposits (struct MHD_Connection *connection, 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.total, + &ctx.db_transaction_value, &ctx.merchant_pub, &ctx.h_wire, ctx.deposits); @@ -1784,7 +1802,8 @@ struct DepositWtidContext * @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 minus fee) + * contribute to the total transfer value? (deposit value including fee) + * @param coin_fee how much did the mint charge for the deposit fee * @param total_amount how much was the total wire transfer? * @param execution_time when was the transaction done, or * when we expect it to be done (if @a wtid was NULL); @@ -1795,31 +1814,40 @@ static void handle_wtid_data (void *cls, const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_Amount *coin_contribution, + const struct TALER_Amount *coin_fee, const struct TALER_Amount *total_amount, 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, - execution_time); + ctx->res = TMH_RESPONSE_reply_deposit_pending (ctx->connection, + execution_time); } else { - ctx->res = TMH_RESPONSE_reply_deposit_wtid (ctx->connection, - &ctx->h_contract, - &ctx->h_wire, - &ctx->coin_pub, - coin_contribution, - total_amount, - ctx->transaction_id, - wtid, - execution_time); + 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, + total_amount, + ctx->transaction_id, + wtid, + execution_time); + } } } @@ -1874,6 +1902,8 @@ TMH_DB_execute_deposit_wtid (struct MHD_Connection *connection, GNUNET_break (0); return TMH_RESPONSE_reply_internal_db_error (connection); } + if (GNUNET_NO == ret) + return TMH_RESPONSE_reply_deposit_unknown (connection); return ctx.res; } diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index f3760216f..38ce45eb9 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -875,6 +875,26 @@ postgres_prepare (PGconn *db_conn) " (merchant_pub=$3)" " )", 3, NULL); + /* Fetch an existing deposit request. + Used in #postgres_wire_lookup_deposit_wtid(). */ + PREPARE ("get_deposit_for_wtid", + "SELECT" + " amount_with_fee_val" + ",amount_with_fee_frac" + ",amount_with_fee_curr" + ",deposit_fee_val" + ",deposit_fee_frac" + ",deposit_fee_curr" + ",wire_deadline" + " FROM deposits" + " WHERE (" + " (coin_pub=$1) AND" + " (transaction_id=$2) AND" + " (merchant_pub=$3) AND" + " (h_contract=$4) AND" + " (h_wire=$5)" + " )", + 5, NULL); /* Used in #postgres_iterate_deposits() */ PREPARE ("deposits_iterate", @@ -972,7 +992,7 @@ postgres_prepare (PGconn *db_conn) " AND rm.oldcoin_index = rcl.oldcoin_index" " AND rcl.cnc_index=rs.noreveal_index", 1, NULL); - /* Used in #postgres_lookup_wire_transactions */ + /* Used in #postgres_lookup_wire_transfer */ PREPARE ("lookup_transactions", "SELECT" " h_contract" @@ -984,9 +1004,12 @@ postgres_prepare (PGconn *db_conn) ",coin_amount_val" ",coin_amount_frac" ",coin_amount_curr" - ",transaction_total_val" - ",transaction_total_frac" - ",transaction_total_curr" + ",coin_fee_val" + ",coin_fee_frac" + ",coin_fee_curr" + ",transfer_total_val" + ",transfer_total_frac" + ",transfer_total_curr" " FROM aggregation_tracking" " WHERE wtid_raw=$1", 1, NULL); @@ -998,9 +1021,12 @@ postgres_prepare (PGconn *db_conn) ",coin_amount_val" ",coin_amount_frac" ",coin_amount_curr" - ",transaction_total_val" - ",transaction_total_frac" - ",transaction_total_curr" + ",coin_fee_val" + ",coin_fee_frac" + ",coin_fee_curr" + ",transfer_total_val" + ",transfer_total_frac" + ",transfer_total_curr" " FROM aggregation_tracking" " WHERE" " coin_pub=$1 AND" @@ -1022,12 +1048,15 @@ postgres_prepare (PGconn *db_conn) ",coin_amount_val" ",coin_amount_frac" ",coin_amount_curr" - ",transaction_total_val" - ",transaction_total_frac" - ",transaction_total_curr" + ",coin_fee_val" + ",coin_fee_frac" + ",coin_fee_curr" + ",transfer_total_val" + ",transfer_total_frac" + ",transfer_total_curr" ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)", - 13, NULL); + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)", + 16, NULL); return GNUNET_OK; #undef PREPARE @@ -3455,17 +3484,83 @@ postgres_get_coin_transactions (void *cls, * @param wtid the raw wire transfer identifier we used * @param cb function to call on each transaction found * @param cb_cls closure for @a cb - * @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors + * @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors, + * #GNUNET_NO if we found no results */ static int -postgres_lookup_wire_transactions (void *cls, - struct TALER_MINTDB_Session *session, - const struct TALER_WireTransferIdentifierRawP *wtid, - TALER_MINTDB_TransactionDataCallback cb, - void *cb_cls) +postgres_lookup_wire_transfer (void *cls, + struct TALER_MINTDB_Session *session, + const struct TALER_WireTransferIdentifierRawP *wtid, + TALER_MINTDB_WireTransferDataCallback cb, + void *cb_cls) { - GNUNET_break (0); // not implemented! - return GNUNET_SYSERR; + PGresult *result; + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_auto_from_type (wtid), + TALER_PQ_query_param_end + }; + int nrows; + int i; + + /* check if the melt record exists and get it */ + result = TALER_PQ_exec_prepared (session->conn, + "lookup_transactions", + params); + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + nrows = PQntuples (result); + if (0 == nrows) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "lookup_wire_transfer() returned 0 matching rows\n"); + PQclear (result); + return GNUNET_NO; + } + for (i=0;iconn, + "lookup_deposit_wtid", + params); + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + nrows = PQntuples (result); + if (0 == nrows) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "lookup_wire_transfer() returned 0 matching rows\n"); + PQclear (result); + + /* Check if transaction exists in deposits, so that we just + do not have a WTID yet, if so, do call the CB with a NULL wtid + and return GNUNET_YES! */ + { + struct TALER_PQ_QueryParam params2[] = { + TALER_PQ_query_param_auto_from_type (coin_pub), + TALER_PQ_query_param_uint64 (&transaction_id), + TALER_PQ_query_param_auto_from_type (merchant_pub), + TALER_PQ_query_param_auto_from_type (h_contract), + TALER_PQ_query_param_auto_from_type (h_wire), + TALER_PQ_query_param_end + }; + + result = TALER_PQ_exec_prepared (session->conn, + "get_deposit_for_wtid", + params2); + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + } + nrows = PQntuples (result); + if (0 == nrows) + { + PQclear (result); + return GNUNET_NO; + } + + /* Ok, we're aware of the transaction, but it has not yet been + executed */ + { + struct GNUNET_TIME_Absolute exec_time; + struct TALER_Amount coin_amount; + struct TALER_Amount coin_fee; + struct TALER_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_amount ("coin_amount", &coin_amount), + TALER_PQ_result_spec_amount ("deposit_fee", &coin_fee), + TALER_PQ_result_spec_absolute_time ("wire_deadline", &exec_time), + TALER_PQ_result_spec_end + }; + if (GNUNET_OK != TALER_PQ_extract_result (result, rs, 0)) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + cb (cb_cls, + NULL, + &coin_amount, + &coin_fee, + NULL, + exec_time); + PQclear (result); + return GNUNET_YES; + } + } + if (1 != nrows) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + { + struct TALER_WireTransferIdentifierRawP wtid; + struct GNUNET_TIME_Absolute exec_time; + struct TALER_Amount coin_amount; + struct TALER_Amount coin_fee; + struct TALER_Amount transaction_amount; + struct TALER_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_auto_from_type ("wtid_raw", &wtid), + TALER_PQ_result_spec_absolute_time ("execution_time", &exec_time), + TALER_PQ_result_spec_amount ("coin_amount", &coin_amount), + TALER_PQ_result_spec_amount ("coin_fee", &coin_fee), + TALER_PQ_result_spec_amount ("transfer_total", &transaction_amount), + TALER_PQ_result_spec_end + }; + if (GNUNET_OK != TALER_PQ_extract_result (result, rs, 0)) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + cb (cb_cls, + &wtid, + &coin_amount, + &coin_fee, + &transaction_amount, + exec_time); + } + PQclear (result); + return GNUNET_OK; } @@ -3512,8 +3727,9 @@ postgres_wire_lookup_deposit_wtid (void *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 coin_value amount contributed by this coin in total + * @param coin_fee deposit fee charged by mint for this coin + * @param transfer_value total amount of the wire transfer * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors */ static int @@ -3527,7 +3743,8 @@ postgres_insert_aggregation_tracking (void *cls, struct GNUNET_TIME_Absolute execution_time, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, - const struct TALER_Amount *transaction_value) + const struct TALER_Amount *coin_fee, + const struct TALER_Amount *transfer_value) { struct TALER_PQ_QueryParam params[] = { TALER_PQ_query_param_auto_from_type (h_contract), @@ -3538,7 +3755,8 @@ postgres_insert_aggregation_tracking (void *cls, TALER_PQ_query_param_auto_from_type (wtid), TALER_PQ_query_param_absolute_time (&execution_time), TALER_PQ_query_param_amount (coin_value), - TALER_PQ_query_param_amount (transaction_value), + TALER_PQ_query_param_amount (coin_fee), + TALER_PQ_query_param_amount (transfer_value), TALER_PQ_query_param_end }; PGresult *result; @@ -3560,9 +3778,6 @@ postgres_insert_aggregation_tracking (void *cls, } PQclear (result); return GNUNET_OK; - - GNUNET_break (0); // not implemented - return GNUNET_SYSERR; } @@ -3635,7 +3850,7 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->get_transfer = &postgres_get_transfer; plugin->get_coin_transactions = &postgres_get_coin_transactions; plugin->free_coin_transaction_list = &common_free_coin_transaction_list; - plugin->lookup_wire_transactions = &postgres_lookup_wire_transactions; + plugin->lookup_wire_transfer = &postgres_lookup_wire_transfer; plugin->wire_lookup_deposit_wtid = &postgres_wire_lookup_deposit_wtid; plugin->insert_aggregation_tracking = &postgres_insert_aggregation_tracking; return plugin; -- cgit v1.2.3