implement #3838 (as required for wire transfers)

This commit is contained in:
Christian Grothoff 2015-09-19 20:28:37 +02:00
parent f8a730a0ab
commit cc47c5c701
2 changed files with 170 additions and 55 deletions

View File

@ -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);

View File

@ -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;i<n;i++)
{
struct TALER_Amount amount_with_fee;
struct TALER_Amount deposit_fee;
struct GNUNET_HashCode h_contract;
json_t *wire;
uint64_t transaction_id;
uint64_t id;
int ret;
struct TALER_PQ_ResultSpec rs[] = {
TALER_PQ_result_spec_uint64 ("id",
&id),
TALER_PQ_result_spec_uint64 ("transaction_id",
&transaction_id),
TALER_PQ_result_spec_amount ("amount_with_fee",
&amount_with_fee),
TALER_PQ_result_spec_amount ("deposit_fee",
&deposit_fee),
TALER_PQ_result_spec_auto_from_type ("h_contract",
&h_contract),
TALER_PQ_result_spec_json ("wire",
&wire),
TALER_PQ_result_spec_end
};
if (GNUNET_OK !=
TALER_PQ_extract_result (result, rs, i))
{
GNUNET_break (0);
PQclear (result);
postgres_rollback (cls, session);
return GNUNET_SYSERR;
}
ret = deposit_cb (deposit_cb_cls,
id,
&amount_with_fee,
&deposit_fee,
transaction_id,
&h_contract,
wire);
TALER_PQ_cleanup_result (rs);
PQclear (result);
if (GNUNET_OK != ret)
break;
}
postgres_rollback (cls, session);
return i;
}
/**
* Insert information about deposited coin into the database.
*
@ -3280,6 +3394,7 @@ libtaler_plugin_mintdb_postgres_init (void *cls)
plugin->get_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;