From cc47c5c701340c9be0acc6b7394aa2afad0cd0d3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 19 Sep 2015 20:28:37 +0200 Subject: implement #3838 (as required for wire transfers) --- src/include/taler_mintdb_plugin.h | 102 +++++++++++++++--------------- src/mintdb/plugin_mintdb_postgres.c | 123 ++++++++++++++++++++++++++++++++++-- 2 files changed, 170 insertions(+), 55 deletions(-) diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 4e06fc86f..851ed5265 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -538,7 +538,7 @@ typedef int const struct TALER_Amount *deposit_fee, uint64_t transaction_id, const struct GNUNET_HashCode *h_contract, - const char *wire); + const json_t *wire); /** @@ -628,23 +628,23 @@ struct TALER_MINTDB_Plugin * Commit a transaction. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion connection to use + * @param session connection to use * @return #GNUNET_OK on success */ int (*commit) (void *cls, - struct TALER_MINTDB_Session *sesssion); + struct TALER_MINTDB_Session *session); /** * Abort/rollback a transaction. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion connection to use + * @param session connection to use */ void (*rollback) (void *cls, - struct TALER_MINTDB_Session *sesssion); + struct TALER_MINTDB_Session *session); /** @@ -653,7 +653,7 @@ struct TALER_MINTDB_Plugin * with this key have. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion connection to use + * @param session connection to use * @param denom_pub the public key used for signing coins of this denomination * @param issue issuing information with value, fees and other info about the coin * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure @@ -669,7 +669,7 @@ struct TALER_MINTDB_Plugin * Fetch information about a denomination key. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion connection to use + * @param session connection to use * @param denom_pub the public key used for signing coins of this denomination * @param[out] issue set to issue information with value, fees and other info about the coin, can be NULL * @return #GNUNET_OK on success; #GNUNET_NO if no record was found, #GNUNET_SYSERR on failure @@ -728,7 +728,7 @@ struct TALER_MINTDB_Plugin * key of the hash of the blinded message. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection to use + * @param session database connection to use * @param h_blind hash of the blinded coin to be signed (will match * `h_coin_envelope` in the @a collectable to be returned) * @param collectable corresponding collectable coin (blind signature) @@ -739,7 +739,7 @@ struct TALER_MINTDB_Plugin */ int (*get_withdraw_info) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *h_blind, struct TALER_MINTDB_CollectableBlindcoin *collectable); @@ -749,7 +749,7 @@ struct TALER_MINTDB_Plugin * hash of the blinded message. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection to use + * @param session database connection to use * @param collectable corresponding collectable coin (blind signature) * if a coin is found * @return #GNUNET_SYSERR on internal error @@ -758,7 +758,7 @@ struct TALER_MINTDB_Plugin */ int (*insert_withdraw_info) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct TALER_MINTDB_CollectableBlindcoin *collectable); @@ -767,13 +767,13 @@ struct TALER_MINTDB_Plugin * reserve. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion connection to use + * @param session connection to use * @param reserve_pub public key of the reserve * @return known transaction history (NULL if reserve is unknown) */ struct TALER_MINTDB_ReserveHistory * (*get_reserve_history) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct TALER_ReservePublicKeyP *reserve_pub); @@ -792,7 +792,7 @@ struct TALER_MINTDB_Plugin * Check if we have the specified deposit already in the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection + * @param session database connection * @param deposit deposit to search for * @return #GNUNET_YES if we know this operation, * #GNUNET_NO if this exact deposit is unknown to us, @@ -800,7 +800,7 @@ struct TALER_MINTDB_Plugin */ int (*have_deposit) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct TALER_MINTDB_Deposit *deposit); @@ -808,13 +808,13 @@ struct TALER_MINTDB_Plugin * Insert information about deposited coin into the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion connection to the database + * @param session connection to the database * @param deposit deposit information to store * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int (*insert_deposit) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct TALER_MINTDB_Deposit *deposit); @@ -822,10 +822,10 @@ struct TALER_MINTDB_Plugin * Obtain information about deposits. Iterates over all deposits * above a certain ID. Use a @a min_id of 0 to start at the beginning. * This operation is executed in its own transaction in transaction - * mode "READ COMMITTED", i.e. we should only see valid deposits. + * mode "REPEATABLE READ", i.e. we should only see valid deposits. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion connection to the database + * @param session connection to the database * @param min_id deposit to start at * @param limit maximum number of transactions to fetch * @param deposit_cb function to call for each deposit @@ -835,9 +835,9 @@ struct TALER_MINTDB_Plugin */ int (*iterate_deposits) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, uint64_t min_id, - unsigned int limit, + uint32_t limit, TALER_MINTDB_DepositIterator deposit_cb, void *deposit_cb_cls); @@ -846,7 +846,7 @@ struct TALER_MINTDB_Plugin * Lookup refresh session data under the given @a session_hash. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database handle to use + * @param session database handle to use * @param session_hash hash over the melt to use for the lookup * @param[out] refresh_session where to store the result * @return #GNUNET_YES on success, @@ -855,7 +855,7 @@ struct TALER_MINTDB_Plugin */ int (*get_refresh_session) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash, struct TALER_MINTDB_RefreshSession *refresh_session); @@ -864,7 +864,7 @@ struct TALER_MINTDB_Plugin * Store new refresh session data under the given @a session_hash. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database handle to use + * @param session database handle to use * @param session_hash hash over the melt to use to locate the session * @param refresh_session session data to store * @return #GNUNET_YES on success, @@ -872,7 +872,7 @@ struct TALER_MINTDB_Plugin */ int (*create_refresh_session) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash, const struct TALER_MINTDB_RefreshSession *refresh_session); @@ -881,7 +881,7 @@ struct TALER_MINTDB_Plugin * Store the given /refresh/melt request in the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection + * @param session database connection * @param oldcoin_index index of the coin to store * @param melt coin melt operation details to store; includes * the session hash of the melt @@ -890,7 +890,7 @@ struct TALER_MINTDB_Plugin */ int (*insert_refresh_melt) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, uint16_t oldcoin_index, const struct TALER_MINTDB_RefreshMelt *melt); @@ -899,7 +899,7 @@ struct TALER_MINTDB_Plugin * Get information about melted coin details from the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection + * @param session database connection * @param session_hash hash to identify refresh session * @param oldcoin_index index of the coin to retrieve * @param melt melt data to fill in, can be NULL @@ -908,7 +908,7 @@ struct TALER_MINTDB_Plugin */ int (*get_refresh_melt) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash, uint16_t oldcoin_index, struct TALER_MINTDB_RefreshMelt *melt); @@ -919,7 +919,7 @@ struct TALER_MINTDB_Plugin * in a given refresh operation. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection + * @param session database connection * @param session_hash hash to identify refresh session * @param num_newcoins number of coins to generate, size of the @a denom_pubs array * @param denom_pubs array denominations of the coins to create @@ -928,7 +928,7 @@ struct TALER_MINTDB_Plugin */ int (*insert_refresh_order) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash, uint16_t num_newcoins, const struct TALER_DenominationPublicKey *denom_pubs); @@ -939,7 +939,7 @@ struct TALER_MINTDB_Plugin * create in the given refresh operation. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection + * @param session database connection * @param session_hash hash to identify refresh session * @param num_newcoins size of the @a denom_pubs array * @param[out] denom_pubs where to write @a num_newcoins denomination keys @@ -948,7 +948,7 @@ struct TALER_MINTDB_Plugin */ int (*get_refresh_order) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash, uint16_t num_newcoins, struct TALER_DenominationPublicKey *denom_pubs); @@ -959,7 +959,7 @@ struct TALER_MINTDB_Plugin * for the given refresh session in the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection to use + * @param session database connection to use * @param session_hash hash to identify refresh session * @param cnc_index cut and choose index (1st dimension), relating to #TALER_CNC_KAPPA * @param num_newcoins coin index size of the @a commit_coins array @@ -969,7 +969,7 @@ struct TALER_MINTDB_Plugin */ int (*insert_refresh_commit_coins) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash, uint16_t cnc_index, uint16_t num_newcoins, @@ -981,7 +981,7 @@ struct TALER_MINTDB_Plugin * given coin of the given refresh session from the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection to use + * @param session database connection to use * @param session_hash hash to identify refresh session * @param cnc_index cut and choose set index (1st dimension) * @param num_coins size of the @a commit_coins array @@ -992,7 +992,7 @@ struct TALER_MINTDB_Plugin */ int (*get_refresh_commit_coins) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash, uint16_t cnc_index, uint16_t num_coins, @@ -1004,7 +1004,7 @@ struct TALER_MINTDB_Plugin * for the given refresh session. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection to use + * @param session database connection to use * @param session_hash hash to identify refresh session * @param cnc_index cut and choose index (1st dimension), relating to #TALER_CNC_KAPPA * @param num_links size of the @a commit_link array @@ -1013,7 +1013,7 @@ struct TALER_MINTDB_Plugin */ int (*insert_refresh_commit_links) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash, uint16_t cnc_index, uint16_t num_links, @@ -1024,7 +1024,7 @@ struct TALER_MINTDB_Plugin * for the given refresh session. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection to use + * @param session database connection to use * @param session_hash hash to identify refresh session * @param cnc_index cut and choose index (1st dimension) * @param num_links size of the @a links array to return @@ -1035,7 +1035,7 @@ struct TALER_MINTDB_Plugin */ int (*get_refresh_commit_links) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash, uint16_t cnc_index, uint16_t num_links, @@ -1046,14 +1046,14 @@ struct TALER_MINTDB_Plugin * Get all of the information from the given melt commit operation. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection to use + * @param session database connection to use * @param session_hash hash to identify refresh session * @return NULL if the @a session_hash does not correspond to any known melt * operation */ struct TALER_MINTDB_MeltCommitment * (*get_melt_commitment) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash); @@ -1075,7 +1075,7 @@ struct TALER_MINTDB_Plugin * be used to try to obtain the private keys during "/refresh/link". * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection + * @param session database connection * @param session_hash hash to identify refresh session * @param newcoin_index coin index * @param ev_sig coin signature @@ -1083,7 +1083,7 @@ struct TALER_MINTDB_Plugin */ int (*insert_refresh_out) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash, uint16_t newcoin_index, const struct TALER_DenominationSignature *ev_sig); @@ -1094,13 +1094,13 @@ struct TALER_MINTDB_Plugin * information, the denomination keys and the signatures. * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection + * @param session database connection * @param session_hash session to get linkage data for * @return all known link data for the session */ struct TALER_MINTDB_LinkDataList * (*get_link_data_list) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *session_hash); @@ -1123,7 +1123,7 @@ struct TALER_MINTDB_Plugin * * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection + * @param session database connection * @param coin_pub public key of the coin * @param tdc function to call for each session the coin was melted into * @param tdc_cls closure for @a tdc @@ -1133,7 +1133,7 @@ struct TALER_MINTDB_Plugin */ int (*get_transfer) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct TALER_CoinSpendPublicKeyP *coin_pub, TALER_MINTDB_TransferDataCallback tdc, void *tdc_cls); @@ -1144,13 +1144,13 @@ struct TALER_MINTDB_Plugin * with the given coin (/refresh/melt and /deposit operations). * * @param cls the @e cls of this struct with the plugin-specific state - * @param sesssion database connection + * @param session database connection * @param coin_pub coin to investigate * @return list of transactions, NULL if coin is fresh */ struct TALER_MINTDB_TransactionList * (*get_coin_transactions) (void *cls, - struct TALER_MINTDB_Session *sesssion, + struct TALER_MINTDB_Session *session, const struct TALER_CoinSpendPublicKeyP *coin_pub); diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index efb73a321..86db0a11e 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -426,7 +426,7 @@ postgres_create_tables (void *cls, /* This table contains the wire transfers the mint is supposed to execute to transmit funds to the merchants (and manage refunds). */ SQLEXEC("CREATE TABLE IF NOT EXISTS deposits " - "(id BIGSERIAL" + "(serial_id BIGSERIAL" ",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)" ",denom_pub BYTEA NOT NULL REFERENCES denominations (pub)" ",denom_sig BYTEA NOT NULL" @@ -852,8 +852,8 @@ postgres_prepare (PGconn *db_conn) /* Used in #postgres_iterate_deposits() */ PREPARE ("deposits_iterate", "SELECT" - " id" - " amount_with_fee_val" + " serial_id" + ",amount_with_fee_val" ",amount_with_fee_frac" ",amount_with_fee_curr" ",deposit_fee_val" @@ -863,7 +863,8 @@ postgres_prepare (PGconn *db_conn) ",h_contract" ",wire" " FROM deposits" - " WHERE id>=$1" + " WHERE serial_id>=$1" + " ORDER BY serial_id ASC" " LIMIT $2;", 2, NULL); /* Used in #postgres_get_coin_transactions() to obtain information @@ -1894,6 +1895,119 @@ postgres_have_deposit (void *cls, } +/** + * Obtain information about deposits. Iterates over all deposits + * above a certain ID. Use a @a min_id of 0 to start at the beginning. + * This operation is executed in its own transaction in transaction + * mode "REPEATABLE READ", i.e. we should only see valid deposits. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to the database + * @param min_id deposit to start at + * @param limit maximum number of transactions to fetch + * @param deposit_cb function to call for each deposit + * @param deposit_cb_cls closure for @a deposit_cb + * @return number of rows processed, 0 if none exist, + * #GNUNET_SYSERR on error + */ +static int +postgres_iterate_deposits (void *cls, + struct TALER_MINTDB_Session *session, + uint64_t min_id, + uint32_t limit, + TALER_MINTDB_DepositIterator deposit_cb, + void *deposit_cb_cls) +{ + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_uint64 (&min_id), + TALER_PQ_query_param_uint32 (&limit), + TALER_PQ_query_param_end + }; + PGresult *result; + unsigned int i; + unsigned int n; + + if (GNUNET_OK != + postgres_start (cls, session)) + return GNUNET_SYSERR; + result = PQexec (session->conn, + "SET TRANSACTION REPEATABLE READ"); + if (PGRES_COMMAND_OK != + PQresultStatus (result)) + { + TALER_LOG_ERROR ("Failed to set transaction to REPEATABL EREAD: %s\n", + PQresultErrorMessage (result)); + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + + result = TALER_PQ_exec_prepared (session->conn, + "deposits_iterate", + params); + if (PGRES_TUPLES_OK != + PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + postgres_rollback (cls, session); + return GNUNET_SYSERR; + } + if (0 == (n = PQntuples (result))) + { + PQclear (result); + postgres_rollback (cls, session); + return 0; + } + for (i=0;iget_reserve_history = &postgres_get_reserve_history; plugin->free_reserve_history = &common_free_reserve_history; plugin->have_deposit = &postgres_have_deposit; + plugin->iterate_deposits = &postgres_iterate_deposits; plugin->insert_deposit = &postgres_insert_deposit; plugin->get_refresh_session = &postgres_get_refresh_session; -- cgit v1.2.3