diff options
Diffstat (limited to 'src/backenddb/plugin_merchantdb_postgres.c')
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 595 |
1 files changed, 231 insertions, 364 deletions
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 15996425..ef7deabb 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -2445,159 +2445,255 @@ postgres_increase_refund (void *cls, /** - * Retrieve the order ID that was used to pay for a resource within a session. + * Closure for #lookup_refunds_detailed_cb(). + */ +struct LookupRefundsDetailedContext +{ + /** + * Function to call for each refund. + */ + TALER_MERCHANTDB_RefundDetailCallback rc; + + /** + * Closure for @e rc. + */ + void *rc_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Transaction result. + */ + enum GNUNET_DB_QueryStatus qs; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. * - * @param cls closure - * @param instance_id identifying the instance - * @param fulfillment_url URL that canonically identifies the resource - * being paid for - * @param session_id session id - * @param[out] order_id where to store the order ID that was used when - * paying for the resource URL + * @param cls of type `struct GetRefundsContext *` + * @param result the postgres result + * @param num_result the number of results in @a result + */ +static void +lookup_refunds_detailed_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRefundsDetailedContext *lrdc = cls; + struct PostgresClosure *pg = lrdc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t refund_serial; + struct GNUNET_TIME_Absolute timestamp; + struct TALER_CoinSpendPublicKeyP coin_pub; + uint64_t rtransaction_id; + struct TALER_Amount refund_amount; + char *reason; + char *exchange_url; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("refund_serial", + &refund_serial), + GNUNET_PQ_result_spec_absolute_time ("refund_timestamp", + ×tamp), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &coin_pub), + GNUNET_PQ_result_spec_string ("exchange_url", + &exchange_url), + GNUNET_PQ_result_spec_uint64 ("rtransaction_id", + &rtransaction_id), + GNUNET_PQ_result_spec_string ("reason", + &reason), + TALER_PQ_RESULT_SPEC_AMOUNT ("refund_amount", + &refund_amount), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + lrdc->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + lrdc->qs = i + 1; + lrdc->rc (lrdc->rc_cls, + refund_serial, + timestamp, + &coin_pub, + exchange_url, + rtransaction_id, + reason, + &refund_amount); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Obtain detailed refund data associated with a contract. + * + * @param cls closure, typically a connection to the db + * @param instance_id instance to lookup refunds for + * @param h_contract_terms hash code of the contract + * @param rc function to call for each coin on which there is a refund + * @param rc_cls closure for @a rc * @return transaction status */ -enum GNUNET_DB_QueryStatus -postgres_lookup_order_by_fulfillment (void *cls, - const char *instance_id, - const char *fulfillment_url, - const char *session_id, - char **order_id) +static enum GNUNET_DB_QueryStatus +postgres_lookup_refunds_detailed ( + void *cls, + const char *instance_id, + const struct GNUNET_HashCode *h_contract_terms, + TALER_MERCHANTDB_RefundDetailCallback rc, + void *rc_cls) { struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_string (fulfillment_url), - GNUNET_PQ_query_param_string (session_id), + GNUNET_PQ_query_param_auto_from_type (instance_id), + GNUNET_PQ_query_param_auto_from_type (h_contract_terms), GNUNET_PQ_query_param_end }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("order_id", - order_id), - GNUNET_PQ_result_spec_end + struct LookupRefundsDetailedContext lrdc = { + .rc = rc, + .rc_cls = rc_cls, + .pg = pg }; - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_order_by_fulfillment", - params, - rs); -} + enum GNUNET_DB_QueryStatus qs; + /* no preflight check here, run in transaction by caller! */ + TALER_LOG_DEBUG ("Looking for refund %s + %s\n", + GNUNET_h2s (h_contract_terms), + instance_id); + check_connection (pg); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_refunds_detailed", + params, + &lookup_refunds_detailed_cb, + &lrdc); + if (0 >= qs) + return qs; + return lrdc.qs; +} -/* ********************* OLD API ************************** */ /** - * Retrieve proposal data given its proposal data's hashcode + * Insert refund proof data from the exchange into the database. * * @param cls closure - * @param contract_terms where to store the retrieved proposal data - * @param h_contract_terms proposal data's hashcode that will be used to - * perform the lookup + * @param refund_serial serial number of the refund + * @param refund_fee refund fee the exchange said it charged + * @param exchange_sig signature from exchange that coin was refunded + * @param exchange_pub signing key that was used for @a exchange_sig * @return transaction status */ static enum GNUNET_DB_QueryStatus -postgres_find_contract_terms_from_hash ( +postgres_insert_refund_proof ( void *cls, - json_t **contract_terms, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_MerchantPublicKeyP *merchant_pub) + uint64_t refund_serial, + const struct TALER_Amount *refund_fee, + const struct TALER_ExchangeSignatureP *exchange_sig, + const struct TALER_ExchangePublicKeyP *exchange_pub) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_uint64 (&refund_serial), + GNUNET_PQ_query_param_auto_from_type (exchange_sig), + TALER_PQ_query_param_amount (refund_fee), + GNUNET_PQ_query_param_auto_from_type (exchange_pub), GNUNET_PQ_query_param_end }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_json ("contract_terms", - contract_terms), - GNUNET_PQ_result_spec_end - }; - check_connection (pg); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "find_contract_terms_from_hash", - params, - rs); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_refund_proof", + params); } /** - * Retrieve proposal data given its proposal data's hashcode + * Lookup refund proof data. * * @param cls closure - * @param contract_terms where to store the retrieved proposal data - * @param h_contract_terms proposal data's hashcode that will be used to - * perform the lookup + * @param refund_serial serial number of the refund + * @param[out] exchange_sig set to signature from exchange + * @param[out] exchange_pub signing key that was used for @a exchange_sig * @return transaction status */ static enum GNUNET_DB_QueryStatus -postgres_find_paid_contract_terms_from_hash (void *cls, - json_t **contract_terms, - const struct - GNUNET_HashCode *h_contract_terms, - const struct - TALER_MerchantPublicKeyP * - merchant_pub) +postgres_lookup_refund_proof (void *cls, + uint64_t refund_serial, + struct TALER_ExchangeSignatureP *exchange_sig, + struct TALER_ExchangePublicKeyP *exchange_pub) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_uint64 (&refund_serial), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_json ("contract_terms", - contract_terms), + GNUNET_PQ_result_spec_auto_from_type ("exchange_sig", + exchange_sig), + GNUNET_PQ_result_spec_auto_from_type ("exchange_pub", + exchange_pub), GNUNET_PQ_result_spec_end }; - /* no preflight check here, runs in its own transaction from - caller (in /pay case) */ check_connection (pg); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "find_paid_contract_terms_from_hash", + "lookup_refund_proof", params, rs); } /** - * Store the order ID that was used to pay for a resource within a session. + * Retrieve the order ID that was used to pay for a resource within a session. * * @param cls closure - * @param session_id session id + * @param instance_id identifying the instance * @param fulfillment_url URL that canonically identifies the resource * being paid for - * @param order_id the order ID that was used when paying for the resource URL - * @param merchant_pub public key of the merchant, identifying the instance + * @param session_id session id + * @param[out] order_id where to store the order ID that was used when + * paying for the resource URL * @return transaction status */ enum GNUNET_DB_QueryStatus -postgres_insert_session_info (void *cls, - const char *session_id, - const char *fulfillment_url, - const char *order_id, - const struct - TALER_MerchantPublicKeyP *merchant_pub) +postgres_lookup_order_by_fulfillment (void *cls, + const char *instance_id, + const char *fulfillment_url, + const char *session_id, + char **order_id) { struct PostgresClosure *pg = cls; - struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (session_id), + GNUNET_PQ_query_param_string (instance_id), GNUNET_PQ_query_param_string (fulfillment_url), - GNUNET_PQ_query_param_string (order_id), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_string (session_id), GNUNET_PQ_query_param_end }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_session_info", - params); + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("order_id", + order_id), + GNUNET_PQ_result_spec_end + }; + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_order_by_fulfillment", + params, + rs); } +/* ********************* OLD API ************************** */ + /** * Insert mapping of @a coin_pub and @a h_contract_terms to * corresponding @a wtid. @@ -3373,233 +3469,6 @@ postgres_find_deposits_by_wtid (void *cls, /** - * Closure for #get_refunds_cb(). - */ -struct GetRefundsContext -{ - /** - * Function to call for each refund. - */ - TALER_MERCHANTDB_CoinRefundCallback rc; - - /** - * Closure for @e rc. - */ - void *rc_cls; - - /** - * Plugin context. - */ - struct PostgresClosure *pg; - - /** - * Transaction result. - */ - enum GNUNET_DB_QueryStatus qs; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls of type `struct GetRefundsContext *` - * @param result the postgres result - * @param num_result the number of results in @a result - */ -static void -get_refunds_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct GetRefundsContext *grc = cls; - struct PostgresClosure *pg = grc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_CoinSpendPublicKeyP coin_pub; - uint64_t rtransaction_id; - struct TALER_Amount refund_amount; - struct TALER_Amount refund_fee; - char *reason; - char *exchange_url; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &coin_pub), - GNUNET_PQ_result_spec_string ("exchange_url", - &exchange_url), - GNUNET_PQ_result_spec_uint64 ("rtransaction_id", - &rtransaction_id), - TALER_PQ_RESULT_SPEC_AMOUNT ("refund_amount", - &refund_amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("refund_fee", - &refund_fee), - GNUNET_PQ_result_spec_string ("reason", - &reason), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - grc->qs = GNUNET_DB_STATUS_HARD_ERROR; - return; - } - grc->qs = i + 1; - grc->rc (grc->rc_cls, - &coin_pub, - exchange_url, - rtransaction_id, - reason, - &refund_amount, - &refund_fee); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Obtain refunds associated with a contract. - * - * @param cls closure, typically a connection to the db - * @param merchant_pub public key of the merchant instance - * @param h_contract_terms hash code of the contract - * @param rc function to call for each coin on which there is a refund - * @param rc_cls closure for @a rc - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -postgres_get_refunds_from_contract_terms_hash ( - void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_contract_terms, - TALER_MERCHANTDB_CoinRefundCallback rc, - void *rc_cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_end - }; - struct GetRefundsContext grc = { - .rc = rc, - .rc_cls = rc_cls, - .pg = pg - }; - enum GNUNET_DB_QueryStatus qs; - - /* no preflight check here, run in transaction by caller! */ - TALER_LOG_DEBUG ("Looking for refund %s + %s\n", - GNUNET_h2s (h_contract_terms), - TALER_B2S (merchant_pub)); - check_connection (pg); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "find_refunds_from_contract_terms_hash", - params, - &get_refunds_cb, - &grc); - if (0 >= qs) - return qs; - return grc.qs; -} - - -/** - * Obtain refund proofs associated with a refund operation on a - * coin. - * - * @param cls closure, typically a connection to the db - * @param merchant_pub public key of the merchant instance - * @param h_contract_terms hash code of the contract - * @param coin_pub public key of the coin - * @param rtransaction_id identificator of the refund - * @param[out] exchange_pub public key of the exchange affirming the refund - * @param[out] exchange_sig signature of the exchange affirming the refund - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_get_refund_proof ( - void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t rtransaction_id, - struct TALER_ExchangePublicKeyP *exchange_pub, - struct TALER_ExchangeSignatureP *exchange_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_uint64 (&rtransaction_id), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("exchange_sig", - exchange_sig), - GNUNET_PQ_result_spec_auto_from_type ("exchange_pub", - exchange_pub), - GNUNET_PQ_result_spec_end - }; - - check_connection (pg); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_refund_proof", - params, - rs); -} - - -/** - * Store refund proofs associated with a refund operation on a - * coin. - * - * @param cls closure, typically a connection to the db - * @param merchant_pub public key of the merchant instance - * @param h_contract_terms hash code of the contract - * @param coin_pub public key of the coin - * @param rtransaction_id identificator of the refund - * @param exchange_pub public key of the exchange affirming the refund - * @param exchange_sig signature of the exchange affirming the refund - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_put_refund_proof ( - void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t rtransaction_id, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_ExchangeSignatureP *exchange_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&rtransaction_id), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_auto_from_type (exchange_sig), - GNUNET_PQ_query_param_auto_from_type (exchange_pub), - GNUNET_PQ_query_param_end - }; - - TALER_LOG_DEBUG ("Inserting refund proof %s + %s\n", - GNUNET_h2s (h_contract_terms), - TALER_B2S (coin_pub)); - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_refund_proof", - params); -} - - -/** * Store information about wire fees charged by an exchange, * including signature (so we have proof). * @@ -5630,6 +5499,53 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) " FROM merchant_instances" " WHERE merchant_id=$1))", 2), + /* for postgres_lookup_refunds_detailed() */ + GNUNET_PQ_make_prepare ("lookup_refunds_detailed", + "SELECT" + " refund_serial" + ",refund_timestamp" + ",coin_pub" + ",merchant_deposits.exchange_url" + ",rtransaction_id" + ",reason" + ",refund_amount_val" + ",refund_amount_frac" + " FROM merchant_refunds" + " JOIN merchant_deposits USING (order_serial, coin_pub)" + " WHERE order_serial=" + " (SELECT order_serial" + " FROM merchant_contract_terms" + " WHERE h_contract_terms=$2" + " AND merchant_serial=" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1))", + 2), + /* for postgres_insert_refund_proof() */ + GNUNET_PQ_make_prepare ("insert_refund_proof", + "INSERT INTO merchant_refund_proofs" + "(refund_serial" + ",exchange_sig" + ",refund_fee_val" + ",refund_fee_frac" + ",signkey_serial)" + "SELECT $1, $2, $3, $4, signkey_serial" + " FROM merchant_exchange_signing_keys" + " WHERE exchange_pub=$5" + " ORDER BY start_date DESC" + " LIMIT 1", + 5), + /* for postgres_lookup_refund_proof() */ + GNUNET_PQ_make_prepare ("lookup_refund_proof", + "SELECT" + " merchant_exchange_signing_keys.exchange_pub" + ",exchange_sig" + " FROM merchant_refund_proofs" + " JOIN merchant_exchange_signing_keys" + " USING (signkey_serial)" + " WHERE" + " refund_serial=$1", + 1), /* for postgres_lookup_order_by_fulfillment() */ GNUNET_PQ_make_prepare ("lookup_order_by_fulfillment", "SELECT" @@ -5653,15 +5569,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) ",wtid) VALUES " "($1, $2, $3)", 3), - GNUNET_PQ_make_prepare ("insert_proof", - "INSERT INTO merchant_proofs" - "(exchange_url" - ",wtid" - ",execution_time" - ",signkey_pub" - ",proof) VALUES " - "($1, $2, $3, $4, $5)", - 5), GNUNET_PQ_make_prepare ("insert_contract_terms", "INSERT INTO merchant_contract_terms" "(order_id" @@ -5733,43 +5640,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) " FROM merchant_refunds" " WHERE coin_pub=$1", 1), - GNUNET_PQ_make_prepare ("find_refunds_from_contract_terms_hash", - "SELECT" - " coin_pub" - ",merchant_deposits.exchange_url" - ",rtransaction_id" - ",refund_amount_val" - ",refund_amount_frac" - ",merchant_deposits.refund_fee_val" - ",merchant_deposits.refund_fee_frac" - ",reason" - " FROM merchant_refunds" - " JOIN merchant_deposits USING (merchant_pub, coin_pub)" - " WHERE merchant_refunds.merchant_pub=$1" - " AND merchant_refunds.h_contract_terms=$2", - 2), - GNUNET_PQ_make_prepare ("get_refund_proof", - "SELECT" - " exchange_pub" - ",exchange_sig" - " FROM merchant_refund_proofs" - " WHERE" - " h_contract_terms=$1" - " AND merchant_pub=$2" - " AND coin_pub=$3" - " AND rtransaction_id=$4", - 4), - GNUNET_PQ_make_prepare ("insert_refund_proof", - "INSERT INTO merchant_refund_proofs" - "(rtransaction_id" - ",merchant_pub" - ",h_contract_terms" - ",coin_pub" - ",exchange_sig" - ",exchange_pub)" - " VALUES " - "($1, $2, $3, $4, $5, $6)", - 6), GNUNET_PQ_make_prepare ("find_deposits", "SELECT" " coin_pub" @@ -6022,12 +5892,11 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) plugin->refund_coin = &postgres_refund_coin; plugin->lookup_order_status = &postgres_lookup_order_status; plugin->increase_refund = &postgres_increase_refund; + plugin->lookup_refunds_detailed = &postgres_lookup_refunds_detailed; + plugin->insert_refund_proof = &postgres_insert_refund_proof; + plugin->lookup_refund_proof = &postgres_lookup_refund_proof; plugin->lookup_order_by_fulfillment = &postgres_lookup_order_by_fulfillment; /* OLD API: */ - plugin->find_contract_terms_from_hash = - &postgres_find_contract_terms_from_hash; - plugin->find_paid_contract_terms_from_hash = - &postgres_find_paid_contract_terms_from_hash; plugin->store_coin_to_transfer = &postgres_store_coin_to_transfer; plugin->store_transfer_to_proof = &postgres_store_transfer_to_proof; plugin->store_wire_fee_by_exchange = &postgres_store_wire_fee_by_exchange; @@ -6038,8 +5907,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) plugin->find_proof_by_wtid = &postgres_find_proof_by_wtid; plugin->get_authorized_tip_amount = &postgres_get_authorized_tip_amount; plugin->lookup_wire_fee = &postgres_lookup_wire_fee; - plugin->get_refund_proof = &postgres_get_refund_proof; - plugin->put_refund_proof = &postgres_put_refund_proof; plugin->enable_tip_reserve_TR = &postgres_enable_tip_reserve_TR; plugin->authorize_tip_TR = &postgres_authorize_tip_TR; plugin->lookup_tip_by_id = &postgres_lookup_tip_by_id; |