diff --git a/contrib/gana b/contrib/gana index a4a6b9ba4..d83d2584f 160000 --- a/contrib/gana +++ b/contrib/gana @@ -1 +1 @@ -Subproject commit a4a6b9ba4b2634c56194d53e36344686d7052cef +Subproject commit d83d2584fd4698719b8eb78a4e0e9c8dad698aca diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am index bae4eba06..ac300a9c2 100644 --- a/src/exchangedb/Makefile.am +++ b/src/exchangedb/Makefile.am @@ -68,7 +68,10 @@ endif libtaler_plugin_exchangedb_postgres_la_SOURCES = \ plugin_exchangedb_common.c plugin_exchangedb_common.h \ + pg_setup_wire_target.h pg_setup_wire_target.c \ + pg_compute_shard.h pg_compute_shard.c \ plugin_exchangedb_postgres.c pg_helper.h \ + pg_reserves_update.h pg_reserves_update.c \ pg_insert_aggregation_tracking.h pg_insert_aggregation_tracking.c \ pg_select_aggregation_amounts_for_kyc_check.h pg_select_aggregation_amounts_for_kyc_check.c \ pg_lookup_wire_fee_by_time.h pg_lookup_wire_fee_by_time.c \ @@ -90,6 +93,106 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \ pg_select_purse_merge.h pg_select_purse_merge.c \ pg_select_contract_by_purse.h pg_select_contract_by_purse.c \ pg_insert_drain_profit.h pg_insert_drain_profit.c \ + pg_create_tables.h pg_create_tables.c \ + pg_setup_foreign_servers.h pg_setup_foreign_servers.c \ + pg_event_listen.h pg_event_listen.c \ + pg_event_listen_cancel.h pg_event_listen_cancel.c \ + pg_event_notify.h pg_event_notify.c \ + pg_get_denomination_info.h pg_get_denomination_info.c \ + pg_iterate_denomination_info.h pg_iterate_denomination_info.c \ + pg_iterate_denominations.h pg_iterate_denominations.c \ + pg_iterate_active_auditors.h pg_iterate_active_auditors.c \ + pg_iterate_auditor_denominations.h pg_iterate_auditor_denominations.c \ + pg_reserves_get.h pg_reserves_get.c \ + pg_reserves_get_origin.h pg_reserves_get_origin.c \ + pg_drain_kyc_alert.h pg_drain_kyc_alert.c \ + pg_reserves_in_insert.h pg_reserves_in_insert.c \ + pg_get_withdraw_info.h pg_get_withdraw_info.c \ + pg_do_batch_withdraw.h pg_do_batch_withdraw.c \ + pg_get_policy_details.h pg_get_policy_details.c \ + pg_persist_policy_details.h pg_persist_policy_details.c \ + pg_do_deposit.h pg_do_deposit.c \ + pg_add_policy_fulfillment_proof.h pg_add_policy_fulfillment_proof.c \ + pg_do_melt.h pg_do_melt.c \ + pg_do_refund.h pg_do_refund.c \ + pg_do_recoup.h pg_do_recoup.c \ + pg_do_recoup_refresh.h pg_do_recoup_refresh.c \ + pg_get_reserve_balance.h pg_get_reserve_balance.c \ + pg_count_known_coins.h pg_count_known_coins.c \ + pg_ensure_coin_known.h pg_ensure_coin_known.c \ + pg_get_known_coin.h pg_get_known_coin.c \ + pg_get_coin_denomination.h pg_get_coin_denomination.c \ + pg_have_deposit2.h pg_have_deposit2.c \ + pg_aggregate.h pg_aggregate.c \ + pg_create_aggregation_transient.h pg_create_aggregation_transient.c \ + pg_select_aggregation_transient.h pg_select_aggregation_transient.c \ + pg_find_aggregation_transient.h pg_find_aggregation_transient.c \ + pg_update_aggregation_transient.h pg_update_aggregation_transient.c \ + pg_get_ready_deposit.h pg_get_ready_deposit.c \ + pg_insert_deposit.h pg_insert_deposit.c \ + pg_insert_refund.h pg_insert_refund.c \ + pg_select_refunds_by_coin.h pg_select_refunds_by_coin.c \ + pg_get_melt.h pg_get_melt.c \ + pg_insert_refresh_reveal.h pg_insert_refresh_reveal.c \ + pg_get_refresh_reveal.h pg_get_refresh_reveal.c \ + pg_lookup_wire_transfer.h pg_lookup_wire_transfer.c \ + pg_lookup_transfer_by_deposit.h pg_lookup_transfer_by_deposit.c \ + pg_insert_wire_fee.h pg_insert_wire_fee.c \ + pg_insert_global_fee.h pg_insert_global_fee.c \ + pg_get_wire_fee.h pg_get_wire_fee.c \ + pg_get_global_fee.h pg_get_global_fee.c \ + pg_get_global_fees.h pg_get_global_fees.c \ + pg_insert_reserve_closed.h pg_insert_reserve_closed.c \ + pg_wire_prepare_data_insert.h pg_wire_prepare_data_insert.c \ + pg_wire_prepare_data_mark_finished.h pg_wire_prepare_data_mark_finished.c \ + pg_wire_prepare_data_mark_failed.h pg_wire_prepare_data_mark_failed.c \ + pg_wire_prepare_data_get.h pg_wire_prepare_data_get.c \ + pg_start_deferred_wire_out.h pg_start_deferred_wire_out.c \ + pg_store_wire_transfer_out.h pg_store_wire_transfer_out.c \ + pg_gc.h pg_gc.c \ + pg_select_deposits_above_serial_id.h pg_select_deposits_above_serial_id.c \ + pg_select_history_requests_above_serial_id.h pg_select_history_requests_above_serial_id.c \ + pg_select_purse_decisions_above_serial_id.h pg_select_purse_decisions_above_serial_id.c \ + pg_select_purse_deposits_by_purse.h pg_select_purse_deposits_by_purse.c \ + pg_select_refreshes_above_serial_id.h pg_select_refreshes_above_serial_id.c \ + pg_select_refunds_above_serial_id.h pg_select_refunds_above_serial_id.c \ + pg_select_reserves_in_above_serial_id.h pg_select_reserves_in_above_serial_id.c \ + pg_select_reserves_in_above_serial_id_by_account.h pg_select_reserves_in_above_serial_id_by_account.c \ + pg_select_withdrawals_above_serial_id.h pg_select_withdrawals_above_serial_id.c \ + pg_select_wire_out_above_serial_id.h pg_select_wire_out_above_serial_id.c \ + pg_select_wire_out_above_serial_id_by_account.h pg_select_wire_out_above_serial_id_by_account.c \ + pg_select_recoup_above_serial_id.h pg_select_recoup_above_serial_id.c \ + pg_select_recoup_refresh_above_serial_id.h pg_select_recoup_refresh_above_serial_id.c \ + pg_get_reserve_by_h_blind.h pg_get_reserve_by_h_blind.c \ + pg_get_old_coin_by_h_blind.h pg_get_old_coin_by_h_blind.c \ + pg_insert_denomination_revocation.h pg_insert_denomination_revocation.c \ + pg_get_denomination_revocation.h pg_get_denomination_revocation.c \ + pg_select_deposits_missing_wire.h pg_select_deposits_missing_wire.c \ + pg_lookup_auditor_timestamp.h pg_lookup_auditor_timestamp.c \ + pg_lookup_auditor_status.h pg_lookup_auditor_status.c \ + pg_insert_auditor.h pg_insert_auditor.c \ + pg_lookup_wire_timestamp.h pg_lookup_wire_timestamp.c \ + pg_insert_wire.h pg_insert_wire.c \ + pg_update_wire.h pg_update_wire.c \ + pg_get_wire_accounts.h pg_get_wire_accounts.c \ + pg_get_wire_fees.h pg_get_wire_fees.c \ + pg_insert_signkey_revocation.h pg_insert_signkey_revocation.c \ + pg_lookup_signkey_revocation.h pg_lookup_signkey_revocation.c \ + pg_lookup_denomination_key.h pg_lookup_denomination_key.c \ + pg_insert_auditor_denom_sig.h pg_insert_auditor_denom_sig.c \ + pg_select_auditor_denom_sig.h pg_select_auditor_denom_sig.c \ + pg_add_denomination_key.h pg_add_denomination_key.c \ + pg_lookup_signing_key.h pg_lookup_signing_key.c \ + pg_begin_shard.h pg_begin_shard.c \ + pg_abort_shard.h pg_abort_shard.c \ + pg_complete_shard.h pg_complete_shard.c \ + pg_release_revolving_shard.h pg_release_revolving_shard.c \ + pg_delete_shard_locks.h pg_delete_shard_locks.c \ + pg_set_extension_manifest.h pg_set_extension_manifest.c \ + pg_insert_partner.h pg_insert_partner.c \ + pg_expire_purse.h pg_expire_purse.c \ + pg_select_purse_by_merge_pub.h pg_select_purse_by_merge_pub.c \ + pg_set_purse_balance.h pg_set_purse_balance.c \ pg_do_reserve_purse.h pg_do_reserve_purse.c \ pg_lookup_global_fee_by_time.h pg_lookup_global_fee_by_time.c \ pg_do_purse_deposit.h pg_do_purse_deposit.c \ diff --git a/src/exchangedb/pg_abort_shard.c b/src/exchangedb/pg_abort_shard.c new file mode 100644 index 000000000..de10f7d3f --- /dev/null +++ b/src/exchangedb/pg_abort_shard.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_abort_shard.c + * @brief Implementation of the abort_shard function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_abort_shard.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_abort_shard (void *cls, + const char *job_name, + uint64_t start_row, + uint64_t end_row) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_uint64 (&start_row), + GNUNET_PQ_query_param_uint64 (&end_row), + GNUNET_PQ_query_param_end + }; + + + PREPARE (pg, + "abort_shard", + "UPDATE work_shards" + " SET last_attempt=0" + " WHERE job_name = $1 " + " AND start_row = $2 " + " AND end_row = $3;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "abort_shard", + params); +} diff --git a/src/exchangedb/pg_abort_shard.h b/src/exchangedb/pg_abort_shard.h new file mode 100644 index 000000000..070b48dab --- /dev/null +++ b/src/exchangedb/pg_abort_shard.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_abort_shard.h + * @brief implementation of the abort_shard function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_ABORT_SHARD_H +#define PG_ABORT_SHARD_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to abort work on a shard. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param job_name name of the operation to abort a word shard for + * @param start_row inclusive start row of the shard + * @param end_row exclusive end row of the shard + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_abort_shard (void *cls, + const char *job_name, + uint64_t start_row, + uint64_t end_row); +#endif diff --git a/src/exchangedb/pg_add_denomination_key.c b/src/exchangedb/pg_add_denomination_key.c new file mode 100644 index 000000000..e115a44ec --- /dev/null +++ b/src/exchangedb/pg_add_denomination_key.c @@ -0,0 +1,89 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_add_denomination_key.c + * @brief Implementation of the add_denomination_key function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_add_denomination_key.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_add_denomination_key ( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta, + const struct TALER_MasterSignatureP *master_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam iparams[] = { + GNUNET_PQ_query_param_auto_from_type (h_denom_pub), + TALER_PQ_query_param_denom_pub (denom_pub), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_timestamp (&meta->start), + GNUNET_PQ_query_param_timestamp (&meta->expire_withdraw), + GNUNET_PQ_query_param_timestamp (&meta->expire_deposit), + GNUNET_PQ_query_param_timestamp (&meta->expire_legal), + TALER_PQ_query_param_amount (&meta->value), + TALER_PQ_query_param_amount (&meta->fees.withdraw), + TALER_PQ_query_param_amount (&meta->fees.deposit), + TALER_PQ_query_param_amount (&meta->fees.refresh), + TALER_PQ_query_param_amount (&meta->fees.refund), + GNUNET_PQ_query_param_uint32 (&meta->age_mask.bits), + GNUNET_PQ_query_param_end + }; + + /* Sanity check: ensure fees match coin currency */ + GNUNET_assert (GNUNET_YES == + TALER_denom_fee_check_currency (meta->value.currency, + &meta->fees)); + /* Used in #postgres_insert_denomination_info() and + #postgres_add_denomination_key() */ + PREPARE (pg, + "denomination_insert", + "INSERT INTO denominations " + "(denom_pub_hash" + ",denom_pub" + ",master_sig" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin_val" /* value of this denom */ + ",coin_frac" /* fractional value of this denom */ + ",fee_withdraw_val" + ",fee_withdraw_frac" + ",fee_deposit_val" + ",fee_deposit_frac" + ",fee_refresh_val" + ",fee_refresh_frac" + ",fee_refund_val" + ",fee_refund_frac" + ",age_mask" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," + " $11, $12, $13, $14, $15, $16, $17, $18);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "denomination_insert", + iparams); +} + diff --git a/src/exchangedb/pg_add_denomination_key.h b/src/exchangedb/pg_add_denomination_key.h new file mode 100644 index 000000000..d131679e8 --- /dev/null +++ b/src/exchangedb/pg_add_denomination_key.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_add_denomination_key.h + * @brief implementation of the add_denomination_key function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_ADD_DENOMINATION_KEY_H +#define PG_ADD_DENOMINATION_KEY_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Activate denomination key, turning it into a "current" or "valid" + * denomination key by adding the master signature. + * + * @param cls closure + * @param h_denom_pub hash of the denomination public key + * @param denom_pub the actual denomination key + * @param meta meta data about the denomination + * @param master_sig master signature to add + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_add_denomination_key ( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta, + const struct TALER_MasterSignatureP *master_sig); +#endif diff --git a/src/exchangedb/pg_add_policy_fulfillment_proof.c b/src/exchangedb/pg_add_policy_fulfillment_proof.c new file mode 100644 index 000000000..bb06206ae --- /dev/null +++ b/src/exchangedb/pg_add_policy_fulfillment_proof.c @@ -0,0 +1,132 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_add_policy_fulfillment_proof.c + * @brief Implementation of the add_policy_fulfillment_proof function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_add_policy_fulfillment_proof.h" +#include "pg_helper.h" + + +/** + * Compares two indices into an array of hash codes according to + * GNUNET_CRYPTO_hash_cmp of the content at those index positions. + * + * Used in a call qsort_t in order to generate sorted policy_hash_codes. + */ +static int +hash_code_cmp ( + const void *hc1, + const void *hc2, + void *arg) +{ + size_t i1 = *(size_t *) hc1; + size_t i2 = *(size_t *) hc2; + const struct TALER_PolicyDetails *d = arg; + + return GNUNET_CRYPTO_hash_cmp (&d[i1].hash_code, + &d[i2].hash_code); +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_add_policy_fulfillment_proof ( + void *cls, + struct TALER_PolicyFulfillmentTransactionData *fulfillment) +{ + enum GNUNET_DB_QueryStatus qs; + struct PostgresClosure *pg = cls; + size_t count = fulfillment->details_count; + struct GNUNET_HashCode hcs[count]; + + /* Create the sorted policy_hash_codes */ + { + size_t idx[count]; + for (size_t i = 0; i < count; i++) + idx[i] = i; + + /* Sort the indices according to the hash codes of the corresponding + * details. */ + qsort_r (idx, + count, + sizeof(size_t), + hash_code_cmp, + fulfillment->details); + + /* Finally, concatenate all hash_codes in sorted order */ + for (size_t i = 0; i < count; i++) + hcs[i] = fulfillment->details[idx[i]].hash_code; + } + + + /* Now, add the proof to the policy_fulfillments table, retrieve the + * record_id */ + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&fulfillment->timestamp), + TALER_PQ_query_param_json (fulfillment->proof), + GNUNET_PQ_query_param_auto_from_type (&fulfillment->h_proof), + GNUNET_PQ_query_param_fixed_size (hcs, + count * sizeof(struct GNUNET_HashCode)), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("fulfillment_id", + &fulfillment->fulfillment_id), + GNUNET_PQ_result_spec_end + }; + + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "insert_proof_into_policy_fulfillments", + params, + rs); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) + return qs; + } + + /* Now, set the states of each entry corresponding to the hash_codes in + * policy_details accordingly */ + for (size_t i = 0; i < count; i++) + { + struct TALER_PolicyDetails *pos = &fulfillment->details[i]; + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&pos->hash_code), + GNUNET_PQ_query_param_timestamp (&pos->deadline), + TALER_PQ_query_param_amount (&pos->commitment), + TALER_PQ_query_param_amount (&pos->accumulated_total), + TALER_PQ_query_param_amount (&pos->policy_fee), + TALER_PQ_query_param_amount (&pos->transferable_amount), + GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state), + GNUNET_PQ_query_param_end + }; + + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_policy_details", + params); + if (qs < 0) + return qs; + } + } + + return qs; +} diff --git a/src/exchangedb/pg_add_policy_fulfillment_proof.h b/src/exchangedb/pg_add_policy_fulfillment_proof.h new file mode 100644 index 000000000..77bddaf08 --- /dev/null +++ b/src/exchangedb/pg_add_policy_fulfillment_proof.h @@ -0,0 +1,39 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_add_policy_fulfillment_proof.h + * @brief implementation of the add_policy_fulfillment_proof function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_ADD_POLICY_FULFILLMENT_PROOF_H +#define PG_ADD_POLICY_FULFILLMENT_PROOF_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Add a proof of fulfillment into the policy_fulfillments table + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param fulfillment fullfilment transaction data to be added + * @return query execution status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_add_policy_fulfillment_proof ( + void *cls, + struct TALER_PolicyFulfillmentTransactionData *fulfillment); + +#endif diff --git a/src/exchangedb/pg_aggregate.c b/src/exchangedb/pg_aggregate.c new file mode 100644 index 000000000..f1c4d6776 --- /dev/null +++ b/src/exchangedb/pg_aggregate.c @@ -0,0 +1,205 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_aggregate.c + * @brief Implementation of the aggregate function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_aggregate.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_aggregate ( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_WireTransferIdentifierRawP *wtid, + struct TALER_Amount *total) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_TIME_Absolute now = {0}; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_end + }; + uint64_t sum_deposit_value; + uint64_t sum_deposit_frac; + uint64_t sum_refund_value; + uint64_t sum_refund_frac; + uint64_t sum_fee_value; + uint64_t sum_fee_frac; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("sum_deposit_value", + &sum_deposit_value), + GNUNET_PQ_result_spec_uint64 ("sum_deposit_fraction", + &sum_deposit_frac), + GNUNET_PQ_result_spec_uint64 ("sum_refund_value", + &sum_refund_value), + GNUNET_PQ_result_spec_uint64 ("sum_refund_fraction", + &sum_refund_frac), + GNUNET_PQ_result_spec_uint64 ("sum_fee_value", + &sum_fee_value), + GNUNET_PQ_result_spec_uint64 ("sum_fee_fraction", + &sum_fee_frac), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + struct TALER_Amount sum_deposit; + struct TALER_Amount sum_refund; + struct TALER_Amount sum_fee; + struct TALER_Amount delta; + + now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (), + pg->aggregator_shift); + + /* Used in #postgres_aggregate() */ + PREPARE (pg, + "aggregate", + "WITH rdy AS (" /* find deposits ready by merchant */ + " SELECT" + " coin_pub" + " FROM deposits_for_matching" + " WHERE refund_deadline<$1" /* filter by shard, only actually executable deposits */ + " AND merchant_pub=$2" /* filter by target merchant */ + " ORDER BY refund_deadline ASC" /* ordering is not critical */ + " LIMIT " + TALER_QUOTE (TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) /* limits transaction size */ + " )" + " ,dep AS (" /* restrict to our merchant and account and mark as done */ + " UPDATE deposits" + " SET done=TRUE" + " WHERE coin_pub IN (SELECT coin_pub FROM rdy)" + " AND merchant_pub=$2" /* theoretically, same coin could be spent at another merchant */ + " AND wire_target_h_payto=$3" /* merchant could have a 2nd bank account */ + " AND done=FALSE" /* theoretically, same coin could be spend at the same merchant a 2nd time */ + " RETURNING" + " deposit_serial_id" + " ,coin_pub" + " ,amount_with_fee_val AS amount_val" + " ,amount_with_fee_frac AS amount_frac)" + " ,ref AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ + " SELECT" + " amount_with_fee_val AS refund_val" + " ,amount_with_fee_frac AS refund_frac" + " ,coin_pub" + " ,deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ + " FROM refunds" + " WHERE coin_pub IN (SELECT coin_pub FROM dep)" + " AND deposit_serial_id IN (SELECT deposit_serial_id FROM dep))" + " ,ref_by_coin AS (" /* total up refunds by coin */ + " SELECT" + " SUM(refund_val) AS sum_refund_val" + " ,SUM(refund_frac) AS sum_refund_frac" + " ,coin_pub" + " ,deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ + " FROM ref" + " GROUP BY coin_pub, deposit_serial_id)" + " ,norm_ref_by_coin AS (" /* normalize */ + " SELECT" + " sum_refund_val + sum_refund_frac / 100000000 AS norm_refund_val" + " ,sum_refund_frac % 100000000 AS norm_refund_frac" + " ,coin_pub" + " ,deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ + " FROM ref_by_coin)" + " ,fully_refunded_coins AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ + " SELECT" + " dep.coin_pub" + " FROM norm_ref_by_coin norm" + " JOIN dep" + " ON (norm.coin_pub = dep.coin_pub" + " AND norm.deposit_serial_id = dep.deposit_Serial_id" + " AND norm.norm_refund_val = dep.amount_val" + " AND norm.norm_refund_frac = dep.amount_frac))" + " ,fees AS (" /* find deposit fees for not fully refunded deposits */ + " SELECT" + " denom.fee_deposit_val AS fee_val" + " ,denom.fee_deposit_frac AS fee_frac" + " ,cs.deposit_serial_id" /* ensures we get the fee for each coin, not once per denomination */ + " FROM dep cs" + " JOIN known_coins kc" /* NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ + " USING (coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " WHERE coin_pub NOT IN (SELECT coin_pub FROM fully_refunded_coins))" + " ,dummy AS (" /* add deposits to aggregation_tracking */ + " INSERT INTO aggregation_tracking" + " (deposit_serial_id" + " ,wtid_raw)" + " SELECT deposit_serial_id,$4" + " FROM dep)" + "SELECT" /* calculate totals (deposits, refunds and fees) */ + " CAST(COALESCE(SUM(dep.amount_val),0) AS INT8) AS sum_deposit_value" /* cast needed, otherwise we get NUMBER */ + " ,COALESCE(SUM(dep.amount_frac),0) AS sum_deposit_fraction" /* SUM over INT returns INT8 */ + " ,CAST(COALESCE(SUM(ref.refund_val),0) AS INT8) AS sum_refund_value" + " ,COALESCE(SUM(ref.refund_frac),0) AS sum_refund_fraction" + " ,CAST(COALESCE(SUM(fees.fee_val),0) AS INT8) AS sum_fee_value" + " ,COALESCE(SUM(fees.fee_frac),0) AS sum_fee_fraction" + " FROM dep " + " FULL OUTER JOIN ref ON (FALSE)" /* We just want all sums */ + " FULL OUTER JOIN fees ON (FALSE);"); + + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "aggregate", + params, + rs); + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + return qs; + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (pg->currency, + total)); + return qs; + } + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (pg->currency, + &sum_deposit)); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (pg->currency, + &sum_refund)); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (pg->currency, + &sum_fee)); + sum_deposit.value = sum_deposit_frac / TALER_AMOUNT_FRAC_BASE + + sum_deposit_value; + sum_deposit.fraction = sum_deposit_frac % TALER_AMOUNT_FRAC_BASE; + sum_refund.value = sum_refund_frac / TALER_AMOUNT_FRAC_BASE + + sum_refund_value; + sum_refund.fraction = sum_refund_frac % TALER_AMOUNT_FRAC_BASE; + sum_fee.value = sum_fee_frac / TALER_AMOUNT_FRAC_BASE + + sum_fee_value; + sum_fee.fraction = sum_fee_frac % TALER_AMOUNT_FRAC_BASE; \ + GNUNET_assert (0 <= + TALER_amount_subtract (&delta, + &sum_deposit, + &sum_refund)); + GNUNET_assert (0 <= + TALER_amount_subtract (total, + &delta, + &sum_fee)); + return qs; +} diff --git a/src/exchangedb/pg_aggregate.h b/src/exchangedb/pg_aggregate.h new file mode 100644 index 000000000..1f986ef9e --- /dev/null +++ b/src/exchangedb/pg_aggregate.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_aggregate.h + * @brief implementation of the aggregate function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_AGGREGATE_H +#define PG_AGGREGATE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Aggregate all matching deposits for @a h_payto and + * @a merchant_pub, returning the total amounts. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto destination of the wire transfer + * @param merchant_pub public key of the merchant + * @param wtid wire transfer ID to set for the aggregate + * @param[out] total set to the sum of the total deposits minus applicable deposit fees and refunds + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_aggregate ( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_WireTransferIdentifierRawP *wtid, + struct TALER_Amount *total); + +#endif diff --git a/src/exchangedb/pg_begin_shard.c b/src/exchangedb/pg_begin_shard.c new file mode 100644 index 000000000..2d4a33af8 --- /dev/null +++ b/src/exchangedb/pg_begin_shard.c @@ -0,0 +1,258 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_begin_shard.c + * @brief Implementation of the begin_shard function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_begin_shard.h" +#include "pg_helper.h" +#include "pg_start.h" +#include "pg_rollback.h" +#include "pg_commit.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_begin_shard (void *cls, + const char *job_name, + struct GNUNET_TIME_Relative delay, + uint64_t shard_size, + uint64_t *start_row, + uint64_t *end_row) +{ + struct PostgresClosure *pg = cls; + + for (unsigned int retries = 0; retries<10; retries++) + { + if (GNUNET_OK != + TEH_PG_start (pg, + "begin_shard")) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + + { + struct GNUNET_TIME_Absolute past; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_absolute_time (&past), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("start_row", + start_row), + GNUNET_PQ_result_spec_uint64 ("end_row", + end_row), + GNUNET_PQ_result_spec_end + }; + + past = GNUNET_TIME_absolute_get (); + + PREPARE (pg, + "get_open_shard", + "SELECT" + " start_row" + ",end_row" + " FROM work_shards" + " WHERE job_name=$1" + " AND completed=FALSE" + " AND last_attempt<$2" + " ORDER BY last_attempt ASC" + " LIMIT 1;"); + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_open_shard", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TEH_PG_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TEH_PG_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + { + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_TIME_Absolute now; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_uint64 (start_row), + GNUNET_PQ_query_param_uint64 (end_row), + GNUNET_PQ_query_param_end + }; + + now = GNUNET_TIME_relative_to_absolute (delay); + + + PREPARE (pg, + "reclaim_shard", + "UPDATE work_shards" + " SET last_attempt=$2" + " WHERE job_name=$1" + " AND start_row=$3" + " AND end_row=$4"); + + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "reclaim_shard", + params); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TEH_PG_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TEH_PG_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + goto commit; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); /* logic error, should be impossible */ + TEH_PG_rollback (pg); + return GNUNET_DB_STATUS_HARD_ERROR; + } + } + break; /* actually unreachable */ + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + break; /* continued below */ + } + } /* get_open_shard */ + + /* No open shard, find last 'end_row' */ + { + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("end_row", + start_row), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_last_shard", + "SELECT" + " end_row" + " FROM work_shards" + " WHERE job_name=$1" + " ORDER BY end_row DESC" + " LIMIT 1;"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_last_shard", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TEH_PG_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TEH_PG_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + *start_row = 0; /* base-case: no shards yet */ + break; /* continued below */ + } + *end_row = *start_row + shard_size; + } /* get_last_shard */ + + /* Claim fresh shard */ + { + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_TIME_Absolute now; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_uint64 (start_row), + GNUNET_PQ_query_param_uint64 (end_row), + GNUNET_PQ_query_param_end + }; + + now = GNUNET_TIME_relative_to_absolute (delay); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Trying to claim shard (%llu-%llu]\n", + (unsigned long long) *start_row, + (unsigned long long) *end_row); + + PREPARE (pg, + "claim_next_shard", + "INSERT INTO work_shards" + "(job_name" + ",last_attempt" + ",start_row" + ",end_row" + ") VALUES " + "($1, $2, $3, $4);"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "claim_next_shard", + params); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TEH_PG_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TEH_PG_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + /* continued below */ + break; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + /* someone else got this shard already, + try again */ + TEH_PG_rollback (pg); + continue; + } + } /* claim_next_shard */ + + /* commit */ +commit: + { + enum GNUNET_DB_QueryStatus qs; + + qs = TEH_PG_commit (pg); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TEH_PG_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TEH_PG_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + } + } /* retry 'for' loop */ + return GNUNET_DB_STATUS_SOFT_ERROR; +} diff --git a/src/exchangedb/pg_begin_shard.h b/src/exchangedb/pg_begin_shard.h new file mode 100644 index 000000000..39bd834e9 --- /dev/null +++ b/src/exchangedb/pg_begin_shard.h @@ -0,0 +1,47 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_begin_shard.h + * @brief implementation of the begin_shard function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_BEGIN_SHARD_H +#define PG_BEGIN_SHARD_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Function called to grab a work shard on an operation @a op. Runs in its + * own transaction. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param job_name name of the operation to grab a word shard for + * @param delay minimum age of a shard to grab + * @param shard_size desired shard size + * @param[out] start_row inclusive start row of the shard (returned) + * @param[out] end_row exclusive end row of the shard (returned) + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_begin_shard (void *cls, + const char *job_name, + struct GNUNET_TIME_Relative delay, + uint64_t shard_size, + uint64_t *start_row, + uint64_t *end_row); + +#endif diff --git a/src/exchangedb/pg_complete_shard.c b/src/exchangedb/pg_complete_shard.c new file mode 100644 index 000000000..5efea7c03 --- /dev/null +++ b/src/exchangedb/pg_complete_shard.c @@ -0,0 +1,59 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_complete_shard.c + * @brief Implementation of the complete_shard function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_complete_shard.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_complete_shard (void *cls, + const char *job_name, + uint64_t start_row, + uint64_t end_row) +{ + struct PostgresClosure *pg = cls; + + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_uint64 (&start_row), + GNUNET_PQ_query_param_uint64 (&end_row), + GNUNET_PQ_query_param_end + }; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Completing shard %llu-%llu\n", + (unsigned long long) start_row, + (unsigned long long) end_row); + + + PREPARE (pg, + "complete_shard", + "UPDATE work_shards" + " SET completed=TRUE" + " WHERE job_name=$1" + " AND start_row=$2" + " AND end_row=$3"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "complete_shard", + params); +} diff --git a/src/exchangedb/pg_complete_shard.h b/src/exchangedb/pg_complete_shard.h new file mode 100644 index 000000000..8693f402e --- /dev/null +++ b/src/exchangedb/pg_complete_shard.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_complete_shard.h + * @brief implementation of the complete_shard function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_COMPLETE_SHARD_H +#define PG_COMPLETE_SHARD_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to persist that work on a shard was completed. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param job_name name of the operation to grab a word shard for + * @param start_row inclusive start row of the shard + * @param end_row exclusive end row of the shard + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_complete_shard (void *cls, + const char *job_name, + uint64_t start_row, + uint64_t end_row); +#endif diff --git a/src/exchangedb/pg_compute_shard.c b/src/exchangedb/pg_compute_shard.c new file mode 100644 index 000000000..1dea591f1 --- /dev/null +++ b/src/exchangedb/pg_compute_shard.c @@ -0,0 +1,49 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_compute_shard.c + * @brief Implementation of the compute_shard function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_compute_shard.h" +#include "pg_helper.h" + + +uint64_t +TEH_PG_compute_shard (const struct TALER_MerchantPublicKeyP *merchant_pub) +{ + uint32_t res; + + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (&res, + sizeof (res), + merchant_pub, + sizeof (*merchant_pub), + "VOID", + 4, + NULL, 0)); + /* interpret hash result as NBO for platform independence, + convert to HBO and map to [0..2^31-1] range */ + res = ntohl (res); + if (res > INT32_MAX) + res += INT32_MIN; + GNUNET_assert (res <= INT32_MAX); + return (uint64_t) res; +} diff --git a/src/exchangedb/pg_compute_shard.h b/src/exchangedb/pg_compute_shard.h new file mode 100644 index 000000000..d9bde2d3e --- /dev/null +++ b/src/exchangedb/pg_compute_shard.h @@ -0,0 +1,39 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_compute_shard.h + * @brief implementation of the compute_shard function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_COMPUTE_SHARD_H +#define PG_COMPUTE_SHARD_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + + +/** + * Compute the shard number of a given @a merchant_pub. + * + * @param merchant_pub merchant public key to compute shard for + * @return shard number + */ +uint64_t +TEH_PG_compute_shard (const struct TALER_MerchantPublicKeyP *merchant_pub); + + +#endif diff --git a/src/exchangedb/pg_count_known_coins.c b/src/exchangedb/pg_count_known_coins.c new file mode 100644 index 000000000..28c4612fc --- /dev/null +++ b/src/exchangedb/pg_count_known_coins.c @@ -0,0 +1,63 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_count_known_coins.c + * @brief Implementation of the count_known_coins function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_count_known_coins.h" +#include "pg_helper.h" + +long long +TEH_PG_count_known_coins (void *cls, + const struct + TALER_DenominationHashP *denom_pub_hash) +{ + struct PostgresClosure *pg = cls; + uint64_t count; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("count", + &count), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + + PREPARE (pg, + "count_known_coins", + "SELECT" + " COUNT(*) AS count" + " FROM known_coins" + " WHERE denominations_serial=" + " (SELECT denominations_serial" + " FROM denominations" + " WHERE denom_pub_hash=$1);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "count_known_coins", + params, + rs); + if (0 > qs) + return (long long) qs; + return (long long) count; +} diff --git a/src/exchangedb/pg_count_known_coins.h b/src/exchangedb/pg_count_known_coins.h new file mode 100644 index 000000000..f5dd4f27f --- /dev/null +++ b/src/exchangedb/pg_count_known_coins.h @@ -0,0 +1,39 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_count_known_coins.h + * @brief implementation of the count_known_coins function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_COUNT_KNOWN_COINS_H +#define PG_COUNT_KNOWN_COINS_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Count the number of known coins by denomination. + * + * @param cls database connection plugin state + * @param denom_pub_hash denomination to count by + * @return number of coins if non-negative, otherwise an `enum GNUNET_DB_QueryStatus` + */ +long long +TEH_PG_count_known_coins (void *cls, + const struct + TALER_DenominationHashP *denom_pub_hash); + +#endif diff --git a/src/exchangedb/pg_create_aggregation_transient.c b/src/exchangedb/pg_create_aggregation_transient.c new file mode 100644 index 000000000..4ced9da04 --- /dev/null +++ b/src/exchangedb/pg_create_aggregation_transient.c @@ -0,0 +1,64 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_create_aggregation_transient.c + * @brief Implementation of the create_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_create_aggregation_transient.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_create_aggregation_transient ( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *exchange_account_section, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, + const struct TALER_Amount *total) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + TALER_PQ_query_param_amount (total), + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_uint64 (&kyc_requirement_row), + GNUNET_PQ_query_param_string (exchange_account_section), + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_end + }; + /* Used in #postgres_create_aggregation_transient() */ + PREPARE (pg, + "create_aggregation_transient", + "INSERT INTO aggregation_transient" + " (amount_val" + " ,amount_frac" + " ,merchant_pub" + " ,wire_target_h_payto" + " ,legitimization_requirement_serial_id" + " ,exchange_account_section" + " ,wtid_raw)" + " VALUES ($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "create_aggregation_transient", + params); +} diff --git a/src/exchangedb/pg_create_aggregation_transient.h b/src/exchangedb/pg_create_aggregation_transient.h new file mode 100644 index 000000000..2f0a348b2 --- /dev/null +++ b/src/exchangedb/pg_create_aggregation_transient.h @@ -0,0 +1,49 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_create_aggregation_transient.h + * @brief implementation of the create_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_CREATE_AGGREGATION_TRANSIENT_H +#define PG_CREATE_AGGREGATION_TRANSIENT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Create a new entry in the transient aggregation table. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto destination of the wire transfer + * @param exchange_account_section exchange account to use + * @param merchant_pub public key of the merchant receiving the transfer + * @param wtid the raw wire transfer identifier to be used + * @param kyc_requirement_row row in legitimization_requirements that need to be satisfied to continue, or 0 for none + * @param total amount to be wired in the future + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_create_aggregation_transient ( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *exchange_account_section, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, + const struct TALER_Amount *total); + +#endif diff --git a/src/exchangedb/pg_create_tables.c b/src/exchangedb/pg_create_tables.c new file mode 100644 index 000000000..63211cf52 --- /dev/null +++ b/src/exchangedb/pg_create_tables.c @@ -0,0 +1,47 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_create_tables.c + * @brief Implementation of the create_tables function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_create_tables.h" +#include "pg_helper.h" + + +enum GNUNET_GenericReturnValue +TEH_PG_create_tables (void *cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_Context *conn; + enum GNUNET_GenericReturnValue ret; + + conn = GNUNET_PQ_connect_with_cfg (pg->cfg, + "exchangedb-postgres", + "exchange-", + NULL, + NULL); + if (NULL == conn) + return GNUNET_SYSERR; + ret = GNUNET_PQ_exec_sql (conn, + "procedures"); + GNUNET_PQ_disconnect (conn); + return ret; +} diff --git a/src/exchangedb/pg_create_tables.h b/src/exchangedb/pg_create_tables.h new file mode 100644 index 000000000..7fb7a56fa --- /dev/null +++ b/src/exchangedb/pg_create_tables.h @@ -0,0 +1,37 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_create_tables.h + * @brief implementation of the create_tables function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_CREATE_TABLES_H +#define PG_CREATE_TABLES_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Create the necessary tables if they are not present + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + */ +enum GNUNET_GenericReturnValue +TEH_PG_create_tables (void *cls); + +#endif diff --git a/src/exchangedb/pg_delete_shard_locks.c b/src/exchangedb/pg_delete_shard_locks.c new file mode 100644 index 000000000..e55cf25ff --- /dev/null +++ b/src/exchangedb/pg_delete_shard_locks.c @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_delete_shard_locks.c + * @brief Implementation of the delete_shard_locks function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_delete_shard_locks.h" +#include "pg_helper.h" + + +enum GNUNET_GenericReturnValue +TEH_PG_delete_shard_locks (void *cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_execute ("DELETE FROM work_shards;"), + GNUNET_PQ_make_execute ("DELETE FROM revolving_work_shards;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + return GNUNET_PQ_exec_statements (pg->conn, + es); +} + diff --git a/src/exchangedb/pg_delete_shard_locks.h b/src/exchangedb/pg_delete_shard_locks.h new file mode 100644 index 000000000..e8df2d67d --- /dev/null +++ b/src/exchangedb/pg_delete_shard_locks.h @@ -0,0 +1,38 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_delete_shard_locks.h + * @brief implementation of the delete_shard_locks function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_DELETE_SHARD_LOCKS_H +#define PG_DELETE_SHARD_LOCKS_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Function called to delete all revolving shards. + * To be used after a crash or when the shard size is + * changed. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @return transaction status code + */ +enum GNUNET_GenericReturnValue +TEH_PG_delete_shard_locks (void *cls); + +#endif diff --git a/src/exchangedb/pg_do_batch_withdraw.c b/src/exchangedb/pg_do_batch_withdraw.c new file mode 100644 index 000000000..8ef1be268 --- /dev/null +++ b/src/exchangedb/pg_do_batch_withdraw.c @@ -0,0 +1,78 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_batch_withdraw.c + * @brief Implementation of the do_batch_withdraw function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_do_batch_withdraw.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_do_batch_withdraw ( + void *cls, + struct GNUNET_TIME_Timestamp now, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *amount, + bool *found, + bool *balance_ok, + uint64_t *ruuid) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_TIME_Timestamp gc; + struct GNUNET_PQ_QueryParam params[] = { + TALER_PQ_query_param_amount (amount), + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_timestamp (&now), + GNUNET_PQ_query_param_timestamp (&gc), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("reserve_found", + found), + GNUNET_PQ_result_spec_bool ("balance_ok", + balance_ok), + GNUNET_PQ_result_spec_uint64 ("ruuid", + ruuid), + GNUNET_PQ_result_spec_end + }; + + gc = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add (now.abs_time, + pg->legal_reserve_expiration_time)); + + + /* Used in #postgres_do_batch_withdraw() to + update the reserve balance and check its status */ + PREPARE (pg, + "call_batch_withdraw", + "SELECT " + " reserve_found" + ",balance_ok" + ",ruuid" + " FROM exchange_do_batch_withdraw" + " ($1,$2,$3,$4,$5);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_batch_withdraw", + params, + rs); +} + diff --git a/src/exchangedb/pg_do_batch_withdraw.h b/src/exchangedb/pg_do_batch_withdraw.h new file mode 100644 index 000000000..ee4bf2937 --- /dev/null +++ b/src/exchangedb/pg_do_batch_withdraw.h @@ -0,0 +1,51 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_batch_withdraw.h + * @brief implementation of the do_batch_withdraw function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_DO_BATCH_WITHDRAW_H +#define PG_DO_BATCH_WITHDRAW_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Perform reserve update as part of a batch withdraw operation, checking + * for sufficient balance. Persisting the withdrawal details is done + * separately! + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param now current time (rounded) + * @param reserve_pub public key of the reserve to debit + * @param amount total amount to withdraw + * @param[out] found set to true if the reserve was found + * @param[out] balance_ok set to true if the balance was sufficient + * @param[out] ruuid set to the reserve's UUID (reserves table row) + * @return query execution status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_do_batch_withdraw ( + void *cls, + struct GNUNET_TIME_Timestamp now, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *amount, + bool *found, + bool *balance_ok, + uint64_t *ruuid); + +#endif diff --git a/src/exchangedb/pg_do_deposit.c b/src/exchangedb/pg_do_deposit.c new file mode 100644 index 000000000..c8f25e5bc --- /dev/null +++ b/src/exchangedb/pg_do_deposit.c @@ -0,0 +1,86 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_deposit.c + * @brief Implementation of the do_deposit function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_do_deposit.h" +#include "pg_helper.h" +#include "pg_compute_shard.h" +enum GNUNET_DB_QueryStatus +TEH_PG_do_deposit ( + void *cls, + const struct TALER_EXCHANGEDB_Deposit *deposit, + uint64_t known_coin_id, + const struct TALER_PaytoHashP *h_payto, + uint64_t *policy_details_serial_id, + struct GNUNET_TIME_Timestamp *exchange_timestamp, + bool *balance_ok, + bool *in_conflict) +{ + struct PostgresClosure *pg = cls; + uint64_t deposit_shard = TEH_PG_compute_shard (&deposit->merchant_pub); + struct GNUNET_PQ_QueryParam params[] = { + TALER_PQ_query_param_amount (&deposit->amount_with_fee), + GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms), + GNUNET_PQ_query_param_auto_from_type (&deposit->wire_salt), + GNUNET_PQ_query_param_timestamp (&deposit->timestamp), + GNUNET_PQ_query_param_timestamp (exchange_timestamp), + GNUNET_PQ_query_param_timestamp (&deposit->refund_deadline), + GNUNET_PQ_query_param_timestamp (&deposit->wire_deadline), + GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub), + GNUNET_PQ_query_param_string (deposit->receiver_wire_account), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_uint64 (&known_coin_id), + GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub), + GNUNET_PQ_query_param_auto_from_type (&deposit->csig), + GNUNET_PQ_query_param_uint64 (&deposit_shard), + GNUNET_PQ_query_param_bool (deposit->has_policy), + (NULL == policy_details_serial_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 (policy_details_serial_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("balance_ok", + balance_ok), + GNUNET_PQ_result_spec_bool ("conflicted", + in_conflict), + GNUNET_PQ_result_spec_timestamp ("exchange_timestamp", + exchange_timestamp), + GNUNET_PQ_result_spec_end + }; + + /* Used in #postgres_do_deposit() to execute a deposit, + checking the coin's balance in the process as needed. */ + PREPARE (pg, + "call_deposit", + "SELECT " + " out_exchange_timestamp AS exchange_timestamp" + ",out_balance_ok AS balance_ok" + ",out_conflict AS conflicted" + " FROM exchange_do_deposit" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_deposit", + params, + rs); +} diff --git a/src/exchangedb/pg_do_deposit.h b/src/exchangedb/pg_do_deposit.h new file mode 100644 index 000000000..e71cf0e4b --- /dev/null +++ b/src/exchangedb/pg_do_deposit.h @@ -0,0 +1,52 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_deposit.h + * @brief implementation of the do_deposit function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_DO_DEPOSIT_H +#define PG_DO_DEPOSIT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Perform deposit operation, checking for sufficient balance + * of the coin and possibly persisting the deposit details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param deposit deposit operation details + * @param known_coin_id row of the coin in the known_coins table + * @param h_payto hash of the merchant's bank account details + * @param policy_details_serial_id pointer to the ID of the entry in policy_details, maybe NULL + * @param[in,out] exchange_timestamp time to use for the deposit (possibly updated) + * @param[out] balance_ok set to true if the balance was sufficient + * @param[out] in_conflict set to true if the deposit conflicted + * @return query execution status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_do_deposit ( + void *cls, + const struct TALER_EXCHANGEDB_Deposit *deposit, + uint64_t known_coin_id, + const struct TALER_PaytoHashP *h_payto, + uint64_t *policy_details_serial_id, + struct GNUNET_TIME_Timestamp *exchange_timestamp, + bool *balance_ok, + bool *in_conflict); + +#endif diff --git a/src/exchangedb/pg_do_melt.c b/src/exchangedb/pg_do_melt.c new file mode 100644 index 000000000..6f81ff38b --- /dev/null +++ b/src/exchangedb/pg_do_melt.c @@ -0,0 +1,82 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_melt.c + * @brief Implementation of the do_melt function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_do_melt.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_do_melt ( + void *cls, + const struct TALER_RefreshMasterSecretP *rms, + struct TALER_EXCHANGEDB_Refresh *refresh, + uint64_t known_coin_id, + bool *zombie_required, + bool *balance_ok) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + NULL == rms + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (rms), + TALER_PQ_query_param_amount (&refresh->amount_with_fee), + GNUNET_PQ_query_param_auto_from_type (&refresh->rc), + GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub), + GNUNET_PQ_query_param_auto_from_type (&refresh->coin_sig), + GNUNET_PQ_query_param_uint64 (&known_coin_id), + GNUNET_PQ_query_param_uint32 (&refresh->noreveal_index), + GNUNET_PQ_query_param_bool (*zombie_required), + GNUNET_PQ_query_param_end + }; + bool is_null; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("balance_ok", + balance_ok), + GNUNET_PQ_result_spec_bool ("zombie_required", + zombie_required), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint32 ("noreveal_index", + &refresh->noreveal_index), + &is_null), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + /* Used in #postgres_do_melt() to melt a coin. */ + PREPARE (pg, + "call_melt", + "SELECT " + " out_balance_ok AS balance_ok" + ",out_zombie_bad AS zombie_required" + ",out_noreveal_index AS noreveal_index" + " FROM exchange_do_melt" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_melt", + params, + rs); + if (is_null) + refresh->noreveal_index = UINT32_MAX; /* set to very invalid value */ + return qs; +} diff --git a/src/exchangedb/pg_do_melt.h b/src/exchangedb/pg_do_melt.h new file mode 100644 index 000000000..554ce08b2 --- /dev/null +++ b/src/exchangedb/pg_do_melt.h @@ -0,0 +1,49 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_melt.h + * @brief implementation of the do_melt function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_DO_MELT_H +#define PG_DO_MELT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Perform melt operation, checking for sufficient balance + * of the coin and possibly persisting the melt details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param rms client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals + * @param[in,out] refresh refresh operation details; the noreveal_index + * is set in case the coin was already melted before + * @param known_coin_id row of the coin in the known_coins table + * @param[in,out] zombie_required true if the melt must only succeed if the coin is a zombie, set to false if the requirement was satisfied + * @param[out] balance_ok set to true if the balance was sufficient + * @return query execution status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_do_melt ( + void *cls, + const struct TALER_RefreshMasterSecretP *rms, + struct TALER_EXCHANGEDB_Refresh *refresh, + uint64_t known_coin_id, + bool *zombie_required, + bool *balance_ok); + +#endif diff --git a/src/exchangedb/pg_do_recoup.c b/src/exchangedb/pg_do_recoup.c new file mode 100644 index 000000000..00f7bdd8b --- /dev/null +++ b/src/exchangedb/pg_do_recoup.c @@ -0,0 +1,86 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_recoup.c + * @brief Implementation of the do_recoup function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_do_recoup.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_do_recoup ( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t reserve_out_serial_id, + const union TALER_DenominationBlindingKeyP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, + const struct TALER_CoinSpendSignatureP *coin_sig, + struct GNUNET_TIME_Timestamp *recoup_timestamp, + bool *recoup_ok, + bool *internal_failure) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_TIME_Timestamp reserve_gc + = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time); + struct GNUNET_TIME_Timestamp reserve_expiration + = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_uint64 (&reserve_out_serial_id), + GNUNET_PQ_query_param_auto_from_type (coin_bks), + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_uint64 (&known_coin_id), + GNUNET_PQ_query_param_auto_from_type (coin_sig), + GNUNET_PQ_query_param_timestamp (&reserve_gc), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_timestamp (recoup_timestamp), + GNUNET_PQ_query_param_end + }; + bool is_null; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + recoup_timestamp), + &is_null), + GNUNET_PQ_result_spec_bool ("recoup_ok", + recoup_ok), + GNUNET_PQ_result_spec_bool ("internal_failure", + internal_failure), + GNUNET_PQ_result_spec_end + }; + + + + PREPARE (pg, + "call_recoup", + "SELECT " + " out_recoup_timestamp AS recoup_timestamp" + ",out_recoup_ok AS recoup_ok" + ",out_internal_failure AS internal_failure" + " FROM exchange_do_recoup_to_reserve" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_recoup", + params, + rs); +} diff --git a/src/exchangedb/pg_do_recoup.h b/src/exchangedb/pg_do_recoup.h new file mode 100644 index 000000000..07a350789 --- /dev/null +++ b/src/exchangedb/pg_do_recoup.h @@ -0,0 +1,56 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_recoup.h + * @brief implementation of the do_recoup function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_DO_RECOUP_H +#define PG_DO_RECOUP_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Perform recoup operation, checking for sufficient deposits + * of the coin and possibly persisting the recoup details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param reserve_pub public key of the reserve to credit + * @param reserve_out_serial_id row in the reserves_out table justifying the recoup + * @param coin_bks coin blinding key secret to persist + * @param coin_pub public key of the coin being recouped + * @param known_coin_id row of the @a coin_pub in the known_coins table + * @param coin_sig signature of the coin requesting the recoup + * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed + * @param[out] recoup_ok set if the recoup succeeded (balance ok) + * @param[out] internal_failure set on internal failures + * @return query execution status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_do_recoup ( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t reserve_out_serial_id, + const union TALER_DenominationBlindingKeyP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, + const struct TALER_CoinSpendSignatureP *coin_sig, + struct GNUNET_TIME_Timestamp *recoup_timestamp, + bool *recoup_ok, + bool *internal_failure); + +#endif diff --git a/src/exchangedb/pg_do_recoup_refresh.c b/src/exchangedb/pg_do_recoup_refresh.c new file mode 100644 index 000000000..be5e4705d --- /dev/null +++ b/src/exchangedb/pg_do_recoup_refresh.c @@ -0,0 +1,79 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_recoup_refresh.c + * @brief Implementation of the do_recoup_refresh function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_do_recoup_refresh.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_do_recoup_refresh ( + void *cls, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + uint64_t rrc_serial, + const union TALER_DenominationBlindingKeyP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, + const struct TALER_CoinSpendSignatureP *coin_sig, + struct GNUNET_TIME_Timestamp *recoup_timestamp, + bool *recoup_ok, + bool *internal_failure) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (old_coin_pub), + GNUNET_PQ_query_param_uint64 (&rrc_serial), + GNUNET_PQ_query_param_auto_from_type (coin_bks), + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_uint64 (&known_coin_id), + GNUNET_PQ_query_param_auto_from_type (coin_sig), + GNUNET_PQ_query_param_timestamp (recoup_timestamp), + GNUNET_PQ_query_param_end + }; + bool is_null; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + recoup_timestamp), + &is_null), + GNUNET_PQ_result_spec_bool ("recoup_ok", + recoup_ok), + GNUNET_PQ_result_spec_bool ("internal_failure", + internal_failure), + GNUNET_PQ_result_spec_end + }; + + + PREPARE (pg, + "call_recoup_refresh", + "SELECT " + " out_recoup_timestamp AS recoup_timestamp" + ",out_recoup_ok AS recoup_ok" + ",out_internal_failure AS internal_failure" + " FROM exchange_do_recoup_to_coin" + " ($1,$2,$3,$4,$5,$6,$7);"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_recoup_refresh", + params, + rs); +} diff --git a/src/exchangedb/pg_do_recoup_refresh.h b/src/exchangedb/pg_do_recoup_refresh.h new file mode 100644 index 000000000..3ac0f0a07 --- /dev/null +++ b/src/exchangedb/pg_do_recoup_refresh.h @@ -0,0 +1,56 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_recoup_refresh.h + * @brief implementation of the do_recoup_refresh function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_DO_RECOUP_REFRESH_H +#define PG_DO_RECOUP_REFRESH_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Perform recoup-refresh operation, checking for sufficient deposits of the + * coin and possibly persisting the recoup-refresh details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param old_coin_pub public key of the old coin to credit + * @param rrc_serial row in the refresh_revealed_coins table justifying the recoup-refresh + * @param coin_bks coin blinding key secret to persist + * @param coin_pub public key of the coin being recouped + * @param known_coin_id row of the @a coin_pub in the known_coins table + * @param coin_sig signature of the coin requesting the recoup + * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed + * @param[out] recoup_ok set if the recoup-refresh succeeded (balance ok) + * @param[out] internal_failure set on internal failures + * @return query execution status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_do_recoup_refresh ( + void *cls, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + uint64_t rrc_serial, + const union TALER_DenominationBlindingKeyP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, + const struct TALER_CoinSpendSignatureP *coin_sig, + struct GNUNET_TIME_Timestamp *recoup_timestamp, + bool *recoup_ok, + bool *internal_failure); +#endif diff --git a/src/exchangedb/pg_do_refund.c b/src/exchangedb/pg_do_refund.c new file mode 100644 index 000000000..1059f9cbb --- /dev/null +++ b/src/exchangedb/pg_do_refund.c @@ -0,0 +1,90 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_refund.c + * @brief Implementation of the do_refund function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_do_refund.h" +#include "pg_helper.h" +#include "pg_compute_shard.h" +enum GNUNET_DB_QueryStatus +TEH_PG_do_refund ( + void *cls, + const struct TALER_EXCHANGEDB_Refund *refund, + const struct TALER_Amount *deposit_fee, + uint64_t known_coin_id, + bool *not_found, + bool *refund_ok, + bool *gone, + bool *conflict) +{ + struct PostgresClosure *pg = cls; + uint64_t deposit_shard = TEH_PG_compute_shard (&refund->details.merchant_pub); + struct TALER_Amount amount_without_fee; + struct GNUNET_PQ_QueryParam params[] = { + TALER_PQ_query_param_amount (&refund->details.refund_amount), + TALER_PQ_query_param_amount (&amount_without_fee), + TALER_PQ_query_param_amount (deposit_fee), + GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms), + GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id), + GNUNET_PQ_query_param_uint64 (&deposit_shard), + GNUNET_PQ_query_param_uint64 (&known_coin_id), + GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub), + GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub), + GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("not_found", + not_found), + GNUNET_PQ_result_spec_bool ("refund_ok", + refund_ok), + GNUNET_PQ_result_spec_bool ("gone", + gone), + GNUNET_PQ_result_spec_bool ("conflict", + conflict), + GNUNET_PQ_result_spec_end + }; + + if (0 > + TALER_amount_subtract (&amount_without_fee, + &refund->details.refund_amount, + &refund->details.refund_fee)) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + /* Used in #postgres_do_refund() to refund a deposit. */ + PREPARE (pg, + "call_refund", + "SELECT " + " out_not_found AS not_found" + ",out_refund_ok AS refund_ok" + ",out_gone AS gone" + ",out_conflict AS conflict" + " FROM exchange_do_refund" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13);"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_refund", + params, + rs); +} diff --git a/src/exchangedb/pg_do_refund.h b/src/exchangedb/pg_do_refund.h new file mode 100644 index 000000000..7118858dc --- /dev/null +++ b/src/exchangedb/pg_do_refund.h @@ -0,0 +1,52 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_do_refund.h + * @brief implementation of the do_refund function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_DO_REFUND_H +#define PG_DO_REFUND_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Perform refund operation, checking for sufficient deposits + * of the coin and possibly persisting the refund details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param refund refund operation details + * @param deposit_fee deposit fee applicable for the coin, possibly refunded + * @param known_coin_id row of the coin in the known_coins table + * @param[out] not_found set if the deposit was not found + * @param[out] refund_ok set if the refund succeeded (below deposit amount) + * @param[out] gone if the merchant was already paid + * @param[out] conflict set if the refund ID was re-used + * @return query execution status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_do_refund ( + void *cls, + const struct TALER_EXCHANGEDB_Refund *refund, + const struct TALER_Amount *deposit_fee, + uint64_t known_coin_id, + bool *not_found, + bool *refund_ok, + bool *gone, + bool *conflict); + +#endif diff --git a/src/exchangedb/pg_drain_kyc_alert.c b/src/exchangedb/pg_drain_kyc_alert.c new file mode 100644 index 000000000..d635d95e9 --- /dev/null +++ b/src/exchangedb/pg_drain_kyc_alert.c @@ -0,0 +1,59 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_drain_kyc_alert.c + * @brief Implementation of the drain_kyc_alert function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_drain_kyc_alert.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_drain_kyc_alert (void *cls, + uint32_t trigger_type, + struct TALER_PaytoHashP *h_payto) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint32 (&trigger_type), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("h_payto", + h_payto), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "drain_kyc_alert", + "DELETE FROM kyc_alerts" + " WHERE trigger_type=$1" + " AND h_payto = " + " (SELECT h_payto " + " FROM kyc_alerts" + " WHERE trigger_type=$1" + " LIMIT 1)" + " RETURNING h_payto;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "drain_kyc_alert", + params, + rs); +} diff --git a/src/exchangedb/pg_drain_kyc_alert.h b/src/exchangedb/pg_drain_kyc_alert.h new file mode 100644 index 000000000..bfaf04892 --- /dev/null +++ b/src/exchangedb/pg_drain_kyc_alert.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_drain_kyc_alert.h + * @brief implementation of the drain_kyc_alert function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_DRAIN_KYC_ALERT_H +#define PG_DRAIN_KYC_ALERT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Extract next KYC alert. Deletes the alert. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param trigger_type which type of alert to drain + * @param[out] h_payto set to hash of payto-URI where KYC status changed + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_drain_kyc_alert (void *cls, + uint32_t trigger_type, + struct TALER_PaytoHashP *h_payto); + +#endif diff --git a/src/exchangedb/pg_ensure_coin_known.c b/src/exchangedb/pg_ensure_coin_known.c new file mode 100644 index 000000000..6b2385adb --- /dev/null +++ b/src/exchangedb/pg_ensure_coin_known.c @@ -0,0 +1,159 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_ensure_coin_known.c + * @brief Implementation of the ensure_coin_known function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_ensure_coin_known.h" +#include "pg_helper.h" + + +enum TALER_EXCHANGEDB_CoinKnownStatus +TEH_PG_ensure_coin_known (void *cls, + const struct TALER_CoinPublicInfo *coin, + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_hash, + struct TALER_AgeCommitmentHash *h_age_commitment) +{ + struct PostgresClosure *pg = cls; + enum GNUNET_DB_QueryStatus qs; + bool existed; + bool is_denom_pub_hash_null = false; + bool is_age_hash_null = false; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin->denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin->h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin->denom_sig), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("existed", + &existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + denom_hash), + &is_denom_pub_hash_null), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + h_age_commitment), + &is_age_hash_null), + GNUNET_PQ_result_spec_end + }; + /* Used in #postgres_insert_known_coin() to store the denomination public + key and signature for a coin known to the exchange. + + See also: + https://stackoverflow.com/questions/34708509/how-to-use-returning-with-on-conflict-in-postgresql/37543015#37543015 + */ + PREPARE (pg, + "insert_known_coin", + "WITH dd" + " (denominations_serial" + " ,coin_val" + " ,coin_frac" + " ) AS (" + " SELECT " + " denominations_serial" + " ,coin_val" + " ,coin_frac" + " FROM denominations" + " WHERE denom_pub_hash=$2" + " ), input_rows" + " (coin_pub) AS (" + " VALUES ($1::BYTEA)" + " ), ins AS (" + " INSERT INTO known_coins " + " (coin_pub" + " ,denominations_serial" + " ,age_commitment_hash" + " ,denom_sig" + " ,remaining_val" + " ,remaining_frac" + " ) SELECT " + " $1" + " ,denominations_serial" + " ,$3" + " ,$4" + " ,coin_val" + " ,coin_frac" + " FROM dd" + " ON CONFLICT DO NOTHING" /* CONFLICT on (coin_pub) */ + " RETURNING " + " known_coin_id" + " ) " + "SELECT " + " FALSE AS existed" + " ,known_coin_id" + " ,NULL AS denom_pub_hash" + " ,NULL AS age_commitment_hash" + " FROM ins " + "UNION ALL " + "SELECT " + " TRUE AS existed" + " ,known_coin_id" + " ,denom_pub_hash" + " ,kc.age_commitment_hash" + " FROM input_rows" + " JOIN known_coins kc USING (coin_pub)" + " JOIN denominations USING (denominations_serial)" + " LIMIT 1"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "insert_known_coin", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return TALER_EXCHANGEDB_CKS_HARD_FAIL; + case GNUNET_DB_STATUS_SOFT_ERROR: + return TALER_EXCHANGEDB_CKS_SOFT_FAIL; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); /* should be impossible */ + return TALER_EXCHANGEDB_CKS_HARD_FAIL; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + if (! existed) + return TALER_EXCHANGEDB_CKS_ADDED; + break; /* continued below */ + } + + if ( (! is_denom_pub_hash_null) && + (0 != GNUNET_memcmp (&denom_hash->hash, + &coin->denom_pub_hash.hash)) ) + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + } + + if ( (! is_age_hash_null) && + (0 != GNUNET_memcmp (h_age_commitment, + &coin->h_age_commitment)) ) + { + GNUNET_break (GNUNET_is_zero (h_age_commitment)); + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + } + + return TALER_EXCHANGEDB_CKS_PRESENT; +} diff --git a/src/exchangedb/pg_ensure_coin_known.h b/src/exchangedb/pg_ensure_coin_known.h new file mode 100644 index 000000000..76581d4b7 --- /dev/null +++ b/src/exchangedb/pg_ensure_coin_known.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_ensure_coin_known.h + * @brief implementation of the ensure_coin_known function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_ENSURE_COIN_KNOWN_H +#define PG_ENSURE_COIN_KNOWN_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Make sure the given @a coin is known to the database. + * + * @param cls database connection plugin state + * @param coin the coin that must be made known + * @param[out] known_coin_id set to the unique row of the coin + * @param[out] denom_hash set to the denomination hash of the existing + * coin (for conflict error reporting) + * @param[out] h_age_commitment set to the conflicting age commitment hash on conflict + * @return database transaction status, non-negative on success + */ +enum TALER_EXCHANGEDB_CoinKnownStatus +TEH_PG_ensure_coin_known (void *cls, + const struct TALER_CoinPublicInfo *coin, + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_hash, + struct TALER_AgeCommitmentHash *h_age_commitment); + +#endif diff --git a/src/exchangedb/pg_event_listen.c b/src/exchangedb/pg_event_listen.c new file mode 100644 index 000000000..c557ed3c5 --- /dev/null +++ b/src/exchangedb/pg_event_listen.c @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_event_listen.c + * @brief Implementation of the event_listen function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_event_listen.h" +#include "pg_helper.h" + +/** + * Register callback to be invoked on events of type @a es. + * + * @param cls database context to use + * @param timeout how long until to generate a timeout event + * @param es specification of the event to listen for + * @param cb function to call when the event happens, possibly + * multiple times (until cancel is invoked) + * @param cb_cls closure for @a cb + * @return handle useful to cancel the listener + */ +struct GNUNET_DB_EventHandler * +TEH_PG_event_listen (void *cls, + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_DB_EventHeaderP *es, + GNUNET_DB_EventCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + + return GNUNET_PQ_event_listen (pg->conn, + es, + timeout, + cb, + cb_cls); +} diff --git a/src/exchangedb/pg_event_listen.h b/src/exchangedb/pg_event_listen.h new file mode 100644 index 000000000..1be140776 --- /dev/null +++ b/src/exchangedb/pg_event_listen.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_event_listen.h + * @brief implementation of the event_listen function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_EVENT_LISTEN_H +#define PG_EVENT_LISTEN_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Register callback to be invoked on events of type @a es. + * + * @param cls database context to use + * @param timeout how long until to generate a timeout event + * @param es specification of the event to listen for + * @param cb function to call when the event happens, possibly + * multiple times (until cancel is invoked) + * @param cb_cls closure for @a cb + * @return handle useful to cancel the listener + */ +struct GNUNET_DB_EventHandler * +TEH_PG_event_listen (void *cls, + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_DB_EventHeaderP *es, + GNUNET_DB_EventCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_event_listen_cancel.c b/src/exchangedb/pg_event_listen_cancel.c new file mode 100644 index 000000000..5d65827c2 --- /dev/null +++ b/src/exchangedb/pg_event_listen_cancel.c @@ -0,0 +1,37 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_event_listen_cancel.c + * @brief Implementation of the event_listen_cancel function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_event_listen_cancel.h" +#include "pg_helper.h" + + + +void +TEH_PG_event_listen_cancel (void *cls, + struct GNUNET_DB_EventHandler *eh) + +{ + (void) cls; + GNUNET_PQ_event_listen_cancel (eh); +} diff --git a/src/exchangedb/pg_event_listen_cancel.h b/src/exchangedb/pg_event_listen_cancel.h new file mode 100644 index 000000000..258d7a58b --- /dev/null +++ b/src/exchangedb/pg_event_listen_cancel.h @@ -0,0 +1,38 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_event_listen_cancel.h + * @brief implementation of the event_listen_cancel function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_EVENT_LISTEN_CANCEL_H +#define PG_EVENT_LISTEN_CANCEL_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + + +/** + * Stop notifications. + * + * @param cls the plugin's `struct PostgresClosure` + * @param eh handle to unregister. + */ +void +TEH_PG_event_listen_cancel (void *cls, + struct GNUNET_DB_EventHandler *eh); +#endif diff --git a/src/exchangedb/pg_event_notify.c b/src/exchangedb/pg_event_notify.c new file mode 100644 index 000000000..577f4acb8 --- /dev/null +++ b/src/exchangedb/pg_event_notify.c @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_event_notify.c + * @brief Implementation of the event_notify function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_event_notify.h" +#include "pg_helper.h" + + +void +TEH_PG_event_notify (void *cls, + const struct GNUNET_DB_EventHeaderP *es, + const void *extra, + size_t extra_size) +{ + struct PostgresClosure *pg = cls; + + GNUNET_PQ_event_notify (pg->conn, + es, + extra, + extra_size); +} diff --git a/src/exchangedb/pg_event_notify.h b/src/exchangedb/pg_event_notify.h new file mode 100644 index 000000000..3b937cbab --- /dev/null +++ b/src/exchangedb/pg_event_notify.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_event_notify.h + * @brief implementation of the event_notify function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_EVENT_NOTIFY_H +#define PG_EVENT_NOTIFY_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Notify all that listen on @a es of an event. + * + * @param cls database context to use + * @param es specification of the event to generate + * @param extra additional event data provided + * @param extra_size number of bytes in @a extra + */ +void +TEH_PG_event_notify (void *cls, + const struct GNUNET_DB_EventHeaderP *es, + const void *extra, + size_t extra_size); + +#endif diff --git a/src/exchangedb/pg_expire_purse.c b/src/exchangedb/pg_expire_purse.c new file mode 100644 index 000000000..6ef7a2779 --- /dev/null +++ b/src/exchangedb/pg_expire_purse.c @@ -0,0 +1,69 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_expire_purse.c + * @brief Implementation of the expire_purse function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_expire_purse.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_expire_purse ( + void *cls, + struct GNUNET_TIME_Absolute start_time, + struct GNUNET_TIME_Absolute end_time) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_absolute_time (&start_time), + GNUNET_PQ_query_param_absolute_time (&end_time), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + bool found = false; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("found", + &found), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + + PREPARE (pg, + "call_expire_purse", + "SELECT " + " out_found AS found" + " FROM exchange_do_expire_purse" + " ($1,$2,$3);"); + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_expire_purse", + params, + rs); + if (qs < 0) + return qs; + GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); + return found + ? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT + : GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; +} diff --git a/src/exchangedb/pg_expire_purse.h b/src/exchangedb/pg_expire_purse.h new file mode 100644 index 000000000..fe05fd52c --- /dev/null +++ b/src/exchangedb/pg_expire_purse.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_expire_purse.h + * @brief implementation of the expire_purse function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_EXPIRE_PURSE_H +#define PG_EXPIRE_PURSE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Function called to clean up one expired purse. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param start_time select purse expired after this time + * @param end_time select purse expired before this time + * @return transaction status code (#GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no purse expired in the given time interval). + */ +enum GNUNET_DB_QueryStatus +TEH_PG_expire_purse ( + void *cls, + struct GNUNET_TIME_Absolute start_time, + struct GNUNET_TIME_Absolute end_time); + +#endif diff --git a/src/exchangedb/pg_find_aggregation_transient.c b/src/exchangedb/pg_find_aggregation_transient.c new file mode 100644 index 000000000..a5f367b5f --- /dev/null +++ b/src/exchangedb/pg_find_aggregation_transient.c @@ -0,0 +1,151 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_find_aggregation_transient.c + * @brief Implementation of the find_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_find_aggregation_transient.h" +#include "pg_helper.h" + + +/** + * Closure for #get_refunds_cb(). + */ +struct FindAggregationTransientContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_TransientAggregationCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Set to #GNUNET_SYSERR on error. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct SelectRefundContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +get_transients_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct FindAggregationTransientContext *srctx = cls; + struct PostgresClosure *pg = srctx->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + cont = srctx->cb (srctx->cb_cls, + payto_uri, + &wtid, + &merchant_pub, + &amount); + GNUNET_free (payto_uri); + if (! cont) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_find_aggregation_transient ( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_TransientAggregationCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_end + }; + struct FindAggregationTransientContext srctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + /* Used in #postgres_find_aggregation_transient() */ + PREPARE (pg, + "find_transient_aggregations", + "SELECT" + " amount_val" + " ,amount_frac" + " ,wtid_raw" + " ,merchant_pub" + " ,payto_uri" + " FROM aggregation_transient atr" + " JOIN wire_targets wt USING (wire_target_h_payto)" + " WHERE atr.wire_target_h_payto=$1;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "find_transient_aggregations", + params, + &get_transients_cb, + &srctx); + if (GNUNET_SYSERR == srctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_find_aggregation_transient.h b/src/exchangedb/pg_find_aggregation_transient.h new file mode 100644 index 000000000..c7ba4ea38 --- /dev/null +++ b/src/exchangedb/pg_find_aggregation_transient.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_find_aggregation_transient.h + * @brief implementation of the find_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_FIND_AGGREGATION_TRANSIENT_H +#define PG_FIND_AGGREGATION_TRANSIENT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Find existing entry in the transient aggregation table. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto destination of the wire transfer + * @param cb function to call on each matching entry + * @param cb_cls closure for @a cb + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_find_aggregation_transient ( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_TransientAggregationCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_gc.c b/src/exchangedb/pg_gc.c new file mode 100644 index 000000000..e01c1e101 --- /dev/null +++ b/src/exchangedb/pg_gc.c @@ -0,0 +1,80 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_gc.c + * @brief Implementation of the gc function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_gc.h" +#include "pg_helper.h" + + +enum GNUNET_GenericReturnValue +TEH_PG_gc (void *cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); + struct GNUNET_TIME_Absolute long_ago; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_absolute_time (&long_ago), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_Context *conn; + enum GNUNET_GenericReturnValue ret; + + /* Keep wire fees for 10 years, that should always + be enough _and_ they are tiny so it does not + matter to make this tight */ + long_ago = GNUNET_TIME_absolute_subtract ( + now, + GNUNET_TIME_relative_multiply ( + GNUNET_TIME_UNIT_YEARS, + 10)); + { + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + struct GNUNET_PQ_PreparedStatement ps[] = { + /* Used in #postgres_gc() */ + GNUNET_PQ_make_prepare ("run_gc", + "CALL" + " exchange_do_gc" + " ($1,$2);"), + GNUNET_PQ_PREPARED_STATEMENT_END + }; + + conn = GNUNET_PQ_connect_with_cfg (pg->cfg, + "exchangedb-postgres", + NULL, + es, + ps); + } + if (NULL == conn) + return GNUNET_SYSERR; + ret = GNUNET_OK; + if (0 > GNUNET_PQ_eval_prepared_non_select (conn, + "run_gc", + params)) + ret = GNUNET_SYSERR; + GNUNET_PQ_disconnect (conn); + return ret; +} diff --git a/src/exchangedb/pg_gc.h b/src/exchangedb/pg_gc.h new file mode 100644 index 000000000..9e6ffbc3d --- /dev/null +++ b/src/exchangedb/pg_gc.h @@ -0,0 +1,38 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_gc.h + * @brief implementation of the gc function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GC_H +#define PG_GC_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to perform "garbage collection" on the + * database, expiring records we no longer require. + * + * @param cls closure + * @return #GNUNET_OK on success, + * #GNUNET_SYSERR on DB errors + */ +enum GNUNET_GenericReturnValue +TEH_PG_gc (void *cls); +#endif diff --git a/src/exchangedb/pg_get_coin_denomination.c b/src/exchangedb/pg_get_coin_denomination.c new file mode 100644 index 000000000..e82b86aa9 --- /dev/null +++ b/src/exchangedb/pg_get_coin_denomination.c @@ -0,0 +1,71 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_coin_denomination.c + * @brief Implementation of the get_coin_denomination function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_coin_denomination.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_get_coin_denomination ( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_hash) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + denom_hash), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + known_coin_id), + GNUNET_PQ_result_spec_end + }; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Getting coin denomination of coin %s\n", + TALER_B2S (coin_pub)); + + /* Used in #postgres_get_coin_denomination() to fetch + the denomination public key hash for + a coin known to the exchange. */ + PREPARE (pg, + "get_coin_denomination", + "SELECT" + " denominations.denom_pub_hash" + ",known_coin_id" + " FROM known_coins" + " JOIN denominations USING (denominations_serial)" + " WHERE coin_pub=$1" + " FOR SHARE;"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_coin_denomination", + params, + rs); +} + + diff --git a/src/exchangedb/pg_get_coin_denomination.h b/src/exchangedb/pg_get_coin_denomination.h new file mode 100644 index 000000000..3b9f03f31 --- /dev/null +++ b/src/exchangedb/pg_get_coin_denomination.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_coin_denomination.h + * @brief implementation of the get_coin_denomination function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_COIN_DENOMINATION_H +#define PG_GET_COIN_DENOMINATION_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Retrieve the denomination of a known coin. + * + * @param cls the plugin closure + * @param coin_pub the public key of the coin to search for + * @param[out] known_coin_id set to the ID of the coin in the known_coins table + * @param[out] denom_hash where to store the hash of the coins denomination + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_coin_denomination ( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_hash); + +#endif diff --git a/src/exchangedb/pg_get_denomination_info.c b/src/exchangedb/pg_get_denomination_info.c new file mode 100644 index 000000000..97250b621 --- /dev/null +++ b/src/exchangedb/pg_get_denomination_info.c @@ -0,0 +1,99 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_denomination_info.c + * @brief Implementation of the get_denomination_info function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_denomination_info.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_get_denomination_info ( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_EXCHANGEDB_DenominationKeyInformation *issue) +{ + struct PostgresClosure *pg = cls; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &issue->signature), + GNUNET_PQ_result_spec_timestamp ("valid_from", + &issue->start), + GNUNET_PQ_result_spec_timestamp ("expire_withdraw", + &issue->expire_withdraw), + GNUNET_PQ_result_spec_timestamp ("expire_deposit", + &issue->expire_deposit), + GNUNET_PQ_result_spec_timestamp ("expire_legal", + &issue->expire_legal), + TALER_PQ_RESULT_SPEC_AMOUNT ("coin", + &issue->value), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", + &issue->fees.withdraw), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + &issue->fees.deposit), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", + &issue->fees.refresh), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", + &issue->fees.refund), + GNUNET_PQ_result_spec_uint32 ("age_mask", + &issue->age_mask.bits), + GNUNET_PQ_result_spec_end + }; + + + /* Used in #postgres_get_denomination_info() */ + PREPARE (pg, + "denomination_get", + "SELECT" + " master_sig" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin_val" /* value of this denom */ + ",coin_frac" /* fractional value of this denom */ + ",fee_withdraw_val" + ",fee_withdraw_frac" + ",fee_deposit_val" + ",fee_deposit_frac" + ",fee_refresh_val" + ",fee_refresh_frac" + ",fee_refund_val" + ",fee_refund_frac" + ",age_mask" + " FROM denominations" + " WHERE denom_pub_hash=$1;"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "denomination_get", + params, + rs); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) + return qs; + issue->denom_hash = *denom_pub_hash; + return qs; +} + diff --git a/src/exchangedb/pg_get_denomination_info.h b/src/exchangedb/pg_get_denomination_info.h new file mode 100644 index 000000000..843227759 --- /dev/null +++ b/src/exchangedb/pg_get_denomination_info.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_denomination_info.h + * @brief implementation of the get_denomination_info function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_DENOMINATION_INFO_H +#define PG_GET_DENOMINATION_INFO_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Fetch information about a denomination key. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param denom_pub_hash hash of 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 + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_denomination_info ( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_EXCHANGEDB_DenominationKeyInformation *issue); + +#endif diff --git a/src/exchangedb/pg_get_denomination_revocation.c b/src/exchangedb/pg_get_denomination_revocation.c new file mode 100644 index 000000000..4d29d88c4 --- /dev/null +++ b/src/exchangedb/pg_get_denomination_revocation.c @@ -0,0 +1,63 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_denomination_revocation.c + * @brief Implementation of the get_denomination_revocation function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_denomination_revocation.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_get_denomination_revocation ( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_MasterSignatureP *master_sig, + uint64_t *rowid) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), + GNUNET_PQ_result_spec_uint64 ("denom_revocations_serial_id", + rowid), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "denomination_revocation_get", + "SELECT" + " master_sig" + ",denom_revocations_serial_id" + " FROM denomination_revocations" + " WHERE denominations_serial=" + " (SELECT denominations_serial" + " FROM denominations" + " WHERE denom_pub_hash=$1);"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "denomination_revocation_get", + params, + rs); +} diff --git a/src/exchangedb/pg_get_denomination_revocation.h b/src/exchangedb/pg_get_denomination_revocation.h new file mode 100644 index 000000000..d022c822d --- /dev/null +++ b/src/exchangedb/pg_get_denomination_revocation.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_denomination_revocation.h + * @brief implementation of the get_denomination_revocation function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_DENOMINATION_REVOCATION_H +#define PG_GET_DENOMINATION_REVOCATION_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Obtain information about a denomination key's revocation from + * the database. + * + * @param cls closure + * @param denom_pub_hash hash of the revoked denomination key + * @param[out] master_sig signature affirming the revocation + * @param[out] rowid row where the information is stored + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_denomination_revocation ( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_MasterSignatureP *master_sig, + uint64_t *rowid); +#endif diff --git a/src/exchangedb/pg_get_global_fee.c b/src/exchangedb/pg_get_global_fee.c new file mode 100644 index 000000000..6f6bbafef --- /dev/null +++ b/src/exchangedb/pg_get_global_fee.c @@ -0,0 +1,91 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_global_fee.c + * @brief Implementation of the get_global_fee function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_global_fee.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_get_global_fee (void *cls, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative *purse_timeout, + struct GNUNET_TIME_Relative *history_expiration, + uint32_t *purse_account_limit, + struct TALER_MasterSignatureP *master_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&date), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("start_date", + start_date), + GNUNET_PQ_result_spec_timestamp ("end_date", + end_date), + TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee", + &fees->history), + TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee", + &fees->account), + TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", + &fees->purse), + GNUNET_PQ_result_spec_relative_time ("purse_timeout", + purse_timeout), + GNUNET_PQ_result_spec_relative_time ("history_expiration", + history_expiration), + GNUNET_PQ_result_spec_uint32 ("purse_account_limit", + purse_account_limit), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), + GNUNET_PQ_result_spec_end + }; + + + /* Used in #postgres_get_global_fee() */ + PREPARE(pg, + "get_global_fee", + "SELECT " + " start_date" + ",end_date" + ",history_fee_val" + ",history_fee_frac" + ",account_fee_val" + ",account_fee_frac" + ",purse_fee_val" + ",purse_fee_frac" + ",purse_timeout" + ",history_expiration" + ",purse_account_limit" + ",master_sig" + " FROM global_fee" + " WHERE start_date <= $1" + " AND end_date > $1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_global_fee", + params, + rs); +} diff --git a/src/exchangedb/pg_get_global_fee.h b/src/exchangedb/pg_get_global_fee.h new file mode 100644 index 000000000..0887d54d2 --- /dev/null +++ b/src/exchangedb/pg_get_global_fee.h @@ -0,0 +1,52 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_global_fee.h + * @brief implementation of the get_global_fee function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_GLOBAL_FEE_H +#define PG_GET_GLOBAL_FEE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Obtain global fees from database. + * + * @param cls closure + * @param date for which date do we want the fee? + * @param[out] start_date when does the fee go into effect + * @param[out] end_date when does the fee end being valid + * @param[out] fees how high are the wire fees + * @param[out] purse_timeout set to how long we keep unmerged purses + * @param[out] history_expiration set to how long we keep account histories + * @param[out] purse_account_limit set to the number of free purses per account + * @param[out] master_sig signature over the above by the exchange master key + * @return status of the transaction + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_global_fee (void *cls, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative *purse_timeout, + struct GNUNET_TIME_Relative *history_expiration, + uint32_t *purse_account_limit, + struct TALER_MasterSignatureP *master_sig); + +#endif diff --git a/src/exchangedb/pg_get_global_fees.c b/src/exchangedb/pg_get_global_fees.c new file mode 100644 index 000000000..0e1736bd4 --- /dev/null +++ b/src/exchangedb/pg_get_global_fees.c @@ -0,0 +1,175 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_global_fees.c + * @brief Implementation of the get_global_fees function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_global_fees.h" +#include "pg_helper.h" + + +/** + * Closure for #global_fees_cb(). + */ +struct GlobalFeeContext +{ + /** + * Function to call for each global fee block. + */ + TALER_EXCHANGEDB_GlobalFeeCallback cb; + + /** + * Closure to give to @e rec. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Set to #GNUNET_SYSERR on error. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +global_fees_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct GlobalFeeContext *gctx = cls; + struct PostgresClosure *pg = gctx->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + break; + } + gctx->cb (gctx->cb_cls, + &fees, + purse_timeout, + history_expiration, + purse_account_limit, + start_date, + end_date, + &master_sig); + GNUNET_PQ_cleanup_result (rs); + } +} + + + +enum GNUNET_DB_QueryStatus +TEH_PG_get_global_fees (void *cls, + TALER_EXCHANGEDB_GlobalFeeCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_TIME_Timestamp date + = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_subtract ( + GNUNET_TIME_absolute_get (), + GNUNET_TIME_UNIT_YEARS)); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&date), + GNUNET_PQ_query_param_end + }; + struct GlobalFeeContext gctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + + /* Used in #postgres_get_global_fees() */ + PREPARE (pg, + "get_global_fees", + "SELECT " + " start_date" + ",end_date" + ",history_fee_val" + ",history_fee_frac" + ",account_fee_val" + ",account_fee_frac" + ",purse_fee_val" + ",purse_fee_frac" + ",purse_timeout" + ",history_expiration" + ",purse_account_limit" + ",master_sig" + " FROM global_fee" + " WHERE start_date >= $1"); + + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "get_global_fees", + params, + &global_fees_cb, + &gctx); +} + + + + diff --git a/src/exchangedb/pg_get_global_fees.h b/src/exchangedb/pg_get_global_fees.h new file mode 100644 index 000000000..c8f6f02c2 --- /dev/null +++ b/src/exchangedb/pg_get_global_fees.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_global_fees.h + * @brief implementation of the get_global_fees function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_GLOBAL_FEES_H +#define PG_GET_GLOBAL_FEES_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Obtain global fees from database. + * + * @param cls closure + * @param cb function to call on each fee entry + * @param cb_cls closure for @a cb + * @return status of the transaction + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_global_fees (void *cls, + TALER_EXCHANGEDB_GlobalFeeCallback cb, + void *cb_cls); +#endif diff --git a/src/exchangedb/pg_get_known_coin.c b/src/exchangedb/pg_get_known_coin.c new file mode 100644 index 000000000..fe5c683bc --- /dev/null +++ b/src/exchangedb/pg_get_known_coin.c @@ -0,0 +1,71 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_known_coin.c + * @brief Implementation of the get_known_coin function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_known_coin.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_get_known_coin (void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_CoinPublicInfo *coin_info) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &coin_info->denom_pub_hash), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &coin_info->h_age_commitment), + &coin_info->no_age_commitment), + TALER_PQ_result_spec_denom_sig ("denom_sig", + &coin_info->denom_sig), + GNUNET_PQ_result_spec_end + }; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Getting known coin data for coin %s\n", + TALER_B2S (coin_pub)); + coin_info->coin_pub = *coin_pub; + /* Used in #postgres_get_known_coin() to fetch + the denomination public key and signature for + a coin known to the exchange. */ + PREPARE (pg, + "get_known_coin", + "SELECT" + " denominations.denom_pub_hash" + ",age_commitment_hash" + ",denom_sig" + " FROM known_coins" + " JOIN denominations USING (denominations_serial)" + " WHERE coin_pub=$1;"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_known_coin", + params, + rs); +} diff --git a/src/exchangedb/pg_get_known_coin.h b/src/exchangedb/pg_get_known_coin.h new file mode 100644 index 000000000..d7f55b33c --- /dev/null +++ b/src/exchangedb/pg_get_known_coin.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_known_coin.h + * @brief implementation of the get_known_coin function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_KNOWN_COIN_H +#define PG_GET_KNOWN_COIN_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Retrieve the record for a known coin. + * + * @param cls the plugin closure + * @param coin_pub the public key of the coin to search for + * @param coin_info place holder for the returned coin information object + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_known_coin (void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_CoinPublicInfo *coin_info); + +#endif diff --git a/src/exchangedb/pg_get_melt.c b/src/exchangedb/pg_get_melt.c new file mode 100644 index 000000000..f239c605b --- /dev/null +++ b/src/exchangedb/pg_get_melt.c @@ -0,0 +1,128 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_melt.c + * @brief Implementation of the get_melt function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_melt.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_get_melt (void *cls, + const struct TALER_RefreshCommitmentP *rc, + struct TALER_EXCHANGEDB_Melt *melt, + uint64_t *melt_serial_id) +{ + struct PostgresClosure *pg = cls; + bool h_age_commitment_is_null; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (rc), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &melt->session.coin. + denom_pub_hash), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", + &melt->melt_fee), + GNUNET_PQ_result_spec_uint32 ("noreveal_index", + &melt->session.noreveal_index), + GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", + &melt->session.coin.coin_pub), + GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", + &melt->session.coin_sig), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &melt->session.coin.h_age_commitment), + &h_age_commitment_is_null), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &melt->session.amount_with_fee), + GNUNET_PQ_result_spec_uint64 ("melt_serial_id", + melt_serial_id), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + memset (&melt->session.coin.denom_sig, + 0, + sizeof (melt->session.coin.denom_sig)); + + /* Used in #postgres_get_melt() to fetch + high-level information about a melt operation */ + PREPARE (pg, + "get_melt", + /* "SELECT" + " denoms.denom_pub_hash" + ",denoms.fee_refresh_val" + ",denoms.fee_refresh_frac" + ",old_coin_pub" + ",old_coin_sig" + ",kc.age_commitment_hash" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",noreveal_index" + ",melt_serial_id" + " FROM refresh_commitments" + " JOIN known_coins kc" + " ON (old_coin_pub = kc.coin_pub)" + " JOIN denominations denoms" + " ON (kc.denominations_serial = denoms.denominations_serial)" + " WHERE rc=$1;", */ + "WITH rc AS MATERIALIZED ( " + " SELECT" + " * FROM refresh_commitments" + " WHERE rc=$1" + ")" + "SELECT" + " denoms.denom_pub_hash" + ",denoms.fee_refresh_val" + ",denoms.fee_refresh_frac" + ",rc.old_coin_pub" + ",rc.old_coin_sig" + ",kc.age_commitment_hash" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",noreveal_index" + ",melt_serial_id " + "FROM (" + " SELECT" + " * " + " FROM known_coins" + " WHERE coin_pub=(SELECT old_coin_pub from rc)" + ") kc " + "JOIN rc" + " ON (kc.coin_pub=rc.old_coin_pub) " + "JOIN denominations denoms" + " USING (denominations_serial);"); + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_melt", + params, + rs); + if (h_age_commitment_is_null) + memset (&melt->session.coin.h_age_commitment, + 0, + sizeof(melt->session.coin.h_age_commitment)); + + melt->session.rc = *rc; + return qs; +} diff --git a/src/exchangedb/pg_get_melt.h b/src/exchangedb/pg_get_melt.h new file mode 100644 index 000000000..73d757a05 --- /dev/null +++ b/src/exchangedb/pg_get_melt.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_melt.h + * @brief implementation of the get_melt function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_MELT_H +#define PG_GET_MELT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Lookup refresh melt commitment data under the given @a rc. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param rc commitment hash to use to locate the operation + * @param[out] melt where to store the result; note that + * melt->session.coin.denom_sig will be set to NULL + * and is not fetched by this routine (as it is not needed by the client) + * @param[out] melt_serial_id set to the row ID of @a rc in the refresh_commitments table + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_melt (void *cls, + const struct TALER_RefreshCommitmentP *rc, + struct TALER_EXCHANGEDB_Melt *melt, + uint64_t *melt_serial_id); + +#endif diff --git a/src/exchangedb/pg_get_old_coin_by_h_blind.c b/src/exchangedb/pg_get_old_coin_by_h_blind.c new file mode 100644 index 000000000..385c3f1d1 --- /dev/null +++ b/src/exchangedb/pg_get_old_coin_by_h_blind.c @@ -0,0 +1,65 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_old_coin_by_h_blind.c + * @brief Implementation of the get_old_coin_by_h_blind function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_old_coin_by_h_blind.h" +#include "pg_helper.h" + + + +enum GNUNET_DB_QueryStatus +TEH_PG_get_old_coin_by_h_blind ( + void *cls, + const struct TALER_BlindedCoinHashP *h_blind_ev, + struct TALER_CoinSpendPublicKeyP *old_coin_pub, + uint64_t *rrc_serial) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_blind_ev), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", + old_coin_pub), + GNUNET_PQ_result_spec_uint64 ("rrc_serial", + rrc_serial), + GNUNET_PQ_result_spec_end + }; + + /* Used in #postgres_get_old_coin_by_h_blind() */ + PREPARE (pg, + "old_coin_by_h_blind", + "SELECT" + " okc.coin_pub AS old_coin_pub" + ",rrc_serial" + " FROM refresh_revealed_coins rrc" + " JOIN refresh_commitments rcom USING (melt_serial_id)" + " JOIN known_coins okc ON (rcom.old_coin_pub = okc.coin_pub)" + " WHERE h_coin_ev=$1" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "old_coin_by_h_blind", + params, + rs); +} diff --git a/src/exchangedb/pg_get_old_coin_by_h_blind.h b/src/exchangedb/pg_get_old_coin_by_h_blind.h new file mode 100644 index 000000000..1404990d9 --- /dev/null +++ b/src/exchangedb/pg_get_old_coin_by_h_blind.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_old_coin_by_h_blind.h + * @brief implementation of the get_old_coin_by_h_blind function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_OLD_COIN_BY_H_BLIND_H +#define PG_GET_OLD_COIN_BY_H_BLIND_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Obtain information about which old coin a coin was refreshed + * given the hash of the blinded (fresh) coin. + * + * @param cls closure + * @param h_blind_ev hash of the blinded coin + * @param[out] old_coin_pub set to information about the old coin (on success only) + * @param[out] rrc_serial set to serial number of the entry in the database + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_old_coin_by_h_blind ( + void *cls, + const struct TALER_BlindedCoinHashP *h_blind_ev, + struct TALER_CoinSpendPublicKeyP *old_coin_pub, + uint64_t *rrc_serial); +#endif diff --git a/src/exchangedb/pg_get_policy_details.c b/src/exchangedb/pg_get_policy_details.c new file mode 100644 index 000000000..5dacb6005 --- /dev/null +++ b/src/exchangedb/pg_get_policy_details.c @@ -0,0 +1,65 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_policy_details.c + * @brief Implementation of the get_policy_details function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_policy_details.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_get_policy_details ( + void *cls, + const struct GNUNET_HashCode *hc, + struct TALER_PolicyDetails *details) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (hc), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("deadline", + &details->deadline), + TALER_PQ_RESULT_SPEC_AMOUNT ("commitment", + &details->commitment), + TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total", + &details->accumulated_total), + TALER_PQ_RESULT_SPEC_AMOUNT ("policy_fee", + &details->policy_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("transferable_amount", + &details->transferable_amount), + GNUNET_PQ_result_spec_auto_from_type ("state", + &details->fulfillment_state), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ("policy_fulfillment_id", + &details->policy_fulfillment_id), + &details->no_policy_fulfillment_id), + GNUNET_PQ_result_spec_end + }; + + + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_policy_details", + params, + rs); +} diff --git a/src/exchangedb/pg_get_policy_details.h b/src/exchangedb/pg_get_policy_details.h new file mode 100644 index 000000000..e3d2b0a2c --- /dev/null +++ b/src/exchangedb/pg_get_policy_details.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_policy_details.h + * @brief implementation of the get_policy_details function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_POLICY_DETAILS_H +#define PG_GET_POLICY_DETAILS_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/* Get the details of a policy, referenced by its hash code + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param hc The hash code under which the details to a particular policy should be found + * @param[out] details The found details + * @return query execution status + * */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_policy_details ( + void *cls, + const struct GNUNET_HashCode *hc, + struct TALER_PolicyDetails *details); + +#endif diff --git a/src/exchangedb/pg_get_ready_deposit.c b/src/exchangedb/pg_get_ready_deposit.c new file mode 100644 index 000000000..741a480d2 --- /dev/null +++ b/src/exchangedb/pg_get_ready_deposit.c @@ -0,0 +1,94 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_ready_deposit.c + * @brief Implementation of the get_ready_deposit function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_ready_deposit.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_get_ready_deposit (void *cls, + uint64_t start_shard_row, + uint64_t end_shard_row, + struct TALER_MerchantPublicKeyP *merchant_pub, + char **payto_uri) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_TIME_Absolute now = {0}; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_uint64 (&start_shard_row), + GNUNET_PQ_query_param_uint64 (&end_shard_row), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", + merchant_pub), + GNUNET_PQ_result_spec_string ("payto_uri", + payto_uri), + GNUNET_PQ_result_spec_end + }; + + now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (), + pg->aggregator_shift); + GNUNET_assert (start_shard_row < end_shard_row); + GNUNET_assert (end_shard_row <= INT32_MAX); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Finding ready deposits by deadline %s (%llu)\n", + GNUNET_TIME_absolute2s (now), + (unsigned long long) now.abs_value_us); + + + /* Used in #postgres_get_ready_deposit() */ + PREPARE (pg, + "deposits_get_ready", + "SELECT" + " payto_uri" + ",merchant_pub" + " FROM deposits_by_ready dbr" + " JOIN deposits dep" + " ON (dbr.coin_pub = dep.coin_pub AND" + " dbr.deposit_serial_id = dep.deposit_serial_id)" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " WHERE dbr.wire_deadline<=$1" + " AND dbr.shard >= $2" + " AND dbr.shard <= $3" + " ORDER BY " + " dbr.wire_deadline ASC" + " ,dbr.shard ASC" + " LIMIT 1;"); + + + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "deposits_get_ready", + params, + rs); +} + + + + + + diff --git a/src/exchangedb/pg_get_ready_deposit.h b/src/exchangedb/pg_get_ready_deposit.h new file mode 100644 index 000000000..19b6dafe4 --- /dev/null +++ b/src/exchangedb/pg_get_ready_deposit.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_ready_deposit.h + * @brief implementation of the get_ready_deposit function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_READY_DEPOSIT_H +#define PG_GET_READY_DEPOSIT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Obtain information about deposits that are ready to be executed. Such + * deposits must not be marked as "done", the execution time must be + * in the past, and the KYC status must be 'ok'. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param start_shard_row minimum shard row to select + * @param end_shard_row maximum shard row to select (inclusive) + * @param[out] merchant_pub set to the public key of a merchant with a ready deposit + * @param[out] payto_uri set to the account of the merchant, to be freed by caller + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_ready_deposit (void *cls, + uint64_t start_shard_row, + uint64_t end_shard_row, + struct TALER_MerchantPublicKeyP *merchant_pub, + char **payto_uri); + +#endif diff --git a/src/exchangedb/pg_get_refresh_reveal.c b/src/exchangedb/pg_get_refresh_reveal.c new file mode 100644 index 000000000..e2db082b7 --- /dev/null +++ b/src/exchangedb/pg_get_refresh_reveal.c @@ -0,0 +1,214 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_refresh_reveal.c + * @brief Implementation of the get_refresh_reveal function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_refresh_reveal.h" +#include "pg_helper.h" + + +/** + * Context where we aggregate data from the database. + * Closure for #add_revealed_coins(). + */ +struct GetRevealContext +{ + /** + * Array of revealed coins we obtained from the DB. + */ + struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs; + + /** + * Length of the @a rrcs array. + */ + unsigned int rrcs_len; + + /** + * Set to an error code if we ran into trouble. + */ + 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 of type `struct GetRevealContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +add_revealed_coins (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct GetRevealContext *grctx = cls; + + if (0 == num_results) + return; + grctx->rrcs = GNUNET_new_array (num_results, + struct TALER_EXCHANGEDB_RefreshRevealedCoin); + grctx->rrcs_len = num_results; + for (unsigned int i = 0; i < num_results; i++) + { + uint32_t off; + struct GNUNET_PQ_ResultSpec rso[] = { + GNUNET_PQ_result_spec_uint32 ("freshcoin_index", + &off), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rso, + i)) + { + GNUNET_break (0); + grctx->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + if (off >= num_results) + { + GNUNET_break (0); + grctx->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + { + struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx->rrcs[off]; + struct GNUNET_PQ_ResultSpec rsi[] = { + /* NOTE: freshcoin_index selected and discarded here... */ + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &rrc->h_denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("link_sig", + &rrc->orig_coin_link_sig), + GNUNET_PQ_result_spec_auto_from_type ("h_coin_ev", + &rrc->coin_envelope_hash), + TALER_PQ_result_spec_blinded_planchet ("coin_ev", + &rrc->blinded_planchet), + TALER_PQ_result_spec_exchange_withdraw_values ("ewv", + &rrc->exchange_vals), + TALER_PQ_result_spec_blinded_denom_sig ("ev_sig", + &rrc->coin_sig), + GNUNET_PQ_result_spec_end + }; + + if (TALER_DENOMINATION_INVALID != rrc->blinded_planchet.cipher) + { + /* duplicate offset, not allowed */ + GNUNET_break (0); + grctx->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rsi, + i)) + { + GNUNET_break (0); + grctx->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + } + } +} + + + + + +enum GNUNET_DB_QueryStatus +TEH_PG_get_refresh_reveal (void *cls, + const struct TALER_RefreshCommitmentP *rc, + TALER_EXCHANGEDB_RefreshCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GetRevealContext grctx; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (rc), + GNUNET_PQ_query_param_end + }; + + memset (&grctx, + 0, + sizeof (grctx)); + + /* Obtain information about the coins created in a refresh + operation, used in #postgres_get_refresh_reveal() */ + PREPARE (pg, + "get_refresh_revealed_coins", + "SELECT " + " rrc.freshcoin_index" + ",denom.denom_pub_hash" + ",rrc.h_coin_ev" + ",rrc.link_sig" + ",rrc.coin_ev" + ",rrc.ewv" + ",rrc.ev_sig" + " FROM refresh_commitments" + " JOIN refresh_revealed_coins rrc" + " USING (melt_serial_id)" + " JOIN denominations denom " + " USING (denominations_serial)" + " WHERE rc=$1;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "get_refresh_revealed_coins", + params, + &add_revealed_coins, + &grctx); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + case GNUNET_DB_STATUS_SOFT_ERROR: + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + goto cleanup; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + default: /* can have more than one result */ + break; + } + switch (grctx.qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + case GNUNET_DB_STATUS_SOFT_ERROR: + goto cleanup; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: /* should be impossible */ + break; + } + + /* Pass result back to application */ + cb (cb_cls, + grctx.rrcs_len, + grctx.rrcs); +cleanup: + for (unsigned int i = 0; i < grctx.rrcs_len; i++) + { + struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i]; + + TALER_blinded_denom_sig_free (&rrc->coin_sig); + TALER_blinded_planchet_free (&rrc->blinded_planchet); + } + GNUNET_free (grctx.rrcs); + return qs; +} diff --git a/src/exchangedb/pg_get_refresh_reveal.h b/src/exchangedb/pg_get_refresh_reveal.h new file mode 100644 index 000000000..0fcea26cd --- /dev/null +++ b/src/exchangedb/pg_get_refresh_reveal.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_refresh_reveal.h + * @brief implementation of the get_refresh_reveal function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_REFRESH_REVEAL_H +#define PG_GET_REFRESH_REVEAL_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Lookup in the database the coins that we want to + * create in the given refresh operation. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param rc identify commitment and thus refresh operation + * @param cb function to call with the results + * @param cb_cls closure for @a cb + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_refresh_reveal (void *cls, + const struct TALER_RefreshCommitmentP *rc, + TALER_EXCHANGEDB_RefreshCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_get_reserve_balance.c b/src/exchangedb/pg_get_reserve_balance.c new file mode 100644 index 000000000..e08261fc0 --- /dev/null +++ b/src/exchangedb/pg_get_reserve_balance.c @@ -0,0 +1,55 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_reserve_balance.c + * @brief Implementation of the get_reserve_balance function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_reserve_balance.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_get_reserve_balance (void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_Amount *balance) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance", + balance), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_reserve_balance", + "SELECT" + " current_balance_val" + ",current_balance_frac" + " FROM reserves" + " WHERE reserve_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_reserve_balance", + params, + rs); +} diff --git a/src/exchangedb/pg_get_reserve_balance.h b/src/exchangedb/pg_get_reserve_balance.h new file mode 100644 index 000000000..fd15f0d80 --- /dev/null +++ b/src/exchangedb/pg_get_reserve_balance.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_reserve_balance.h + * @brief implementation of the get_reserve_balance function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_RESERVE_BALANCE_H +#define PG_GET_RESERVE_BALANCE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Get the balance of the specified reserve. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param reserve_pub public key of the reserve + * @param[out] balance set to the reserve balance + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_reserve_balance (void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_Amount *balance); + +#endif diff --git a/src/exchangedb/pg_get_reserve_by_h_blind.c b/src/exchangedb/pg_get_reserve_by_h_blind.c new file mode 100644 index 000000000..2105b4766 --- /dev/null +++ b/src/exchangedb/pg_get_reserve_by_h_blind.c @@ -0,0 +1,63 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_reserve_by_h_blind.c + * @brief Implementation of the get_reserve_by_h_blind function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_reserve_by_h_blind.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_get_reserve_by_h_blind ( + void *cls, + const struct TALER_BlindedCoinHashP *bch, + struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *reserve_out_serial_id) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (bch), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + reserve_pub), + GNUNET_PQ_result_spec_uint64 ("reserve_out_serial_id", + reserve_out_serial_id), + GNUNET_PQ_result_spec_end + }; + /* Used in #postgres_get_reserve_by_h_blind() */ + PREPARE (pg, + "reserve_by_h_blind", + "SELECT" + " reserves.reserve_pub" + ",reserve_out_serial_id" + " FROM reserves_out" + " JOIN reserves" + " USING (reserve_uuid)" + " WHERE h_blind_ev=$1" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "reserve_by_h_blind", + params, + rs); +} diff --git a/src/exchangedb/pg_get_reserve_by_h_blind.h b/src/exchangedb/pg_get_reserve_by_h_blind.h new file mode 100644 index 000000000..49c1c8403 --- /dev/null +++ b/src/exchangedb/pg_get_reserve_by_h_blind.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_reserve_by_h_blind.h + * @brief implementation of the get_reserve_by_h_blind function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_RESERVE_BY_H_BLIND_H +#define PG_GET_RESERVE_BY_H_BLIND_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Obtain information about which reserve a coin was generated + * from given the hash of the blinded coin. + * + * @param cls closure + * @param bch hash that uniquely identifies the withdraw request + * @param[out] reserve_pub set to information about the reserve (on success only) + * @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in reserves_out + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_reserve_by_h_blind ( + void *cls, + const struct TALER_BlindedCoinHashP *bch, + struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *reserve_out_serial_id); + +#endif diff --git a/src/exchangedb/pg_get_wire_accounts.c b/src/exchangedb/pg_get_wire_accounts.c new file mode 100644 index 000000000..6986eaef2 --- /dev/null +++ b/src/exchangedb/pg_get_wire_accounts.c @@ -0,0 +1,129 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_wire_accounts.c + * @brief Implementation of the get_wire_accounts function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_wire_accounts.h" +#include "pg_helper.h" + + +/** + * Closure for #get_wire_accounts_cb(). + */ +struct GetWireAccountsContext +{ + /** + * Function to call per result. + */ + TALER_EXCHANGEDB_WireAccountCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Flag set to #GNUNET_OK as long as everything is fine. + */ + enum GNUNET_GenericReturnValue status; + +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct MissingWireContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_wire_accounts_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct GetWireAccountsContext *ctx = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + char *payto_uri; + struct TALER_MasterSignatureP master_sig; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &master_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ctx->cb (ctx->cb_cls, + payto_uri, + &master_sig); + GNUNET_PQ_cleanup_result (rs); + } +} + + + + +enum GNUNET_DB_QueryStatus +TEH_PG_get_wire_accounts (void *cls, + TALER_EXCHANGEDB_WireAccountCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GetWireAccountsContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .status = GNUNET_OK + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "get_wire_accounts", + "SELECT" + " payto_uri" + ",master_sig" + " FROM wire_accounts" + " WHERE is_active"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "get_wire_accounts", + params, + &get_wire_accounts_cb, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; + +} diff --git a/src/exchangedb/pg_get_wire_accounts.h b/src/exchangedb/pg_get_wire_accounts.h new file mode 100644 index 000000000..4ddda0ed3 --- /dev/null +++ b/src/exchangedb/pg_get_wire_accounts.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_wire_accounts.h + * @brief implementation of the get_wire_accounts function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_WIRE_ACCOUNTS_H +#define PG_GET_WIRE_ACCOUNTS_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + + +/** + * Obtain information about the enabled wire accounts of the exchange. + * + * @param cls closure + * @param cb function to call on each account + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_wire_accounts (void *cls, + TALER_EXCHANGEDB_WireAccountCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_get_wire_fee.c b/src/exchangedb/pg_get_wire_fee.c new file mode 100644 index 000000000..4b4324766 --- /dev/null +++ b/src/exchangedb/pg_get_wire_fee.c @@ -0,0 +1,78 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_wire_fee.c + * @brief Implementation of the get_wire_fee function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_wire_fee.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_get_wire_fee (void *cls, + const char *type, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_WireFeeSet *fees, + struct TALER_MasterSignatureP *master_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (type), + GNUNET_PQ_query_param_timestamp (&date), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("start_date", + start_date), + GNUNET_PQ_result_spec_timestamp ("end_date", + end_date), + TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", + &fees->wire), + TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", + &fees->closing), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), + GNUNET_PQ_result_spec_end + }; + + + + /* Used in #postgres_get_wire_fee() */ + PREPARE(pg, + "get_wire_fee", + "SELECT " + " start_date" + ",end_date" + ",wire_fee_val" + ",wire_fee_frac" + ",closing_fee_val" + ",closing_fee_frac" + ",master_sig" + " FROM wire_fee" + " WHERE wire_method=$1" + " AND start_date <= $2" + " AND end_date > $2;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_wire_fee", + params, + rs); +} diff --git a/src/exchangedb/pg_get_wire_fee.h b/src/exchangedb/pg_get_wire_fee.h new file mode 100644 index 000000000..92107fe30 --- /dev/null +++ b/src/exchangedb/pg_get_wire_fee.h @@ -0,0 +1,49 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_wire_fee.h + * @brief implementation of the get_wire_fee function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_WIRE_FEE_H +#define PG_GET_WIRE_FEE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Obtain wire fee from database. + * + * @param cls closure + * @param type type of wire transfer the fee applies for + * @param date for which date do we want the fee? + * @param[out] start_date when does the fee go into effect + * @param[out] end_date when does the fee end being valid + * @param[out] fees how high are the wire fees + * @param[out] master_sig signature over the above by the exchange master key + * @return status of the transaction + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_wire_fee (void *cls, + const char *type, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_WireFeeSet *fees, + struct TALER_MasterSignatureP *master_sig); + +#endif diff --git a/src/exchangedb/pg_get_wire_fees.c b/src/exchangedb/pg_get_wire_fees.c new file mode 100644 index 000000000..a83db151d --- /dev/null +++ b/src/exchangedb/pg_get_wire_fees.c @@ -0,0 +1,150 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_wire_fees.c + * @brief Implementation of the get_wire_fees function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_wire_fees.h" +#include "pg_helper.h" + +/** + * Closure for #get_wire_fees_cb(). + */ +struct GetWireFeesContext +{ + /** + * Function to call per result. + */ + TALER_EXCHANGEDB_WireFeeCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Flag set to #GNUNET_OK as long as everything is fine. + */ + enum GNUNET_GenericReturnValue status; + +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct GetWireFeesContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_wire_fees_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct GetWireFeesContext *ctx = cls; + struct PostgresClosure *pg = ctx->pg; + + for (unsigned int i = 0; i < num_results; i++) + { + struct TALER_MasterSignatureP master_sig; + struct TALER_WireFeeSet fees; + struct GNUNET_TIME_Timestamp start_date; + struct GNUNET_TIME_Timestamp end_date; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", + &fees.wire), + TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", + &fees.closing), + GNUNET_PQ_result_spec_timestamp ("start_date", + &start_date), + GNUNET_PQ_result_spec_timestamp ("end_date", + &end_date), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &master_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ctx->cb (ctx->cb_cls, + &fees, + start_date, + end_date, + &master_sig); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_get_wire_fees (void *cls, + const char *wire_method, + TALER_EXCHANGEDB_WireFeeCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (wire_method), + GNUNET_PQ_query_param_end + }; + struct GetWireFeesContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + + PREPARE (pg, + "get_wire_fees", + "SELECT" + " wire_fee_val" + ",wire_fee_frac" + ",closing_fee_val" + ",closing_fee_frac" + ",start_date" + ",end_date" + ",master_sig" + " FROM wire_fee" + " WHERE wire_method=$1"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "get_wire_fees", + params, + &get_wire_fees_cb, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_get_wire_fees.h b/src/exchangedb/pg_get_wire_fees.h new file mode 100644 index 000000000..83bacd674 --- /dev/null +++ b/src/exchangedb/pg_get_wire_fees.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_wire_fees.h + * @brief implementation of the get_wire_fees function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_WIRE_FEES_H +#define PG_GET_WIRE_FEES_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Obtain information about the fee structure of the exchange for + * a given @a wire_method + * + * @param cls closure + * @param wire_method which wire method to obtain fees for + * @param cb function to call on each account + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_wire_fees (void *cls, + const char *wire_method, + TALER_EXCHANGEDB_WireFeeCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_get_withdraw_info.c b/src/exchangedb/pg_get_withdraw_info.c new file mode 100644 index 000000000..ef3936269 --- /dev/null +++ b/src/exchangedb/pg_get_withdraw_info.c @@ -0,0 +1,85 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_withdraw_info.c + * @brief Implementation of the get_withdraw_info function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_get_withdraw_info.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_get_withdraw_info ( + void *cls, + const struct TALER_BlindedCoinHashP *bch, + struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (bch), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &collectable->denom_pub_hash), + TALER_PQ_result_spec_blinded_denom_sig ("denom_sig", + &collectable->sig), + GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", + &collectable->reserve_sig), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &collectable->reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", + &collectable->h_coin_envelope), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &collectable->amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", + &collectable->withdraw_fee), + GNUNET_PQ_result_spec_end + }; + + /* Used in #postgres_get_withdraw_info() to + locate the response for a /reserve/withdraw request + using the hash of the blinded message. Used to + make sure /reserve/withdraw requests are idempotent. */ + PREPARE (pg, + "get_withdraw_info", + "SELECT" + " denom.denom_pub_hash" + ",denom_sig" + ",reserve_sig" + ",reserves.reserve_pub" + ",execution_date" + ",h_blind_ev" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",denom.fee_withdraw_val" + ",denom.fee_withdraw_frac" + " FROM reserves_out" + " JOIN reserves" + " USING (reserve_uuid)" + " JOIN denominations denom" + " USING (denominations_serial)" + " WHERE h_blind_ev=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_withdraw_info", + params, + rs); +} diff --git a/src/exchangedb/pg_get_withdraw_info.h b/src/exchangedb/pg_get_withdraw_info.h new file mode 100644 index 000000000..7c3e06a02 --- /dev/null +++ b/src/exchangedb/pg_get_withdraw_info.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_get_withdraw_info.h + * @brief implementation of the get_withdraw_info function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_GET_WITHDRAW_INFO_H +#define PG_GET_WITHDRAW_INFO_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Locate the response for a /reserve/withdraw request under the + * key of the hash of the blinded message. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param bch hash that uniquely identifies the withdraw operation + * @param collectable corresponding collectable coin (blind signature) + * if a coin is found + * @return statement execution status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_get_withdraw_info ( + void *cls, + const struct TALER_BlindedCoinHashP *bch, + struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable); + +#endif diff --git a/src/exchangedb/pg_have_deposit2.c b/src/exchangedb/pg_have_deposit2.c new file mode 100644 index 000000000..1616858c5 --- /dev/null +++ b/src/exchangedb/pg_have_deposit2.c @@ -0,0 +1,120 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_have_deposit2.c + * @brief Implementation of the have_deposit2 function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_have_deposit2.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_have_deposit2 ( + void *cls, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant, + struct GNUNET_TIME_Timestamp refund_deadline, + struct TALER_Amount *deposit_fee, + struct GNUNET_TIME_Timestamp *exchange_timestamp) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_auto_from_type (h_contract_terms), + GNUNET_PQ_query_param_auto_from_type (merchant), + GNUNET_PQ_query_param_end + }; + struct TALER_EXCHANGEDB_Deposit deposit2; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &deposit2.amount_with_fee), + GNUNET_PQ_result_spec_timestamp ("wallet_timestamp", + &deposit2.timestamp), + GNUNET_PQ_result_spec_timestamp ("exchange_timestamp", + exchange_timestamp), + GNUNET_PQ_result_spec_timestamp ("refund_deadline", + &deposit2.refund_deadline), + GNUNET_PQ_result_spec_timestamp ("wire_deadline", + &deposit2.wire_deadline), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + deposit_fee), + GNUNET_PQ_result_spec_auto_from_type ("wire_salt", + &deposit2.wire_salt), + GNUNET_PQ_result_spec_string ("receiver_wire_account", + &deposit2.receiver_wire_account), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + struct TALER_MerchantWireHashP h_wire2; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Getting deposits for coin %s\n", + TALER_B2S (coin_pub)); + + /* Fetch an existing deposit request, used to ensure idempotency + during /deposit processing. Used in #postgres_have_deposit(). */ + PREPARE (pg, + "get_deposit", + "SELECT" + " dep.amount_with_fee_val" + ",dep.amount_with_fee_frac" + ",denominations.fee_deposit_val" + ",denominations.fee_deposit_frac" + ",dep.wallet_timestamp" + ",dep.exchange_timestamp" + ",dep.refund_deadline" + ",dep.wire_deadline" + ",dep.h_contract_terms" + ",dep.wire_salt" + ",wt.payto_uri AS receiver_wire_account" + " FROM deposits dep" + " JOIN known_coins kc ON (kc.coin_pub = dep.coin_pub)" + " JOIN denominations USING (denominations_serial)" + " JOIN wire_targets wt USING (wire_target_h_payto)" + " WHERE dep.coin_pub=$1" + " AND dep.merchant_pub=$3" + " AND dep.h_contract_terms=$2;"); + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_deposit", + params, + rs); + if (0 >= qs) + return qs; + TALER_merchant_wire_signature_hash (deposit2.receiver_wire_account, + &deposit2.wire_salt, + &h_wire2); + GNUNET_free (deposit2.receiver_wire_account); + /* Now we check that the other information in @a deposit + also matches, and if not report inconsistencies. */ + if ( (GNUNET_TIME_timestamp_cmp (refund_deadline, + !=, + deposit2.refund_deadline)) || + (0 != GNUNET_memcmp (h_wire, + &h_wire2) ) ) + { + /* Inconsistencies detected! Does not match! */ + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; +} diff --git a/src/exchangedb/pg_have_deposit2.h b/src/exchangedb/pg_have_deposit2.h new file mode 100644 index 000000000..0e8119c20 --- /dev/null +++ b/src/exchangedb/pg_have_deposit2.h @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_have_deposit2.h + * @brief implementation of the have_deposit2 function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_HAVE_DEPOSIT2_H +#define PG_HAVE_DEPOSIT2_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Check if we have the specified deposit already in the database. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param h_contract_terms contract to check for + * @param h_wire wire hash to check for + * @param coin_pub public key of the coin to check for + * @param merchant merchant public key to check for + * @param refund_deadline expected refund deadline + * @param[out] deposit_fee set to the deposit fee the exchange charged + * @param[out] exchange_timestamp set to the time when the exchange received the deposit + * @return 1 if we know this operation, + * 0 if this exact deposit is unknown to us, + * otherwise transaction error status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_have_deposit2 ( + void *cls, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant, + struct GNUNET_TIME_Timestamp refund_deadline, + struct TALER_Amount *deposit_fee, + struct GNUNET_TIME_Timestamp *exchange_timestamp); +#endif diff --git a/src/exchangedb/pg_insert_auditor.c b/src/exchangedb/pg_insert_auditor.c new file mode 100644 index 000000000..757dfa625 --- /dev/null +++ b/src/exchangedb/pg_insert_auditor.c @@ -0,0 +1,58 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_auditor.c + * @brief Implementation of the insert_auditor function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_auditor.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_auditor (void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp start_date) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (auditor_pub), + GNUNET_PQ_query_param_string (auditor_name), + GNUNET_PQ_query_param_string (auditor_url), + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_end + }; + + /* used in #postgres_insert_auditor() */ + PREPARE (pg, + "insert_auditor", + "INSERT INTO auditors " + "(auditor_pub" + ",auditor_name" + ",auditor_url" + ",is_active" + ",last_change" + ") VALUES " + "($1, $2, $3, true, $4);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_auditor", + params); +} diff --git a/src/exchangedb/pg_insert_auditor.h b/src/exchangedb/pg_insert_auditor.h new file mode 100644 index 000000000..7523282e4 --- /dev/null +++ b/src/exchangedb/pg_insert_auditor.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_auditor.h + * @brief implementation of the insert_auditor function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_AUDITOR_H +#define PG_INSERT_AUDITOR_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Insert information about an auditor that will audit this exchange. + * + * @param cls closure + * @param auditor_pub key of the auditor + * @param auditor_url base URL of the auditor's REST service + * @param auditor_name name of the auditor (for humans) + * @param start_date date when the auditor was added by the offline system + * (only to be used for replay detection) + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_auditor (void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp start_date); +#endif diff --git a/src/exchangedb/pg_insert_auditor_denom_sig.c b/src/exchangedb/pg_insert_auditor_denom_sig.c new file mode 100644 index 000000000..3643a87f2 --- /dev/null +++ b/src/exchangedb/pg_insert_auditor_denom_sig.c @@ -0,0 +1,61 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_auditor_denom_sig.c + * @brief Implementation of the insert_auditor_denom_sig function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_auditor_denom_sig.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_auditor_denom_sig ( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const struct TALER_AuditorSignatureP *auditor_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (auditor_pub), + GNUNET_PQ_query_param_auto_from_type (h_denom_pub), + GNUNET_PQ_query_param_auto_from_type (auditor_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_auditor_denom_sig", + "WITH ax AS" + " (SELECT auditor_uuid" + " FROM auditors" + " WHERE auditor_pub=$1)" + "INSERT INTO auditor_denom_sigs " + "(auditor_uuid" + ",denominations_serial" + ",auditor_sig" + ") SELECT ax.auditor_uuid, denominations_serial, $3 " + " FROM denominations" + " CROSS JOIN ax" + " WHERE denom_pub_hash=$2;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_auditor_denom_sig", + params); +} diff --git a/src/exchangedb/pg_insert_auditor_denom_sig.h b/src/exchangedb/pg_insert_auditor_denom_sig.h new file mode 100644 index 000000000..baa67cfe8 --- /dev/null +++ b/src/exchangedb/pg_insert_auditor_denom_sig.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_auditor_denom_sig.h + * @brief implementation of the insert_auditor_denom_sig function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_AUDITOR_DENOM_SIG_H +#define PG_INSERT_AUDITOR_DENOM_SIG_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Insert information about an auditor auditing a denomination key. + * + * @param cls closure + * @param h_denom_pub the audited denomination + * @param auditor_pub the auditor's key + * @param auditor_sig signature affirming the auditor's audit activity + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_auditor_denom_sig ( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const struct TALER_AuditorSignatureP *auditor_sig); +#endif diff --git a/src/exchangedb/pg_insert_denomination_revocation.c b/src/exchangedb/pg_insert_denomination_revocation.c new file mode 100644 index 000000000..061d7adc0 --- /dev/null +++ b/src/exchangedb/pg_insert_denomination_revocation.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_denomination_revocation.c + * @brief Implementation of the insert_denomination_revocation function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_denomination_revocation.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_denomination_revocation ( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + const struct TALER_MasterSignatureP *master_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_end + }; + + /* Used in #postgres_insert_denomination_revocation() */ + PREPARE (pg, + "denomination_revocation_insert", + "INSERT INTO denomination_revocations " + "(denominations_serial" + ",master_sig" + ") SELECT denominations_serial,$2" + " FROM denominations" + " WHERE denom_pub_hash=$1;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "denomination_revocation_insert", + params); +} diff --git a/src/exchangedb/pg_insert_denomination_revocation.h b/src/exchangedb/pg_insert_denomination_revocation.h new file mode 100644 index 000000000..e3da87666 --- /dev/null +++ b/src/exchangedb/pg_insert_denomination_revocation.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_denomination_revocation.h + * @brief implementation of the insert_denomination_revocation function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_DENOMINATION_REVOCATION_H +#define PG_INSERT_DENOMINATION_REVOCATION_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Store information that a denomination key was revoked + * in the database. + * + * @param cls closure + * @param denom_pub_hash hash of the revoked denomination key + * @param master_sig signature affirming the revocation + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_denomination_revocation ( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + const struct TALER_MasterSignatureP *master_sig); +#endif diff --git a/src/exchangedb/pg_insert_deposit.c b/src/exchangedb/pg_insert_deposit.c new file mode 100644 index 000000000..09247e282 --- /dev/null +++ b/src/exchangedb/pg_insert_deposit.c @@ -0,0 +1,104 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_deposit.c + * @brief Implementation of the insert_deposit function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_deposit.h" +#include "pg_helper.h" +#include "pg_setup_wire_target.h" +#include "pg_compute_shard.h" +enum GNUNET_DB_QueryStatus +TEH_PG_insert_deposit (void *cls, + struct GNUNET_TIME_Timestamp exchange_timestamp, + const struct TALER_EXCHANGEDB_Deposit *deposit) +{ + struct PostgresClosure *pg = cls; + struct TALER_PaytoHashP h_payto; + enum GNUNET_DB_QueryStatus qs; + + qs = TEH_PG_setup_wire_target (pg, + deposit->receiver_wire_account, + &h_payto); + if (qs < 0) + return qs; + if (GNUNET_TIME_timestamp_cmp (deposit->wire_deadline, + <, + deposit->refund_deadline)) + { + GNUNET_break (0); + } + { + uint64_t shard = TEH_PG_compute_shard (&deposit->merchant_pub); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub), + TALER_PQ_query_param_amount (&deposit->amount_with_fee), + GNUNET_PQ_query_param_timestamp (&deposit->timestamp), + GNUNET_PQ_query_param_timestamp (&deposit->refund_deadline), + GNUNET_PQ_query_param_timestamp (&deposit->wire_deadline), + GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub), + GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms), + GNUNET_PQ_query_param_auto_from_type (&deposit->wire_salt), + GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&deposit->csig), + GNUNET_PQ_query_param_timestamp (&exchange_timestamp), + GNUNET_PQ_query_param_uint64 (&shard), + GNUNET_PQ_query_param_end + }; + + GNUNET_assert (shard <= INT32_MAX); + GNUNET_log ( + GNUNET_ERROR_TYPE_INFO, + "Inserting deposit to be executed at %s (%llu/%llu)\n", + GNUNET_TIME_timestamp2s (deposit->wire_deadline), + (unsigned long long) deposit->wire_deadline.abs_time.abs_value_us, + (unsigned long long) deposit->refund_deadline.abs_time.abs_value_us); + /* Store information about a /deposit the exchange is to execute. + Used in #postgres_insert_deposit(). Only used in test cases. */ + PREPARE (pg, + "insert_deposit", + "INSERT INTO deposits " + "(known_coin_id" + ",coin_pub" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",wallet_timestamp" + ",refund_deadline" + ",wire_deadline" + ",merchant_pub" + ",h_contract_terms" + ",wire_salt" + ",wire_target_h_payto" + ",coin_sig" + ",exchange_timestamp" + ",shard" + ") SELECT known_coin_id, $1, $2, $3, $4, $5, $6, " + " $7, $8, $9, $10, $11, $12, $13" + " FROM known_coins" + " WHERE coin_pub=$1" + " ON CONFLICT DO NOTHING;"); + + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_deposit", + params); + } +} diff --git a/src/exchangedb/pg_insert_deposit.h b/src/exchangedb/pg_insert_deposit.h new file mode 100644 index 000000000..15de39eff --- /dev/null +++ b/src/exchangedb/pg_insert_deposit.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_deposit.h + * @brief implementation of the insert_deposit function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_DEPOSIT_H +#define PG_INSERT_DEPOSIT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Insert information about deposited coin into the database. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param exchange_timestamp time the exchange received the deposit request + * @param deposit deposit information to store + * @return query result status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_deposit (void *cls, + struct GNUNET_TIME_Timestamp exchange_timestamp, + const struct TALER_EXCHANGEDB_Deposit *deposit); + +#endif diff --git a/src/exchangedb/pg_insert_global_fee.c b/src/exchangedb/pg_insert_global_fee.c new file mode 100644 index 000000000..c08fc23bb --- /dev/null +++ b/src/exchangedb/pg_insert_global_fee.c @@ -0,0 +1,137 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_global_fee.c + * @brief Implementation of the insert_global_fee function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_global_fee.h" +#include "pg_helper.h" +#include "pg_get_global_fee.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_global_fee (void *cls, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + const struct TALER_MasterSignatureP *master_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_timestamp (&end_date), + TALER_PQ_query_param_amount (&fees->history), + TALER_PQ_query_param_amount (&fees->account), + TALER_PQ_query_param_amount (&fees->purse), + GNUNET_PQ_query_param_relative_time (&purse_timeout), + GNUNET_PQ_query_param_relative_time (&history_expiration), + GNUNET_PQ_query_param_uint32 (&purse_account_limit), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_end + }; + struct TALER_GlobalFeeSet wx; + struct TALER_MasterSignatureP sig; + struct GNUNET_TIME_Timestamp sd; + struct GNUNET_TIME_Timestamp ed; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_TIME_Relative pt; + struct GNUNET_TIME_Relative he; + uint32_t pal; + + qs = TEH_PG_get_global_fee (pg, + start_date, + &sd, + &ed, + &wx, + &pt, + &he, + &pal, + &sig); + if (qs < 0) + return qs; + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + if (0 != GNUNET_memcmp (&sig, + master_sig)) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (0 != + TALER_global_fee_set_cmp (fees, + &wx)) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if ( (GNUNET_TIME_timestamp_cmp (sd, + !=, + start_date)) || + (GNUNET_TIME_timestamp_cmp (ed, + !=, + end_date)) ) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if ( (GNUNET_TIME_relative_cmp (purse_timeout, + !=, + pt)) || + (GNUNET_TIME_relative_cmp (history_expiration, + !=, + he)) ) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (purse_account_limit != pal) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + /* equal record already exists */ + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + + /* Used in #postgres_insert_global_fee */ + PREPARE (pg, + "insert_global_fee", + "INSERT INTO global_fee " + "(start_date" + ",end_date" + ",history_fee_val" + ",history_fee_frac" + ",account_fee_val" + ",account_fee_frac" + ",purse_fee_val" + ",purse_fee_frac" + ",purse_timeout" + ",history_expiration" + ",purse_account_limit" + ",master_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_global_fee", + params); +} diff --git a/src/exchangedb/pg_insert_global_fee.h b/src/exchangedb/pg_insert_global_fee.h new file mode 100644 index 000000000..9780d5322 --- /dev/null +++ b/src/exchangedb/pg_insert_global_fee.h @@ -0,0 +1,50 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_global_fee.h + * @brief implementation of the insert_global_fee function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_GLOBAL_FEE_H +#define PG_INSERT_GLOBAL_FEE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Insert global fee data into database. + * + * @param cls closure + * @param start_date when does the fees go into effect + * @param end_date when does the fees end being valid + * @param fees how high is are the global fees + * @param purse_timeout when do purses time out + * @param history_expiration how long are account histories preserved + * @param purse_account_limit how many purses are free per account + * @param master_sig signature over the above by the exchange master key + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_global_fee (void *cls, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + const struct TALER_MasterSignatureP *master_sig); +#endif diff --git a/src/exchangedb/pg_insert_partner.c b/src/exchangedb/pg_insert_partner.c new file mode 100644 index 000000000..567f37763 --- /dev/null +++ b/src/exchangedb/pg_insert_partner.c @@ -0,0 +1,70 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_partner.c + * @brief Implementation of the insert_partner function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_partner.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_partner (void *cls, + const struct TALER_MasterPublicKeyP *master_pub, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + struct GNUNET_TIME_Relative wad_frequency, + const struct TALER_Amount *wad_fee, + const char *partner_base_url, + const struct TALER_MasterSignatureP *master_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (master_pub), + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_timestamp (&end_date), + GNUNET_PQ_query_param_relative_time (&wad_frequency), + TALER_PQ_query_param_amount (wad_fee), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_string (partner_base_url), + GNUNET_PQ_query_param_end + }; + + + PREPARE (pg, + "insert_partner", + "INSERT INTO partners" + " (partner_master_pub" + " ,start_date" + " ,end_date" + " ,wad_frequency" + " ,wad_fee_val" + " ,wad_fee_frac" + " ,master_sig" + " ,partner_base_url" + " ) VALUES " + " ($1, $2, $3, $4, $5, $6, $7, $8);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_partner", + params); +} + + diff --git a/src/exchangedb/pg_insert_partner.h b/src/exchangedb/pg_insert_partner.h new file mode 100644 index 000000000..eed40a80e --- /dev/null +++ b/src/exchangedb/pg_insert_partner.h @@ -0,0 +1,51 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_partner.h + * @brief implementation of the insert_partner function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_PARTNER_H +#define PG_INSERT_PARTNER_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Function called to store configuration data about a partner + * exchange that we are federated with. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param master_pub public offline signing key of the partner exchange + * @param start_date when does the following data start to be valid + * @param end_date when does the validity end (exclusive) + * @param wad_frequency how often do we do exchange-to-exchange settlements? + * @param wad_fee how much do we charge for transfers to the partner + * @param partner_base_url base URL of the partner exchange + * @param master_sig signature with our offline signing key affirming the above + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_partner (void *cls, + const struct TALER_MasterPublicKeyP *master_pub, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + struct GNUNET_TIME_Relative wad_frequency, + const struct TALER_Amount *wad_fee, + const char *partner_base_url, + const struct TALER_MasterSignatureP *master_sig); + +#endif diff --git a/src/exchangedb/pg_insert_refresh_reveal.c b/src/exchangedb/pg_insert_refresh_reveal.c new file mode 100644 index 000000000..098a3aed8 --- /dev/null +++ b/src/exchangedb/pg_insert_refresh_reveal.c @@ -0,0 +1,94 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_refresh_reveal.c + * @brief Implementation of the insert_refresh_reveal function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_refresh_reveal.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_refresh_reveal ( + void *cls, + uint64_t melt_serial_id, + uint32_t num_rrcs, + const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs, + unsigned int num_tprivs, + const struct TALER_TransferPrivateKeyP *tprivs, + const struct TALER_TransferPublicKeyP *tp) +{ + struct PostgresClosure *pg = cls; + + if (TALER_CNC_KAPPA != num_tprivs + 1) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + for (uint32_t i = 0; iorig_coin_link_sig), + GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub), + TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet), + TALER_PQ_query_param_exchange_withdraw_values (&rrc->exchange_vals), + GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash), + TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_refresh_revealed_coin", + params); + if (0 > qs) + return qs; + } + + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&melt_serial_id), + GNUNET_PQ_query_param_auto_from_type (tp), + GNUNET_PQ_query_param_fixed_size ( + tprivs, + num_tprivs * sizeof (struct TALER_TransferPrivateKeyP)), + GNUNET_PQ_query_param_end + }; + + /* Used in #postgres_insert_refresh_reveal() to store the transfer + keys we learned */ + PREPARE (pg, + "insert_refresh_transfer_keys", + "INSERT INTO refresh_transfer_keys " + "(melt_serial_id" + ",transfer_pub" + ",transfer_privs" + ") VALUES ($1, $2, $3)" + " ON CONFLICT DO NOTHING;"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_refresh_transfer_keys", + params); + } +} diff --git a/src/exchangedb/pg_insert_refresh_reveal.h b/src/exchangedb/pg_insert_refresh_reveal.h new file mode 100644 index 000000000..ad53ab197 --- /dev/null +++ b/src/exchangedb/pg_insert_refresh_reveal.h @@ -0,0 +1,51 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_refresh_reveal.h + * @brief implementation of the insert_refresh_reveal function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_REFRESH_REVEAL_H +#define PG_INSERT_REFRESH_REVEAL_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Store in the database which coin(s) the wallet wanted to create + * in a given refresh operation and all of the other information + * we learned or created in the /refresh/reveal step. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param melt_serial_id row ID of the commitment / melt operation in refresh_commitments + * @param num_rrcs number of coins to generate, size of the @a rrcs array + * @param rrcs information about the new coins + * @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1 + * @param tprivs transfer private keys to store + * @param tp public key to store + * @return query status for the transaction + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_refresh_reveal ( + void *cls, + uint64_t melt_serial_id, + uint32_t num_rrcs, + const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs, + unsigned int num_tprivs, + const struct TALER_TransferPrivateKeyP *tprivs, + const struct TALER_TransferPublicKeyP *tp); + +#endif diff --git a/src/exchangedb/pg_insert_refund.c b/src/exchangedb/pg_insert_refund.c new file mode 100644 index 000000000..047df0334 --- /dev/null +++ b/src/exchangedb/pg_insert_refund.c @@ -0,0 +1,66 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_refund.c + * @brief Implementation of the insert_refund function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_refund.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_refund (void *cls, + const struct TALER_EXCHANGEDB_Refund *refund) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub), + GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub), + GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig), + GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms), + GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id), + TALER_PQ_query_param_amount (&refund->details.refund_amount), + GNUNET_PQ_query_param_end + }; + + GNUNET_assert (GNUNET_YES == + TALER_amount_cmp_currency (&refund->details.refund_amount, + &refund->details.refund_fee)); + + /* Used in #postgres_insert_refund() to store refund information */ + PREPARE (pg, + "insert_refund", + "INSERT INTO refunds " + "(coin_pub " + ",deposit_serial_id" + ",merchant_sig " + ",rtransaction_id " + ",amount_with_fee_val " + ",amount_with_fee_frac " + ") SELECT $1, deposit_serial_id, $3, $5, $6, $7" + " FROM deposits" + " WHERE coin_pub=$1" + " AND h_contract_terms=$4" + " AND merchant_pub=$2"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_refund", + params); +} diff --git a/src/exchangedb/pg_insert_refund.h b/src/exchangedb/pg_insert_refund.h new file mode 100644 index 000000000..02190bcc9 --- /dev/null +++ b/src/exchangedb/pg_insert_refund.h @@ -0,0 +1,38 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_refund.h + * @brief implementation of the insert_refund function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_REFUND_H +#define PG_INSERT_REFUND_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Insert information about refunded coin into the database. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param refund refund information to store + * @return query result status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_refund (void *cls, + const struct TALER_EXCHANGEDB_Refund *refund); + +#endif diff --git a/src/exchangedb/pg_insert_reserve_closed.c b/src/exchangedb/pg_insert_reserve_closed.c new file mode 100644 index 000000000..d17c37edc --- /dev/null +++ b/src/exchangedb/pg_insert_reserve_closed.c @@ -0,0 +1,114 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_reserve_closed.c + * @brief Implementation of the insert_reserve_closed function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_reserve_closed.h" +#include "pg_helper.h" +#include "pg_reserves_get.h" +#include "pg_reserves_update.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_reserve_closed ( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct GNUNET_TIME_Timestamp execution_date, + const char *receiver_account, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_Amount *amount_with_fee, + const struct TALER_Amount *closing_fee, + uint64_t close_request_row) +{ + struct PostgresClosure *pg = cls; + struct TALER_EXCHANGEDB_Reserve reserve; + enum GNUNET_DB_QueryStatus qs; + struct TALER_PaytoHashP h_payto; + + TALER_payto_hash (receiver_account, + &h_payto); + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_timestamp (&execution_date), + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_auto_from_type (&h_payto), + TALER_PQ_query_param_amount (amount_with_fee), + TALER_PQ_query_param_amount (closing_fee), + GNUNET_PQ_query_param_uint64 (&close_request_row), + GNUNET_PQ_query_param_end + }; + + /* Used in #postgres_insert_reserve_closed() */ + PREPARE (pg, + "reserves_close_insert", + "INSERT INTO reserves_close " + "(reserve_pub" + ",execution_date" + ",wtid" + ",wire_target_h_payto" + ",amount_val" + ",amount_frac" + ",closing_fee_val" + ",closing_fee_frac" + ",close_request_row" + ") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9);"); + + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "reserves_close_insert", + params); + } + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) + return qs; + + /* update reserve balance */ + reserve.pub = *reserve_pub; + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + (qs = TEH_PG_reserves_get (cls, + &reserve))) + { + /* Existence should have been checked before we got here... */ + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + qs = GNUNET_DB_STATUS_HARD_ERROR; + return qs; + } + { + enum TALER_AmountArithmeticResult ret; + + ret = TALER_amount_subtract (&reserve.balance, + &reserve.balance, + amount_with_fee); + if (ret < 0) + { + /* The reserve history was checked to make sure there is enough of a balance + left before we tried this; however, concurrent operations may have changed + the situation by now. We should re-try the transaction. */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Closing of reserve `%s' refused due to balance mismatch. Retrying.\n", + TALER_B2S (reserve_pub)); + return GNUNET_DB_STATUS_HARD_ERROR; + } + GNUNET_break (TALER_AAR_RESULT_ZERO == ret); + } + return TEH_PG_reserves_update (cls, + &reserve); +} diff --git a/src/exchangedb/pg_insert_reserve_closed.h b/src/exchangedb/pg_insert_reserve_closed.h new file mode 100644 index 000000000..2ac1a6e30 --- /dev/null +++ b/src/exchangedb/pg_insert_reserve_closed.h @@ -0,0 +1,51 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_reserve_closed.h + * @brief implementation of the insert_reserve_closed function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_RESERVE_CLOSED_H +#define PG_INSERT_RESERVE_CLOSED_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Insert reserve close operation into database. + * + * @param cls closure + * @param reserve_pub which reserve is this about? + * @param execution_date when did we perform the transfer? + * @param receiver_account to which account do we transfer? + * @param wtid wire transfer details + * @param amount_with_fee amount we charged to the reserve + * @param closing_fee how high is the closing fee + * @param close_request_row identifies explicit close request, 0 for none + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_reserve_closed ( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct GNUNET_TIME_Timestamp execution_date, + const char *receiver_account, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_Amount *amount_with_fee, + const struct TALER_Amount *closing_fee, + uint64_t close_request_row); + +#endif diff --git a/src/exchangedb/pg_insert_signkey_revocation.c b/src/exchangedb/pg_insert_signkey_revocation.c new file mode 100644 index 000000000..9197be6ad --- /dev/null +++ b/src/exchangedb/pg_insert_signkey_revocation.c @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_signkey_revocation.c + * @brief Implementation of the insert_signkey_revocation function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_signkey_revocation.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_signkey_revocation ( + void *cls, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_MasterSignatureP *master_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (exchange_pub), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_end + }; + + + PREPARE (pg, + "insert_signkey_revocation", + "INSERT INTO signkey_revocations " + "(esk_serial" + ",master_sig" + ") SELECT esk_serial, $2 " + " FROM exchange_sign_keys" + " WHERE exchange_pub=$1;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_signkey_revocation", + params); +} diff --git a/src/exchangedb/pg_insert_signkey_revocation.h b/src/exchangedb/pg_insert_signkey_revocation.h new file mode 100644 index 000000000..534e6d451 --- /dev/null +++ b/src/exchangedb/pg_insert_signkey_revocation.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_signkey_revocation.h + * @brief implementation of the insert_signkey_revocation function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_SIGNKEY_REVOCATION_H +#define PG_INSERT_SIGNKEY_REVOCATION_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Store information about a revoked online signing key. + * + * @param cls closure + * @param exchange_pub exchange online signing key that was revoked + * @param master_sig signature affirming the revocation + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_signkey_revocation ( + void *cls, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_MasterSignatureP *master_sig); +#endif diff --git a/src/exchangedb/pg_insert_wire.c b/src/exchangedb/pg_insert_wire.c new file mode 100644 index 000000000..646bce94e --- /dev/null +++ b/src/exchangedb/pg_insert_wire.c @@ -0,0 +1,56 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_wire.c + * @brief Implementation of the insert_wire function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_wire.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_wire (void *cls, + const char *payto_uri, + struct GNUNET_TIME_Timestamp start_date, + const struct TALER_MasterSignatureP *master_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (payto_uri), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_end + }; + + /* used in #postgres_insert_wire() */ + PREPARE (pg, + "insert_wire", + "INSERT INTO wire_accounts " + "(payto_uri" + ",master_sig" + ",is_active" + ",last_change" + ") VALUES " + "($1, $2, true, $3);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_wire", + params); +} diff --git a/src/exchangedb/pg_insert_wire.h b/src/exchangedb/pg_insert_wire.h new file mode 100644 index 000000000..15ce08674 --- /dev/null +++ b/src/exchangedb/pg_insert_wire.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_wire.h + * @brief implementation of the insert_wire function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_WIRE_H +#define PG_INSERT_WIRE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Insert information about an wire account used by this exchange. + * + * @param cls closure + * @param payto_uri wire account of the exchange + * @param start_date date when the account was added by the offline system + * (only to be used for replay detection) + * @param master_sig public signature affirming the existence of the account, + * must be of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_wire (void *cls, + const char *payto_uri, + struct GNUNET_TIME_Timestamp start_date, + const struct TALER_MasterSignatureP *master_sig); + +#endif diff --git a/src/exchangedb/pg_insert_wire_fee.c b/src/exchangedb/pg_insert_wire_fee.c new file mode 100644 index 000000000..278ec2bcb --- /dev/null +++ b/src/exchangedb/pg_insert_wire_fee.c @@ -0,0 +1,108 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_wire_fee.c + * @brief Implementation of the insert_wire_fee function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_wire_fee.h" +#include "pg_helper.h" +#include "pg_get_wire_fee.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_wire_fee (void *cls, + const char *type, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_WireFeeSet *fees, + const struct TALER_MasterSignatureP *master_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (type), + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_timestamp (&end_date), + TALER_PQ_query_param_amount (&fees->wire), + TALER_PQ_query_param_amount (&fees->closing), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_end + }; + struct TALER_WireFeeSet wx; + struct TALER_MasterSignatureP sig; + struct GNUNET_TIME_Timestamp sd; + struct GNUNET_TIME_Timestamp ed; + enum GNUNET_DB_QueryStatus qs; + + qs = TEH_PG_get_wire_fee (pg, + type, + start_date, + &sd, + &ed, + &wx, + &sig); + if (qs < 0) + return qs; + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + if (0 != GNUNET_memcmp (&sig, + master_sig)) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (0 != + TALER_wire_fee_set_cmp (fees, + &wx)) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if ( (GNUNET_TIME_timestamp_cmp (sd, + !=, + start_date)) || + (GNUNET_TIME_timestamp_cmp (ed, + !=, + end_date)) ) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + /* equal record already exists */ + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + + /* Used in #postgres_insert_wire_fee */ + PREPARE (pg, + "insert_wire_fee", + "INSERT INTO wire_fee " + "(wire_method" + ",start_date" + ",end_date" + ",wire_fee_val" + ",wire_fee_frac" + ",closing_fee_val" + ",closing_fee_frac" + ",master_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_wire_fee", + params); +} diff --git a/src/exchangedb/pg_insert_wire_fee.h b/src/exchangedb/pg_insert_wire_fee.h new file mode 100644 index 000000000..e53faf5a5 --- /dev/null +++ b/src/exchangedb/pg_insert_wire_fee.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_insert_wire_fee.h + * @brief implementation of the insert_wire_fee function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_WIRE_FEE_H +#define PG_INSERT_WIRE_FEE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Insert wire transfer fee into database. + * + * @param cls closure + * @param type type of wire transfer this fee applies for + * @param start_date when does the fee go into effect + * @param end_date when does the fee end being valid + * @param fees how high are the wire fees + * @param master_sig signature over the above by the exchange master key + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_wire_fee (void *cls, + const char *type, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_WireFeeSet *fees, + const struct TALER_MasterSignatureP *master_sig); +#endif diff --git a/src/exchangedb/pg_iterate_active_auditors.c b/src/exchangedb/pg_iterate_active_auditors.c new file mode 100644 index 000000000..11b10cb48 --- /dev/null +++ b/src/exchangedb/pg_iterate_active_auditors.c @@ -0,0 +1,124 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_iterate_active_auditors.c + * @brief Implementation of the iterate_active_auditors function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_iterate_active_auditors.h" +#include "pg_helper.h" + + +/** + * Closure for #auditors_cb_helper() + */ +struct AuditorsIteratorContext +{ + /** + * Function to call with the results. + */ + TALER_EXCHANGEDB_AuditorsCallback cb; + + /** + * Closure to pass to @e cb + */ + void *cb_cls; + +}; + + +/** + * Helper function for #postgres_iterate_active_auditors(). + * Calls the callback with each auditor. + * + * @param cls a `struct SignkeysIteratorContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +auditors_cb_helper (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct AuditorsIteratorContext *dic = cls; + + for (unsigned int i = 0; icb (dic->cb_cls, + &auditor_pub, + auditor_url, + auditor_name); + GNUNET_PQ_cleanup_result (rs); + } +} + + + +enum GNUNET_DB_QueryStatus +TEH_PG_iterate_active_auditors (void *cls, + TALER_EXCHANGEDB_AuditorsCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + struct AuditorsIteratorContext dic = { + .cb = cb, + .cb_cls = cb_cls, + }; + /* Used in #postgres_iterate_active_auditors() */ + PREPARE (pg, + "select_auditors", + "SELECT" + " auditor_pub" + ",auditor_url" + ",auditor_name" + " FROM auditors" + " WHERE" + " is_active;"); + + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "select_auditors", + params, + &auditors_cb_helper, + &dic); +} diff --git a/src/exchangedb/pg_iterate_active_auditors.h b/src/exchangedb/pg_iterate_active_auditors.h new file mode 100644 index 000000000..1247d2d3d --- /dev/null +++ b/src/exchangedb/pg_iterate_active_auditors.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_iterate_active_auditors.h + * @brief implementation of the iterate_active_auditors function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_ITERATE_ACTIVE_AUDITORS_H +#define PG_ITERATE_ACTIVE_AUDITORS_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to invoke @a cb on every active auditor. Disabled + * auditors are skipped. Runs in its own read-only transaction. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param cb function to call on each active auditor + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_iterate_active_auditors (void *cls, + TALER_EXCHANGEDB_AuditorsCallback cb, + void *cb_cls); +#endif diff --git a/src/exchangedb/pg_iterate_auditor_denominations.c b/src/exchangedb/pg_iterate_auditor_denominations.c new file mode 100644 index 000000000..6456ed1d4 --- /dev/null +++ b/src/exchangedb/pg_iterate_auditor_denominations.c @@ -0,0 +1,121 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_iterate_auditor_denominations.c + * @brief Implementation of the iterate_auditor_denominations function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_iterate_auditor_denominations.h" +#include "pg_helper.h" + +/** + * Closure for #auditor_denoms_cb_helper() + */ +struct AuditorDenomsIteratorContext +{ + /** + * Function to call with the results. + */ + TALER_EXCHANGEDB_AuditorDenominationsCallback cb; + + /** + * Closure to pass to @e cb + */ + void *cb_cls; +}; + + +/** + * Helper function for #postgres_iterate_auditor_denominations(). + * Calls the callback with each auditor and denomination pair. + * + * @param cls a `struct AuditorDenomsIteratorContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +auditor_denoms_cb_helper (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct AuditorDenomsIteratorContext *dic = cls; + + for (unsigned int i = 0; icb (dic->cb_cls, + &auditor_pub, + &h_denom_pub, + &auditor_sig); + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_iterate_auditor_denominations ( + void *cls, + TALER_EXCHANGEDB_AuditorDenominationsCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + struct AuditorDenomsIteratorContext dic = { + .cb = cb, + .cb_cls = cb_cls, + }; + /* Used in #postgres_iterate_auditor_denominations() */ + PREPARE (pg, + "select_auditor_denoms", + "SELECT" + " auditors.auditor_pub" + ",denominations.denom_pub_hash" + ",auditor_denom_sigs.auditor_sig" + " FROM auditor_denom_sigs" + " JOIN auditors USING (auditor_uuid)" + " JOIN denominations USING (denominations_serial)" + " WHERE auditors.is_active;"); + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "select_auditor_denoms", + params, + &auditor_denoms_cb_helper, + &dic); +} diff --git a/src/exchangedb/pg_iterate_auditor_denominations.h b/src/exchangedb/pg_iterate_auditor_denominations.h new file mode 100644 index 000000000..da1f36701 --- /dev/null +++ b/src/exchangedb/pg_iterate_auditor_denominations.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_iterate_auditor_denominations.h + * @brief implementation of the iterate_auditor_denominations function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_ITERATE_AUDITOR_DENOMINATIONS_H +#define PG_ITERATE_AUDITOR_DENOMINATIONS_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + + +/** + * Function called to invoke @a cb on every denomination with an active + * auditor. Disabled auditors and denominations without auditor are + * skipped. Runs in its own read-only transaction. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param cb function to call on each active auditor + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_iterate_auditor_denominations ( + void *cls, + TALER_EXCHANGEDB_AuditorDenominationsCallback cb, + void *cb_cls); +#endif diff --git a/src/exchangedb/pg_iterate_denomination_info.c b/src/exchangedb/pg_iterate_denomination_info.c new file mode 100644 index 000000000..bf39a65af --- /dev/null +++ b/src/exchangedb/pg_iterate_denomination_info.c @@ -0,0 +1,194 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_iterate_denomination_info.c + * @brief Implementation of the iterate_denomination_info function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_iterate_denomination_info.h" +#include "pg_helper.h" + + +/** + * Closure for #domination_cb_helper() + */ +struct DenomIteratorContext +{ + /** + * Function to call with the results. + */ + TALER_EXCHANGEDB_DenominationCallback cb; + + /** + * Closure to pass to @e cb + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; +}; + + +/** + * Helper function for #postgres_iterate_denomination_info(). + * Calls the callback with each denomination key. + * + * @param cls a `struct DenomIteratorContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +domination_cb_helper (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct DenomIteratorContext *dic = cls; + struct PostgresClosure *pg = dic->pg; + + for (unsigned int i = 0; icb (dic->cb_cls, + &denom_pub, + &issue); + } + TALER_denom_pub_free (&denom_pub); + } +} + + + + + + + + + + +/** + * Fetch information about all known denomination keys. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param cb function to call on each denomination key + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_iterate_denomination_info (void *cls, + TALER_EXCHANGEDB_DenominationCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + struct DenomIteratorContext dic = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg + }; + + /* Used in #postgres_iterate_denomination_info() */ + PREPARE (pg, + "denomination_iterate", + "SELECT" + " master_sig" + ",denom_pub_hash" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin_val" /* value of this denom */ + ",coin_frac" /* fractional value of this denom */ + ",fee_withdraw_val" + ",fee_withdraw_frac" + ",fee_deposit_val" + ",fee_deposit_frac" + ",fee_refresh_val" + ",fee_refresh_frac" + ",fee_refund_val" + ",fee_refund_frac" + ",denom_pub" + ",age_mask" + " FROM denominations;"); + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "denomination_iterate", + params, + &domination_cb_helper, + &dic); +} diff --git a/src/exchangedb/pg_iterate_denomination_info.h b/src/exchangedb/pg_iterate_denomination_info.h new file mode 100644 index 000000000..57847a515 --- /dev/null +++ b/src/exchangedb/pg_iterate_denomination_info.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_iterate_denomination_info.h + * @brief implementation of the iterate_denomination_info function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_ITERATE_DENOMINATION_INFO_H +#define PG_ITERATE_DENOMINATION_INFO_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Fetch information about all known denomination keys. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param cb function to call on each denomination key + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_iterate_denomination_info (void *cls, + TALER_EXCHANGEDB_DenominationCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_iterate_denominations.c b/src/exchangedb/pg_iterate_denominations.c new file mode 100644 index 000000000..d8a91f558 --- /dev/null +++ b/src/exchangedb/pg_iterate_denominations.c @@ -0,0 +1,179 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_iterate_denominations.c + * @brief Implementation of the iterate_denominations function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_iterate_denominations.h" +#include "pg_helper.h" + + + + +/** + * Closure for #dominations_cb_helper() + */ +struct DenomsIteratorContext +{ + /** + * Function to call with the results. + */ + TALER_EXCHANGEDB_DenominationsCallback cb; + + /** + * Closure to pass to @e cb + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; +}; + + +/** + * Helper function for #postgres_iterate_denominations(). + * Calls the callback with each denomination key. + * + * @param cls a `struct DenomsIteratorContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +dominations_cb_helper (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct DenomsIteratorContext *dic = cls; + struct PostgresClosure *pg = dic->pg; + + for (unsigned int i = 0; icb (dic->cb_cls, + &denom_pub, + &h_denom_pub, + &meta, + &master_sig, + revoked); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_iterate_denominations (void *cls, + TALER_EXCHANGEDB_DenominationsCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + struct DenomsIteratorContext dic = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg + }; + + /* Used in #postgres_iterate_denominations() */ + PREPARE (pg, + "select_denominations", + "SELECT" + " denominations.master_sig" + ",denom_revocations_serial_id IS NOT NULL AS revoked" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin_val" /* value of this denom */ + ",coin_frac" /* fractional value of this denom */ + ",fee_withdraw_val" + ",fee_withdraw_frac" + ",fee_deposit_val" + ",fee_deposit_frac" + ",fee_refresh_val" + ",fee_refresh_frac" + ",fee_refund_val" + ",fee_refund_frac" + ",denom_type" + ",age_mask" + ",denom_pub" + " FROM denominations" + " LEFT JOIN " + " denomination_revocations USING (denominations_serial);"); + + + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "select_denominations", + params, + &dominations_cb_helper, + &dic); +} diff --git a/src/exchangedb/pg_iterate_denominations.h b/src/exchangedb/pg_iterate_denominations.h new file mode 100644 index 000000000..a205fc6ba --- /dev/null +++ b/src/exchangedb/pg_iterate_denominations.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_iterate_denominations.h + * @brief implementation of the iterate_denominations function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_ITERATE_DENOMINATIONS_H +#define PG_ITERATE_DENOMINATIONS_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to invoke @a cb on every known denomination key (revoked + * and non-revoked) that has been signed by the master key. Runs in its own + * read-only transaction. + * + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param cb function to call on each denomination key + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_iterate_denominations (void *cls, + TALER_EXCHANGEDB_DenominationsCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_lookup_auditor_status.c b/src/exchangedb/pg_lookup_auditor_status.c new file mode 100644 index 000000000..5e62bfa9e --- /dev/null +++ b/src/exchangedb/pg_lookup_auditor_status.c @@ -0,0 +1,61 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_auditor_status.c + * @brief Implementation of the lookup_auditor_status function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_lookup_auditor_status.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_auditor_status ( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + char **auditor_url, + bool *enabled) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (auditor_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("auditor_url", + auditor_url), + GNUNET_PQ_result_spec_bool ("is_active", + enabled), + GNUNET_PQ_result_spec_end + }; + + /* Used in #postgres_lookup_auditor_status() */ + PREPARE (pg, + "lookup_auditor_status", + "SELECT" + " auditor_url" + ",is_active" + " FROM auditors" + " WHERE auditor_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_auditor_status", + params, + rs); +} diff --git a/src/exchangedb/pg_lookup_auditor_status.h b/src/exchangedb/pg_lookup_auditor_status.h new file mode 100644 index 000000000..b75788e11 --- /dev/null +++ b/src/exchangedb/pg_lookup_auditor_status.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_auditor_status.h + * @brief implementation of the lookup_auditor_status function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_AUDITOR_STATUS_H +#define PG_LOOKUP_AUDITOR_STATUS_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Lookup current state of an auditor. + * + * @param cls closure + * @param auditor_pub key to look up information for + * @param[out] auditor_url set to the base URL of the auditor's REST API; memory to be + * released by the caller! + * @param[out] enabled set if the auditor is currently in use + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_auditor_status ( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + char **auditor_url, + bool *enabled); + +#endif diff --git a/src/exchangedb/pg_lookup_auditor_timestamp.c b/src/exchangedb/pg_lookup_auditor_timestamp.c new file mode 100644 index 000000000..3a4bd6bed --- /dev/null +++ b/src/exchangedb/pg_lookup_auditor_timestamp.c @@ -0,0 +1,57 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_auditor_timestamp.c + * @brief Implementation of the lookup_auditor_timestamp function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_lookup_auditor_timestamp.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_auditor_timestamp ( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct GNUNET_TIME_Timestamp *last_date) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (auditor_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("last_change", + last_date), + GNUNET_PQ_result_spec_end + }; + + /* Used in #postgres_lookup_auditor_timestamp() */ + PREPARE (pg, + "lookup_auditor_timestamp", + "SELECT" + " last_change" + " FROM auditors" + " WHERE auditor_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_auditor_timestamp", + params, + rs); +} diff --git a/src/exchangedb/pg_lookup_auditor_timestamp.h b/src/exchangedb/pg_lookup_auditor_timestamp.h new file mode 100644 index 000000000..5674ba225 --- /dev/null +++ b/src/exchangedb/pg_lookup_auditor_timestamp.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_auditor_timestamp.h + * @brief implementation of the lookup_auditor_timestamp function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_AUDITOR_TIMESTAMP_H +#define PG_LOOKUP_AUDITOR_TIMESTAMP_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Check the last date an auditor was modified. + * + * @param cls closure + * @param auditor_pub key to look up information for + * @param[out] last_date last modification date to auditor status + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_auditor_timestamp ( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct GNUNET_TIME_Timestamp *last_date); +#endif diff --git a/src/exchangedb/pg_lookup_denomination_key.c b/src/exchangedb/pg_lookup_denomination_key.c new file mode 100644 index 000000000..36ada96e4 --- /dev/null +++ b/src/exchangedb/pg_lookup_denomination_key.c @@ -0,0 +1,88 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_denomination_key.c + * @brief Implementation of the lookup_denomination_key function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_lookup_denomination_key.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_denomination_key ( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_denom_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("valid_from", + &meta->start), + GNUNET_PQ_result_spec_timestamp ("expire_withdraw", + &meta->expire_withdraw), + GNUNET_PQ_result_spec_timestamp ("expire_deposit", + &meta->expire_deposit), + GNUNET_PQ_result_spec_timestamp ("expire_legal", + &meta->expire_legal), + TALER_PQ_RESULT_SPEC_AMOUNT ("coin", + &meta->value), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", + &meta->fees.withdraw), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + &meta->fees.deposit), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", + &meta->fees.refresh), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", + &meta->fees.refund), + GNUNET_PQ_result_spec_uint32 ("age_mask", + &meta->age_mask.bits), + GNUNET_PQ_result_spec_end + }; + + /* used in #postgres_lookup_denomination_key() */ + PREPARE (pg, + "lookup_denomination_key", + "SELECT" + " valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin_val" + ",coin_frac" + ",fee_withdraw_val" + ",fee_withdraw_frac" + ",fee_deposit_val" + ",fee_deposit_frac" + ",fee_refresh_val" + ",fee_refresh_frac" + ",fee_refund_val" + ",fee_refund_frac" + ",age_mask" + " FROM denominations" + " WHERE denom_pub_hash=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_denomination_key", + params, + rs); +} diff --git a/src/exchangedb/pg_lookup_denomination_key.h b/src/exchangedb/pg_lookup_denomination_key.h new file mode 100644 index 000000000..b7317ac4a --- /dev/null +++ b/src/exchangedb/pg_lookup_denomination_key.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_denomination_key.h + * @brief implementation of the lookup_denomination_key function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_DENOMINATION_KEY_H +#define PG_LOOKUP_DENOMINATION_KEY_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Lookup information about current denomination key. + * + * @param cls closure + * @param h_denom_pub hash of the denomination public key + * @param[out] meta set to various meta data about the key + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_denomination_key ( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta); + +#endif diff --git a/src/exchangedb/pg_lookup_signing_key.c b/src/exchangedb/pg_lookup_signing_key.c new file mode 100644 index 000000000..3f31a6f49 --- /dev/null +++ b/src/exchangedb/pg_lookup_signing_key.c @@ -0,0 +1,65 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_signing_key.c + * @brief Implementation of the lookup_signing_key function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_lookup_signing_key.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_signing_key ( + void *cls, + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct TALER_EXCHANGEDB_SignkeyMetaData *meta) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (exchange_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("valid_from", + &meta->start), + GNUNET_PQ_result_spec_timestamp ("expire_sign", + &meta->expire_sign), + GNUNET_PQ_result_spec_timestamp ("expire_legal", + &meta->expire_legal), + GNUNET_PQ_result_spec_end + }; + + + PREPARE (pg, + "lookup_signing_key", + "SELECT" + " valid_from" + ",expire_sign" + ",expire_legal" + " FROM exchange_sign_keys" + " WHERE exchange_pub=$1"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_signing_key", + params, + rs); +} + diff --git a/src/exchangedb/pg_lookup_signing_key.h b/src/exchangedb/pg_lookup_signing_key.h new file mode 100644 index 000000000..487d60d2b --- /dev/null +++ b/src/exchangedb/pg_lookup_signing_key.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_signing_key.h + * @brief implementation of the lookup_signing_key function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_SIGNING_KEY_H +#define PG_LOOKUP_SIGNING_KEY_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + + +/** + * Lookup signing key meta data. + * + * @param cls closure + * @param exchange_pub the exchange online signing public key + * @param[out] meta meta data about @a exchange_pub + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_signing_key ( + void *cls, + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct TALER_EXCHANGEDB_SignkeyMetaData *meta); +#endif diff --git a/src/exchangedb/pg_lookup_signkey_revocation.c b/src/exchangedb/pg_lookup_signkey_revocation.c new file mode 100644 index 000000000..374aa7d5b --- /dev/null +++ b/src/exchangedb/pg_lookup_signkey_revocation.c @@ -0,0 +1,61 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_signkey_revocation.c + * @brief Implementation of the lookup_signkey_revocation function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_lookup_signkey_revocation.h" +#include "pg_helper.h" + + + +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_signkey_revocation ( + void *cls, + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct TALER_MasterSignatureP *master_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (exchange_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), + GNUNET_PQ_result_spec_end + }; + + + PREPARE (pg, + "lookup_signkey_revocation", + "SELECT " + " master_sig" + " FROM signkey_revocations" + " WHERE esk_serial=" + " (SELECT esk_serial" + " FROM exchange_sign_keys" + " WHERE exchange_pub=$1);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_signkey_revocation", + params, + rs); +} diff --git a/src/exchangedb/pg_lookup_signkey_revocation.h b/src/exchangedb/pg_lookup_signkey_revocation.h new file mode 100644 index 000000000..de0fb1d74 --- /dev/null +++ b/src/exchangedb/pg_lookup_signkey_revocation.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_signkey_revocation.h + * @brief implementation of the lookup_signkey_revocation function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_SIGNKEY_REVOCATION_H +#define PG_LOOKUP_SIGNKEY_REVOCATION_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Obtain information about a revoked online signing key. + * + * @param cls closure + * @param exchange_pub exchange online signing key + * @param[out] master_sig set to signature affirming the revocation (if revoked) + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_signkey_revocation ( + void *cls, + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct TALER_MasterSignatureP *master_sig); + +#endif diff --git a/src/exchangedb/pg_lookup_transfer_by_deposit.c b/src/exchangedb/pg_lookup_transfer_by_deposit.c new file mode 100644 index 000000000..686b67cc4 --- /dev/null +++ b/src/exchangedb/pg_lookup_transfer_by_deposit.c @@ -0,0 +1,203 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_transfer_by_deposit.c + * @brief Implementation of the lookup_transfer_by_deposit function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_lookup_transfer_by_deposit.h" +#include "pg_helper.h" + + + +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_transfer_by_deposit ( + void *cls, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + bool *pending, + struct TALER_WireTransferIdentifierRawP *wtid, + struct GNUNET_TIME_Timestamp *exec_time, + struct TALER_Amount *amount_with_fee, + struct TALER_Amount *deposit_fee, + struct TALER_EXCHANGEDB_KycStatus *kyc) +{ + struct PostgresClosure *pg = cls; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_auto_from_type (h_contract_terms), + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_end + }; + char *payto_uri; + struct TALER_WireSaltP wire_salt; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", + wtid), + GNUNET_PQ_result_spec_auto_from_type ("wire_salt", + &wire_salt), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri), + GNUNET_PQ_result_spec_timestamp ("execution_date", + exec_time), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + deposit_fee), + GNUNET_PQ_result_spec_end + }; + + memset (kyc, + 0, + sizeof (*kyc)); + /* check if the aggregation record exists and get it */ + + /* Used in #postgres_lookup_transfer_by_deposit */ + PREPARE (pg, + "lookup_deposit_wtid", + "SELECT" + " aggregation_tracking.wtid_raw" + ",wire_out.execution_date" + ",dep.amount_with_fee_val" + ",dep.amount_with_fee_frac" + ",dep.wire_salt" + ",wt.payto_uri" + ",denom.fee_deposit_val" + ",denom.fee_deposit_frac" + " FROM deposits dep" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " JOIN aggregation_tracking" + " USING (deposit_serial_id)" + " JOIN known_coins kc" + " ON (kc.coin_pub = dep.coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " JOIN wire_out" + " USING (wtid_raw)" + " WHERE dep.coin_pub=$1" + " AND dep.merchant_pub=$3" + " AND dep.h_contract_terms=$2"); + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_deposit_wtid", + params, + rs); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + struct TALER_MerchantWireHashP wh; + + TALER_merchant_wire_signature_hash (payto_uri, + &wire_salt, + &wh); + GNUNET_PQ_cleanup_result (rs); + if (0 == + GNUNET_memcmp (&wh, + h_wire)) + { + *pending = false; + kyc->ok = true; + return qs; + } + qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + if (0 > qs) + return qs; + *pending = true; + memset (wtid, + 0, + sizeof (*wtid)); + GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "lookup_deposit_wtid returned 0 matching rows\n"); + { + /* Check if transaction exists in deposits, so that we just + do not have a WTID yet. In that case, return without wtid + (by setting 'pending' true). */ + struct GNUNET_PQ_ResultSpec rs2[] = { + GNUNET_PQ_result_spec_auto_from_type ("wire_salt", + &wire_salt), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ("legitimization_requirement_serial_id", + &kyc->requirement_row), + NULL), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + deposit_fee), + GNUNET_PQ_result_spec_timestamp ("wire_deadline", + exec_time), + GNUNET_PQ_result_spec_end + }; + + /* Fetch an existing deposit request. + Used in #postgres_lookup_transfer_by_deposit(). */ + PREPARE (pg, + "get_deposit_without_wtid", + "SELECT" + " agt.legitimization_requirement_serial_id" + ",dep.wire_salt" + ",wt.payto_uri" + ",dep.amount_with_fee_val" + ",dep.amount_with_fee_frac" + ",denom.fee_deposit_val" + ",denom.fee_deposit_frac" + ",dep.wire_deadline" + " FROM deposits dep" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " JOIN known_coins kc" + " ON (kc.coin_pub = dep.coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " LEFT JOIN aggregation_transient agt " + " ON ( (dep.wire_target_h_payto = agt.wire_target_h_payto) AND" + " (dep.merchant_pub = agt.merchant_pub) )" + " WHERE dep.coin_pub=$1" + " AND dep.merchant_pub=$3" + " AND dep.h_contract_terms=$2" + " LIMIT 1;"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_deposit_without_wtid", + params, + rs2); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + struct TALER_MerchantWireHashP wh; + + if (0 == kyc->requirement_row) + kyc->ok = true; /* technically: unknown */ + TALER_merchant_wire_signature_hash (payto_uri, + &wire_salt, + &wh); + GNUNET_PQ_cleanup_result (rs); + if (0 != + GNUNET_memcmp (&wh, + h_wire)) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + return qs; + } +} diff --git a/src/exchangedb/pg_lookup_transfer_by_deposit.h b/src/exchangedb/pg_lookup_transfer_by_deposit.h new file mode 100644 index 000000000..ff5554dcc --- /dev/null +++ b/src/exchangedb/pg_lookup_transfer_by_deposit.h @@ -0,0 +1,61 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_transfer_by_deposit.h + * @brief implementation of the lookup_transfer_by_deposit function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_TRANSFER_BY_DEPOSIT_H +#define PG_LOOKUP_TRANSFER_BY_DEPOSIT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Try to find the wire transfer details for a deposit operation. + * If we did not execute the deposit yet, return when it is supposed + * to be executed. + * + * @param cls closure + * @param h_contract_terms hash of the proposal data + * @param h_wire hash of merchant wire details + * @param coin_pub public key of deposited coin + * @param merchant_pub merchant public key + * @param[out] pending set to true if the transaction is still pending + * @param[out] wtid wire transfer identifier, only set if @a pending is false + * @param[out] exec_time when was the transaction done, or + * when we expect it to be done (if @a pending is false) + * @param[out] amount_with_fee set to the total deposited amount + * @param[out] deposit_fee set to how much the exchange did charge for the deposit + * @param[out] kyc set to the kyc status of the receiver (if @a pending) + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_transfer_by_deposit ( + void *cls, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + bool *pending, + struct TALER_WireTransferIdentifierRawP *wtid, + struct GNUNET_TIME_Timestamp *exec_time, + struct TALER_Amount *amount_with_fee, + struct TALER_Amount *deposit_fee, + struct TALER_EXCHANGEDB_KycStatus *kyc); + +#endif diff --git a/src/exchangedb/pg_lookup_wire_timestamp.c b/src/exchangedb/pg_lookup_wire_timestamp.c new file mode 100644 index 000000000..19e915d48 --- /dev/null +++ b/src/exchangedb/pg_lookup_wire_timestamp.c @@ -0,0 +1,56 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_wire_timestamp.c + * @brief Implementation of the lookup_wire_timestamp function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_lookup_wire_timestamp.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_wire_timestamp (void *cls, + const char *payto_uri, + struct GNUNET_TIME_Timestamp *last_date) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (payto_uri), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("last_change", + last_date), + GNUNET_PQ_result_spec_end + }; + + + PREPARE (pg, + "lookup_wire_timestamp", + "SELECT" + " last_change" + " FROM wire_accounts" + " WHERE payto_uri=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_wire_timestamp", + params, + rs); +} diff --git a/src/exchangedb/pg_lookup_wire_timestamp.h b/src/exchangedb/pg_lookup_wire_timestamp.h new file mode 100644 index 000000000..069dd940c --- /dev/null +++ b/src/exchangedb/pg_lookup_wire_timestamp.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_wire_timestamp.h + * @brief implementation of the lookup_wire_timestamp function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_WIRE_TIMESTAMP_H +#define PG_LOOKUP_WIRE_TIMESTAMP_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Check the last date an exchange wire account was modified. + * + * @param cls closure + * @param payto_uri key to look up information for + * @param[out] last_date last modification date to auditor status + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_wire_timestamp (void *cls, + const char *payto_uri, + struct GNUNET_TIME_Timestamp *last_date); + +#endif diff --git a/src/exchangedb/pg_lookup_wire_transfer.c b/src/exchangedb/pg_lookup_wire_transfer.c new file mode 100644 index 000000000..394251702 --- /dev/null +++ b/src/exchangedb/pg_lookup_wire_transfer.c @@ -0,0 +1,187 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_wire_tranfer.c + * @brief Implementation of the lookup_wire_tranfer function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_lookup_wire_transfer.h" +#include "pg_helper.h" + +/** + * Closure for #handle_wt_result. + */ +struct WireTransferResultContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_AggregationDataCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Set to #GNUNET_SYSERR on serious errors. + */ + int status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. Helper function + * for #postgres_lookup_wire_transfer(). + * + * @param cls closure of type `struct WireTransferResultContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +handle_wt_result (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct WireTransferResultContext *ctx = cls; + struct PostgresClosure *pg = ctx->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ctx->cb (ctx->cb_cls, + rowid, + &merchant_pub, + payto_uri, + &h_payto, + exec_time, + &h_contract_terms, + &denom_pub, + &coin_pub, + &amount_with_fee, + &deposit_fee); + GNUNET_PQ_cleanup_result (rs); + } +} + +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_wire_transfer ( + void *cls, + const struct TALER_WireTransferIdentifierRawP *wtid, + TALER_EXCHANGEDB_AggregationDataCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_end + }; + struct WireTransferResultContext ctx; + enum GNUNET_DB_QueryStatus qs; + + ctx.cb = cb; + ctx.cb_cls = cb_cls; + ctx.pg = pg; + ctx.status = GNUNET_OK; + /* check if the melt record exists and get it */ + /* Used in #postgres_lookup_wire_transfer */ + PREPARE (pg, + "lookup_transactions", + "SELECT" + " aggregation_serial_id" + ",deposits.h_contract_terms" + ",payto_uri" + ",wire_targets.wire_target_h_payto" + ",kc.coin_pub" + ",deposits.merchant_pub" + ",wire_out.execution_date" + ",deposits.amount_with_fee_val" + ",deposits.amount_with_fee_frac" + ",denom.fee_deposit_val" + ",denom.fee_deposit_frac" + ",denom.denom_pub" + " FROM aggregation_tracking" + " JOIN deposits" + " USING (deposit_serial_id)" + " JOIN wire_targets" + " USING (wire_target_h_payto)" + " JOIN known_coins kc" + " USING (coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " JOIN wire_out" + " USING (wtid_raw)" + " WHERE wtid_raw=$1;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_transactions", + params, + &handle_wt_result, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_lookup_wire_transfer.h b/src/exchangedb/pg_lookup_wire_transfer.h new file mode 100644 index 000000000..1d66a2119 --- /dev/null +++ b/src/exchangedb/pg_lookup_wire_transfer.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_lookup_wire_tranfer.h + * @brief implementation of the lookup_wire_tranfer function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_WIRE_TRANSFER_H +#define PG_LOOKUP_WIRE_TRANSFER_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Lookup the list of Taler transactions that were aggregated + * into a wire transfer by the respective @a wtid. + * + * @param cls closure + * @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 query status of the transaction + */ +enum GNUNET_DB_QueryStatus +TEH_PG_lookup_wire_transfer ( + void *cls, + const struct TALER_WireTransferIdentifierRawP *wtid, + TALER_EXCHANGEDB_AggregationDataCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_persist_policy_details.c b/src/exchangedb/pg_persist_policy_details.c new file mode 100644 index 000000000..28e2e4c5e --- /dev/null +++ b/src/exchangedb/pg_persist_policy_details.c @@ -0,0 +1,67 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_persist_policy_details.c + * @brief Implementation of the persist_policy_details function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_persist_policy_details.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_persist_policy_details ( + void *cls, + const struct TALER_PolicyDetails *details, + uint64_t *policy_details_serial_id, + struct TALER_Amount *accumulated_total, + enum TALER_PolicyFulfillmentState *fulfillment_state) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&details->hash_code), + TALER_PQ_query_param_json (details->policy_json), + GNUNET_PQ_query_param_timestamp (&details->deadline), + TALER_PQ_query_param_amount (&details->commitment), + TALER_PQ_query_param_amount (&details->accumulated_total), + TALER_PQ_query_param_amount (&details->policy_fee), + TALER_PQ_query_param_amount (&details->transferable_amount), + GNUNET_PQ_query_param_auto_from_type (&details->fulfillment_state), + (details->no_policy_fulfillment_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 (&details->policy_fulfillment_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id", + policy_details_serial_id), + TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total", + accumulated_total), + GNUNET_PQ_result_spec_uint32 ("fulfillment_state", + fulfillment_state), + GNUNET_PQ_result_spec_end + }; + + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_insert_or_update_policy_details", + params, + rs); +} diff --git a/src/exchangedb/pg_persist_policy_details.h b/src/exchangedb/pg_persist_policy_details.h new file mode 100644 index 000000000..ed9fd95d8 --- /dev/null +++ b/src/exchangedb/pg_persist_policy_details.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_persist_policy_details.h + * @brief implementation of the persist_policy_details function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_PERSIST_POLICY_DETAILS_H +#define PG_PERSIST_POLICY_DETAILS_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/* Persist the details to a policy in the policy_details table. If there + * already exists a policy, update the fields accordingly. + * + * @param details The policy details that should be persisted. If an entry for + * the given details->hash_code exists, the values will be updated. + * @param[out] policy_details_serial_id The row ID of the policy details + * @param[out] accumulated_total The total amount accumulated in that policy + * @param[out] fulfillment_state The state of policy. If the state was Insufficient prior to the call and the provided deposit raises the accumulated_total above the commitment, it will be set to Ready. + * @return query execution status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_persist_policy_details ( + void *cls, + const struct TALER_PolicyDetails *details, + uint64_t *policy_details_serial_id, + struct TALER_Amount *accumulated_total, + enum TALER_PolicyFulfillmentState *fulfillment_state); + +#endif diff --git a/src/exchangedb/pg_release_revolving_shard.c b/src/exchangedb/pg_release_revolving_shard.c new file mode 100644 index 000000000..f176972b6 --- /dev/null +++ b/src/exchangedb/pg_release_revolving_shard.c @@ -0,0 +1,59 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_release_revolving_shard.c + * @brief Implementation of the release_revolving_shard function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_release_revolving_shard.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_release_revolving_shard (void *cls, + const char *job_name, + uint32_t start_row, + uint32_t end_row) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_uint32 (&start_row), + GNUNET_PQ_query_param_uint32 (&end_row), + GNUNET_PQ_query_param_end + }; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Releasing revolving shard %s %u-%u\n", + job_name, + (unsigned int) start_row, + (unsigned int) end_row); + + + PREPARE (pg, + "release_revolving_shard", + "UPDATE revolving_work_shards" + " SET active=FALSE" + " WHERE job_name=$1" + " AND start_row=$2" + " AND end_row=$3"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "release_revolving_shard", + params); +} diff --git a/src/exchangedb/pg_release_revolving_shard.h b/src/exchangedb/pg_release_revolving_shard.h new file mode 100644 index 000000000..f1712f538 --- /dev/null +++ b/src/exchangedb/pg_release_revolving_shard.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_release_revolving_shard.h + * @brief implementation of the release_revolving_shard function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_RELEASE_REVOLVING_SHARD_H +#define PG_RELEASE_REVOLVING_SHARD_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Function called to release a revolving shard + * back into the work pool. Clears the + * "completed" flag. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param job_name name of the operation to grab a word shard for + * @param start_row inclusive start row of the shard + * @param end_row exclusive end row of the shard + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_release_revolving_shard (void *cls, + const char *job_name, + uint32_t start_row, + uint32_t end_row); + +#endif diff --git a/src/exchangedb/pg_reserves_get.c b/src/exchangedb/pg_reserves_get.c new file mode 100644 index 000000000..bea0022dd --- /dev/null +++ b/src/exchangedb/pg_reserves_get.c @@ -0,0 +1,61 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_reserves_get.c + * @brief Implementation of the reserves_get function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_reserves_get.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_reserves_get (void *cls, + struct TALER_EXCHANGEDB_Reserve *reserve) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&reserve->pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance", + &reserve->balance), + GNUNET_PQ_result_spec_timestamp ("expiration_date", + &reserve->expiry), + GNUNET_PQ_result_spec_timestamp ("gc_date", + &reserve->gc), + GNUNET_PQ_result_spec_end + }; + /* Used in #postgres_reserves_get() */ + PREPARE (pg, + "reserves_get", + "SELECT" + " current_balance_val" + ",current_balance_frac" + ",expiration_date" + ",gc_date" + " FROM reserves" + " WHERE reserve_pub=$1" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "reserves_get", + params, + rs); +} diff --git a/src/exchangedb/pg_reserves_get.h b/src/exchangedb/pg_reserves_get.h new file mode 100644 index 000000000..8a96d53ed --- /dev/null +++ b/src/exchangedb/pg_reserves_get.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_reserves_get.h + * @brief implementation of the reserves_get function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_RESERVES_GET_H +#define PG_RESERVES_GET_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Get the summary of a reserve. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param[in,out] reserve the reserve data. The public key of the reserve should be + * set in this structure; it is used to query the database. The balance + * and expiration are then filled accordingly. + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_reserves_get (void *cls, + struct TALER_EXCHANGEDB_Reserve *reserve); + +#endif diff --git a/src/exchangedb/pg_reserves_get_origin.c b/src/exchangedb/pg_reserves_get_origin.c new file mode 100644 index 000000000..fd6c56586 --- /dev/null +++ b/src/exchangedb/pg_reserves_get_origin.c @@ -0,0 +1,57 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_reserves_get_origin.c + * @brief Implementation of the reserves_get_origin function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_reserves_get_origin.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_reserves_get_origin ( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_PaytoHashP *h_payto) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("wire_source_h_payto", + h_payto), + GNUNET_PQ_result_spec_end + }; + + + PREPARE (pg, + "get_h_wire_source_of_reserve", + "SELECT" + " wire_source_h_payto" + " FROM reserves_in" + " WHERE reserve_pub=$1"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_h_wire_source_of_reserve", + params, + rs); +} diff --git a/src/exchangedb/pg_reserves_get_origin.h b/src/exchangedb/pg_reserves_get_origin.h new file mode 100644 index 000000000..22085d8f0 --- /dev/null +++ b/src/exchangedb/pg_reserves_get_origin.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_reserves_get_origin.h + * @brief implementation of the reserves_get_origin function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_RESERVES_GET_ORIGIN_H +#define PG_RESERVES_GET_ORIGIN_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Get the origin of funds of a reserve. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param reserve_pub public key of the reserve + * @param[out] h_payto set to hash of the wire source payto://-URI + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_reserves_get_origin ( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_PaytoHashP *h_payto); + +#endif diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c new file mode 100644 index 000000000..38524bd61 --- /dev/null +++ b/src/exchangedb/pg_reserves_in_insert.c @@ -0,0 +1,297 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_reserves_in_insert.c + * @brief Implementation of the reserves_in_insert function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_reserves_in_insert.h" +#include "pg_helper.h" +#include "pg_start.h" +#include "pg_start_read_committed.h" +#include "pg_commit.h" +#include "pg_reserves_get.h" +#include "pg_reserves_update.h" +#include "pg_setup_wire_target.h" +#include "pg_event_notify.h" +/** + * Generate event notification for the reserve + * change. + * + * @param pg plugin state + * @param reserve_pub reserve to notfiy on + */ + +static void +notify_on_reserve (struct PostgresClosure *pg, + const struct TALER_ReservePublicKeyP *reserve_pub) +{ + struct TALER_ReserveEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING), + .reserve_pub = *reserve_pub + }; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Notifying on reserve!\n"); + TEH_PG_event_notify (pg, + &rep.header, + NULL, + 0); +} + +enum GNUNET_DB_QueryStatus +TEH_PG_reserves_in_insert (void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *balance, + struct GNUNET_TIME_Timestamp execution_time, + const char *sender_account_details, + const char *exchange_account_section, + uint64_t wire_ref) +{ + struct PostgresClosure *pg = cls; + enum GNUNET_DB_QueryStatus qs1; + struct TALER_EXCHANGEDB_Reserve reserve; + struct GNUNET_TIME_Timestamp expiry; + struct GNUNET_TIME_Timestamp gc; + uint64_t reserve_uuid; + + reserve.pub = *reserve_pub; + expiry = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add (execution_time.abs_time, + pg->idle_reserve_expiration_time)); + gc = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), + pg->legal_reserve_expiration_time)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Creating reserve %s with expiration in %s\n", + TALER_B2S (reserve_pub), + GNUNET_STRINGS_relative_time_to_string ( + pg->idle_reserve_expiration_time, + GNUNET_NO)); + /* Optimistically assume this is a new reserve, create balance for the first + time; we do this before adding the actual transaction to "reserves_in", + as for a new reserve it can't be a duplicate 'add' operation, and as + the 'add' operation needs the reserve entry as a foreign key. */ + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + TALER_PQ_query_param_amount (balance), + GNUNET_PQ_query_param_timestamp (&expiry), + GNUNET_PQ_query_param_timestamp (&gc), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("reserve_uuid", + &reserve_uuid), + GNUNET_PQ_result_spec_end + }; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Reserve does not exist; creating a new one\n"); + /* Note: query uses 'on conflict do nothing' */ + + + + PREPARE (pg, + "reserve_create", + "INSERT INTO reserves " + "(reserve_pub" + ",current_balance_val" + ",current_balance_frac" + ",expiration_date" + ",gc_date" + ") VALUES " + "($1, $2, $3, $4, $5)" + " ON CONFLICT DO NOTHING" + " RETURNING reserve_uuid;"); + + qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "reserve_create", + params, + rs); + if (qs1 < 0) + return qs1; + } + + /* Create new incoming transaction, "ON CONFLICT DO NOTHING" + is again used to guard against duplicates. */ + { + enum GNUNET_DB_QueryStatus qs2; + enum GNUNET_DB_QueryStatus qs3; + struct TALER_PaytoHashP h_payto; + + qs3 = TEH_PG_setup_wire_target (pg, + sender_account_details, + &h_payto); + if (qs3 < 0) + return qs3; + /* We do not have the UUID, so insert by public key */ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&reserve.pub), + GNUNET_PQ_query_param_uint64 (&wire_ref), + TALER_PQ_query_param_amount (balance), + GNUNET_PQ_query_param_string (exchange_account_section), + GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_timestamp (&execution_time), + GNUNET_PQ_query_param_end + }; + + + PREPARE (pg, + "reserves_in_add_transaction", + "INSERT INTO reserves_in " + "(reserve_pub" + ",wire_reference" + ",credit_val" + ",credit_frac" + ",exchange_account_section" + ",wire_source_h_payto" + ",execution_date" + ") VALUES ($1, $2, $3, $4, $5, $6, $7)" + " ON CONFLICT DO NOTHING;"); + qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "reserves_in_add_transaction", + params); + /* qs2 could be 0 as statement used 'ON CONFLICT DO NOTHING' */ + if (0 >= qs2) + { + if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs2) && + (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1) ) + { + /* Conflict for the transaction, but the reserve was + just now created, that should be impossible. */ + GNUNET_break (0); /* should be impossible: reserve was fresh, + but transaction already known */ + return GNUNET_DB_STATUS_HARD_ERROR; + } + /* Transaction was already known or error. We are finished. */ + return qs2; + } + } + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs1) + { + /* New reserve, we are finished */ + notify_on_reserve (pg, + reserve_pub); + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + + /* we were wrong with our optimistic assumption: + reserve did already exist, need to do an update instead */ + { + /* We need to move away from 'read committed' to serializable. + Also, we know that it should be safe to commit at this point. + (We are only run in a larger transaction for performance.) */ + enum GNUNET_DB_QueryStatus cs; + + cs = TEH_PG_commit(pg); + if (cs < 0) + return cs; + if (GNUNET_OK != + TEH_PG_start (pg, + "reserve-update-serializable")) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + } + { + enum GNUNET_DB_QueryStatus reserve_exists; + + reserve_exists = TEH_PG_reserves_get (pg, + &reserve); + switch (reserve_exists) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return reserve_exists; + case GNUNET_DB_STATUS_SOFT_ERROR: + return reserve_exists; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + /* First we got a conflict, but then we cannot select? Very strange. */ + GNUNET_break (0); + return GNUNET_DB_STATUS_SOFT_ERROR; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + /* continued below */ + break; + } + } + + { + struct TALER_EXCHANGEDB_Reserve updated_reserve; + enum GNUNET_DB_QueryStatus qs3; + + /* If the reserve already existed, we need to still update the + balance; we do this after checking for duplication, as + otherwise we might have to actually pay the cost to roll this + back for duplicate transactions; like this, we should virtually + never actually have to rollback anything. */ + updated_reserve.pub = reserve.pub; + if (0 > + TALER_amount_add (&updated_reserve.balance, + &reserve.balance, + balance)) + { + /* currency overflow or incompatible currency */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Attempt to deposit incompatible amount into reserve\n"); + return GNUNET_DB_STATUS_HARD_ERROR; + } + updated_reserve.expiry = GNUNET_TIME_timestamp_max (expiry, + reserve.expiry); + updated_reserve.gc = GNUNET_TIME_timestamp_max (gc, + reserve.gc); + qs3 = TEH_PG_reserves_update (pg, + &updated_reserve); + switch (qs3) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return qs3; + case GNUNET_DB_STATUS_SOFT_ERROR: + return qs3; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + /* How can the UPDATE not work here? Very strange. */ + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + /* continued below */ + break; + } + } + notify_on_reserve (pg, + reserve_pub); + /* Go back to original transaction mode */ + { + enum GNUNET_DB_QueryStatus cs; + + cs = TEH_PG_commit (pg); + if (cs < 0) + return cs; + if (GNUNET_OK != + TEH_PG_start_read_committed (pg, "reserve-insert-continued")) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + } + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; +} diff --git a/src/exchangedb/pg_reserves_in_insert.h b/src/exchangedb/pg_reserves_in_insert.h new file mode 100644 index 000000000..854019386 --- /dev/null +++ b/src/exchangedb/pg_reserves_in_insert.h @@ -0,0 +1,51 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_reserves_in_insert.h + * @brief implementation of the reserves_in_insert function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_RESERVES_IN_INSERT_H +#define PG_RESERVES_IN_INSERT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Insert an incoming transaction into reserves. New reserves are also + * created through this function. Started within the scope of an ongoing + * transaction. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param reserve_pub public key of the reserve + * @param balance the amount that has to be added to the reserve + * @param execution_time when was the amount added + * @param sender_account_details account information for the sender (payto://-URL) + * @param exchange_account_section name of the section in the configuration for the exchange's + * account into which the deposit was made + * @param wire_ref unique reference identifying the wire transfer + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_reserves_in_insert (void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *balance, + struct GNUNET_TIME_Timestamp execution_time, + const char *sender_account_details, + const char *exchange_account_section, + uint64_t wire_ref); + +#endif diff --git a/src/exchangedb/pg_reserves_update.c b/src/exchangedb/pg_reserves_update.c new file mode 100644 index 000000000..4a8861020 --- /dev/null +++ b/src/exchangedb/pg_reserves_update.c @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_reserves_update.c + * @brief Implementation of the reserves_update function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_reserves_update.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_reserves_update (void *cls, + const struct TALER_EXCHANGEDB_Reserve *reserve) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&reserve->expiry), + GNUNET_PQ_query_param_timestamp (&reserve->gc), + TALER_PQ_query_param_amount (&reserve->balance), + GNUNET_PQ_query_param_auto_from_type (&reserve->pub), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "reserve_update", + "UPDATE reserves" + " SET" + " expiration_date=$1" + ",gc_date=$2" + ",current_balance_val=$3" + ",current_balance_frac=$4" + " WHERE reserve_pub=$5;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "reserve_update", + params); +} diff --git a/src/exchangedb/pg_reserves_update.h b/src/exchangedb/pg_reserves_update.h new file mode 100644 index 000000000..24cf671da --- /dev/null +++ b/src/exchangedb/pg_reserves_update.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_reserves_update.h + * @brief implementation of the reserves_update function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_RESERVES_UPDATE_H +#define PG_RESERVES_UPDATE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Updates a reserve with the data from the given reserve structure. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param reserve the reserve structure whose data will be used to update the + * corresponding record in the database. + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_reserves_update (void *cls, + const struct TALER_EXCHANGEDB_Reserve *reserve); + +#endif diff --git a/src/exchangedb/pg_select_aggregation_transient.c b/src/exchangedb/pg_select_aggregation_transient.c new file mode 100644 index 000000000..f3e39c532 --- /dev/null +++ b/src/exchangedb/pg_select_aggregation_transient.c @@ -0,0 +1,67 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_aggregation_transient.c + * @brief Implementation of the select_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_aggregation_transient.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_aggregation_transient ( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *exchange_account_section, + struct TALER_WireTransferIdentifierRawP *wtid, + struct TALER_Amount *total) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_string (exchange_account_section), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + total), + GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", + wtid), + GNUNET_PQ_result_spec_end + }; + /* Used in #postgres_select_aggregation_transient() */ + PREPARE (pg, + "select_aggregation_transient", + "SELECT" + " amount_val" + " ,amount_frac" + " ,wtid_raw" + " FROM aggregation_transient" + " WHERE wire_target_h_payto=$1" + " AND merchant_pub=$2" + " AND exchange_account_section=$3;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_aggregation_transient", + params, + rs); +} diff --git a/src/exchangedb/pg_select_aggregation_transient.h b/src/exchangedb/pg_select_aggregation_transient.h new file mode 100644 index 000000000..fd82a97aa --- /dev/null +++ b/src/exchangedb/pg_select_aggregation_transient.h @@ -0,0 +1,47 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_aggregation_transient.h + * @brief implementation of the select_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_AGGREGATION_TRANSIENT_H +#define PG_SELECT_AGGREGATION_TRANSIENT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Find existing entry in the transient aggregation table. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto destination of the wire transfer + * @param merchant_pub public key of the merchant receiving the transfer + * @param exchange_account_section exchange account to use + * @param[out] wtid set to the raw wire transfer identifier to be used + * @param[out] total existing amount to be wired in the future + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_aggregation_transient ( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *exchange_account_section, + struct TALER_WireTransferIdentifierRawP *wtid, + struct TALER_Amount *total); +#endif diff --git a/src/exchangedb/pg_select_auditor_denom_sig.c b/src/exchangedb/pg_select_auditor_denom_sig.c new file mode 100644 index 000000000..90e0c5096 --- /dev/null +++ b/src/exchangedb/pg_select_auditor_denom_sig.c @@ -0,0 +1,67 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_auditor_denom_sig.c + * @brief Implementation of the select_auditor_denom_sig function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_auditor_denom_sig.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_auditor_denom_sig ( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct TALER_AuditorSignatureP *auditor_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (auditor_pub), + GNUNET_PQ_query_param_auto_from_type (h_denom_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("auditor_sig", + auditor_sig), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "select_auditor_denom_sig", + "SELECT" + " auditor_sig" + " FROM auditor_denom_sigs" + " WHERE auditor_uuid=" + " (SELECT auditor_uuid" + " FROM auditors" + " WHERE auditor_pub=$1)" + " AND denominations_serial=" + " (SELECT denominations_serial" + " FROM denominations" + " WHERE denom_pub_hash=$2);"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_auditor_denom_sig", + params, + rs); +} + diff --git a/src/exchangedb/pg_select_auditor_denom_sig.h b/src/exchangedb/pg_select_auditor_denom_sig.h new file mode 100644 index 000000000..0f635cf42 --- /dev/null +++ b/src/exchangedb/pg_select_auditor_denom_sig.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_auditor_denom_sig.h + * @brief implementation of the select_auditor_denom_sig function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_AUDITOR_DENOM_SIG_H +#define PG_SELECT_AUDITOR_DENOM_SIG_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Select information about an auditor auditing a denomination key. + * + * @param cls closure + * @param h_denom_pub the audited denomination + * @param auditor_pub the auditor's key + * @param[out] auditor_sig set to signature affirming the auditor's audit activity + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_auditor_denom_sig ( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct TALER_AuditorSignatureP *auditor_sig); + +#endif diff --git a/src/exchangedb/pg_select_deposits_above_serial_id.c b/src/exchangedb/pg_select_deposits_above_serial_id.c new file mode 100644 index 000000000..52f96e5f4 --- /dev/null +++ b/src/exchangedb/pg_select_deposits_above_serial_id.c @@ -0,0 +1,197 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_deposits_above_serial_id.c + * @brief Implementation of the select_deposits_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_deposits_above_serial_id.h" +#include "pg_helper.h" + +/** + * Closure for #deposit_serial_helper_cb(). + */ +struct DepositSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_DepositCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct DepositSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +deposit_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct DepositSerialContext *dsc = cls; + struct PostgresClosure *pg = dsc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ret = dsc->cb (dsc->cb_cls, + rowid, + exchange_timestamp, + &deposit, + &denom_pub, + done); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + +enum GNUNET_DB_QueryStatus +TEH_PG_select_deposits_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_DepositCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct DepositSerialContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Fetch deposits with rowid '\geq' the given parameter */ + PREPARE (pg, + "audit_get_deposits_incr", + "SELECT" + " amount_with_fee_val" + ",amount_with_fee_frac" + ",wallet_timestamp" + ",exchange_timestamp" + ",merchant_pub" + ",denom.denom_pub" + ",kc.coin_pub" + ",kc.age_commitment_hash" + ",coin_sig" + ",refund_deadline" + ",wire_deadline" + ",h_contract_terms" + ",wire_salt" + ",payto_uri AS receiver_wire_account" + ",done" + ",deposit_serial_id" + " FROM deposits" + " JOIN wire_targets USING (wire_target_h_payto)" + " JOIN known_coins kc USING (coin_pub)" + " JOIN denominations denom USING (denominations_serial)" + " WHERE (" + " (deposit_serial_id>=$1)" + " )" + " ORDER BY deposit_serial_id ASC;"); + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_deposits_incr", + params, + &deposit_serial_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_deposits_above_serial_id.h b/src/exchangedb/pg_select_deposits_above_serial_id.h new file mode 100644 index 000000000..e29937e08 --- /dev/null +++ b/src/exchangedb/pg_select_deposits_above_serial_id.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_deposits_above_serial_id.h + * @brief implementation of the select_deposits_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_DEPOSITS_ABOVE_SERIAL_ID_H +#define PG_SELECT_DEPOSITS_ABOVE_SERIAL_ID_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Select deposits above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_deposits_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_DepositCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_select_deposits_missing_wire.c b/src/exchangedb/pg_select_deposits_missing_wire.c new file mode 100644 index 000000000..2a260a369 --- /dev/null +++ b/src/exchangedb/pg_select_deposits_missing_wire.c @@ -0,0 +1,176 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_deposits_missing_wire.c + * @brief Implementation of the select_deposits_missing_wire function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_deposits_missing_wire.h" +#include "pg_helper.h" + +/** + * Closure for #missing_wire_cb(). + */ +struct MissingWireContext +{ + /** + * Function to call per result. + */ + TALER_EXCHANGEDB_WireMissingCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Set to #GNUNET_SYSERR on error. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct MissingWireContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +missing_wire_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct MissingWireContext *mwc = cls; + struct PostgresClosure *pg = mwc->pg; + + while (0 < num_results) + { + uint64_t rowid; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_Amount amount; + char *payto_uri; + struct GNUNET_TIME_Timestamp deadline; + bool done; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("deposit_serial_id", + &rowid), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &coin_pub), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &amount), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri), + GNUNET_PQ_result_spec_timestamp ("wire_deadline", + &deadline), + GNUNET_PQ_result_spec_bool ("done", + &done), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + --num_results)) + { + GNUNET_break (0); + mwc->status = GNUNET_SYSERR; + return; + } + mwc->cb (mwc->cb_cls, + rowid, + &coin_pub, + &amount, + payto_uri, + deadline, + done); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_deposits_missing_wire (void *cls, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + TALER_EXCHANGEDB_WireMissingCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_timestamp (&end_date), + GNUNET_PQ_query_param_end + }; + struct MissingWireContext mwc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Used in #postgres_select_deposits_missing_wire */ + // FIXME: used by the auditor; can probably be done + // smarter by checking if 'done' or 'blocked' + // are set correctly when going over deposits, instead + // of JOINing with refunds. + PREPARE (pg, + "deposits_get_overdue", + "SELECT" + " deposit_serial_id" + ",coin_pub" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",payto_uri" + ",wire_deadline" + ",done" + " FROM deposits d" + " JOIN known_coins" + " USING (coin_pub)" + " JOIN wire_targets" + " USING (wire_target_h_payto)" + " WHERE wire_deadline >= $1" + " AND wire_deadline < $2" + " AND NOT (EXISTS (SELECT 1" + " FROM refunds r" + " WHERE (r.coin_pub = d.coin_pub) AND (r.deposit_serial_id = d.deposit_serial_id))" + " OR EXISTS (SELECT 1" + " FROM aggregation_tracking" + " WHERE (aggregation_tracking.deposit_serial_id = d.deposit_serial_id)))" + " ORDER BY wire_deadline ASC"); + + + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "deposits_get_overdue", + params, + &missing_wire_cb, + &mwc); + if (GNUNET_OK != mwc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_deposits_missing_wire.h b/src/exchangedb/pg_select_deposits_missing_wire.h new file mode 100644 index 000000000..f702c2417 --- /dev/null +++ b/src/exchangedb/pg_select_deposits_missing_wire.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_deposits_missing_wire.h + * @brief implementation of the select_deposits_missing_wire function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_DEPOSITS_MISSING_WIRE_H +#define PG_SELECT_DEPOSITS_MISSING_WIRE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Select all of those deposits in the database for which we do + * not have a wire transfer (or a refund) and which should have + * been deposited between @a start_date and @a end_date. + * + * @param cls closure + * @param start_date lower bound on the requested wire execution date + * @param end_date upper bound on the requested wire execution date + * @param cb function to call on all such deposits + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_deposits_missing_wire (void *cls, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + TALER_EXCHANGEDB_WireMissingCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_select_history_requests_above_serial_id.c b/src/exchangedb/pg_select_history_requests_above_serial_id.c new file mode 100644 index 000000000..81e038114 --- /dev/null +++ b/src/exchangedb/pg_select_history_requests_above_serial_id.c @@ -0,0 +1,159 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_history_requests_above_serial_id.c + * @brief Implementation of the select_history_requests_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_history_requests_above_serial_id.h" +#include "pg_helper.h" + +/** + * Closure for #purse_deposit_serial_helper_cb(). + */ +struct HistoryRequestSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_HistoryRequestCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct HistoryRequestSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +history_request_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct HistoryRequestSerialContext *dsc = cls; + struct PostgresClosure *pg = dsc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ret = dsc->cb (dsc->cb_cls, + rowid, + &history_fee, + ts, + &reserve_pub, + &reserve_sig); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_history_requests_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_HistoryRequestCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct HistoryRequestSerialContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + PREPARE (pg, + "audit_get_history_requests_incr", + "SELECT" + " history_request_serial_id" + ",history_fee_val" + ",history_fee_frac" + ",request_timestamp" + ",reserve_pub" + ",reserve_sig" + " FROM history_requests" + " WHERE (" + " (history_request_serial_id>=$1)" + " )" + " ORDER BY history_request_serial_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_history_requests_incr", + params, + &history_request_serial_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_history_requests_above_serial_id.h b/src/exchangedb/pg_select_history_requests_above_serial_id.h new file mode 100644 index 000000000..b16efdce1 --- /dev/null +++ b/src/exchangedb/pg_select_history_requests_above_serial_id.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_history_requests_above_serial_id.h + * @brief implementation of the select_history_requests_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_HISTORY_REQUESTS_ABOVE_SERIAL_ID_H +#define PG_SELECT_HISTORY_REQUESTS_ABOVE_SERIAL_ID_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Select history requests above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_history_requests_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_HistoryRequestCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_select_purse_by_merge_pub.c b/src/exchangedb/pg_select_purse_by_merge_pub.c new file mode 100644 index 000000000..965b27ba3 --- /dev/null +++ b/src/exchangedb/pg_select_purse_by_merge_pub.c @@ -0,0 +1,83 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_purse_by_merge_pub.c + * @brief Implementation of the select_purse_by_merge_pub function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_purse_by_merge_pub.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_select_purse_by_merge_pub ( + void *cls, + const struct TALER_PurseMergePublicKeyP *merge_pub, + struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp *purse_expiration, + struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t *age_limit, + struct TALER_Amount *target_amount, + struct TALER_Amount *balance, + struct TALER_PurseContractSignatureP *purse_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (merge_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + purse_pub), + GNUNET_PQ_result_spec_timestamp ("purse_expiration", + purse_expiration), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + h_contract_terms), + GNUNET_PQ_result_spec_uint32 ("age_limit", + age_limit), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + target_amount), + TALER_PQ_RESULT_SPEC_AMOUNT ("balance", + balance), + GNUNET_PQ_result_spec_auto_from_type ("purse_sig", + purse_sig), + GNUNET_PQ_result_spec_end + }; + + + PREPARE (pg, + "select_purse_by_merge_pub", + "SELECT " + " purse_pub" + ",purse_expiration" + ",h_contract_terms" + ",age_limit" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",balance_val" + ",balance_frac" + ",purse_sig" + " FROM purse_requests" + " WHERE merge_pub=$1;"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_purse_by_merge_pub", + params, + rs); +} diff --git a/src/exchangedb/pg_select_purse_by_merge_pub.h b/src/exchangedb/pg_select_purse_by_merge_pub.h new file mode 100644 index 000000000..2a7667132 --- /dev/null +++ b/src/exchangedb/pg_select_purse_by_merge_pub.h @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_purse_by_merge_pub.h + * @brief implementation of the select_purse_by_merge_pub function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_PURSE_BY_MERGE_PUB_H +#define PG_SELECT_PURSE_BY_MERGE_PUB_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to return meta data about a purse by the + * merge capability key. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param merge_pub public key representing the merge capability + * @param[out] purse_pub public key of the purse + * @param[out] purse_expiration when would an unmerged purse expire + * @param[out] h_contract_terms contract associated with the purse + * @param[out] age_limit the age limit for deposits into the purse + * @param[out] target_amount amount to be put into the purse + * @param[out] balance amount put so far into the purse + * @param[out] purse_sig signature of the purse over the initialization data + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_purse_by_merge_pub ( + void *cls, + const struct TALER_PurseMergePublicKeyP *merge_pub, + struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp *purse_expiration, + struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t *age_limit, + struct TALER_Amount *target_amount, + struct TALER_Amount *balance, + struct TALER_PurseContractSignatureP *purse_sig); +#endif diff --git a/src/exchangedb/pg_select_purse_decisions_above_serial_id.c b/src/exchangedb/pg_select_purse_decisions_above_serial_id.c new file mode 100644 index 000000000..2368f2d3e --- /dev/null +++ b/src/exchangedb/pg_select_purse_decisions_above_serial_id.c @@ -0,0 +1,164 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_purse_decisions_above_serial_id.c + * @brief Implementation of the select_purse_decisions_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_purse_decisions_above_serial_id.h" +#include "pg_helper.h" + +/** + * Closure for #purse_decision_serial_helper_cb(). + */ +struct PurseDecisionSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_PurseDecisionCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct PurseRefundSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +purse_decision_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct PurseDecisionSerialContext *dsc = cls; + struct PostgresClosure *pg = dsc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ret = dsc->cb (dsc->cb_cls, + rowid, + &purse_pub, + no_reserve ? NULL : &reserve_pub, + &val); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_purse_decisions_above_serial_id ( + void *cls, + uint64_t serial_id, + bool refunded, + TALER_EXCHANGEDB_PurseDecisionCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_bool (refunded), + GNUNET_PQ_query_param_end + }; + struct PurseDecisionSerialContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "audit_get_purse_decisions_incr", + "SELECT" + " pd.purse_pub" + ",pm.reserve_pub" + ",pd.purse_decision_serial_id" + ",pr.amount_with_fee_val" + ",pr.amount_with_fee_frac" + " FROM purse_decision pd" + " JOIN purse_requests pr ON (pd.purse_pub = pr.purse_pub)" + " LEFT JOIN purse_merges pm ON (pm.purse_pub = pd.purse_pub)" + " WHERE (" + " (purse_decision_serial_id>=$1) AND " + " (refunded=$2)" + " )" + " ORDER BY purse_decision_serial_id ASC;"); + + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_purse_decisions_incr", + params, + &purse_decision_serial_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_purse_decisions_above_serial_id.h b/src/exchangedb/pg_select_purse_decisions_above_serial_id.h new file mode 100644 index 000000000..53ab31c80 --- /dev/null +++ b/src/exchangedb/pg_select_purse_decisions_above_serial_id.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_purse_decisions_above_serial_id.h + * @brief implementation of the select_purse_decisions_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_PURSE_DECISIONS_ABOVE_SERIAL_ID_H +#define PG_SELECT_PURSE_DECISIONS_ABOVE_SERIAL_ID_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Select purse decisions above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param refunded which refund status to select for + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_purse_decisions_above_serial_id ( + void *cls, + uint64_t serial_id, + bool refunded, + TALER_EXCHANGEDB_PurseDecisionCallback cb, + void *cb_cls); +#endif diff --git a/src/exchangedb/pg_select_purse_deposits_by_purse.c b/src/exchangedb/pg_select_purse_deposits_by_purse.c new file mode 100644 index 000000000..5fe7e014b --- /dev/null +++ b/src/exchangedb/pg_select_purse_deposits_by_purse.c @@ -0,0 +1,153 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_purse_deposits_by_purse.c + * @brief Implementation of the select_purse_deposits_by_purse function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_purse_deposits_by_purse.h" +#include "pg_helper.h" + +/** + * Closure for #purse_refund_coin_helper_cb(). + */ +struct PurseRefundCoinContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_PurseRefundCoinCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct PurseRefundCoinContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +purse_refund_coin_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct PurseRefundCoinContext *dsc = cls; + struct PostgresClosure *pg = dsc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ret = dsc->cb (dsc->cb_cls, + rowid, + &amount_with_fee, + &coin_pub, + &denom_pub); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_purse_deposits_by_purse ( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + TALER_EXCHANGEDB_PurseRefundCoinCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_end + }; + struct PurseRefundCoinContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "audit_get_purse_deposits_by_purse", + "SELECT" + " pd.purse_deposit_serial_id" + ",pd.amount_with_fee_val" + ",pd.amount_with_fee_frac" + ",pd.coin_pub" + ",denom.denom_pub" + " FROM purse_deposits pd" + " JOIN known_coins kc USING (coin_pub)" + " JOIN denominations denom USING (denominations_serial)" + " WHERE purse_pub=$1;"); + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_purse_deposits_by_purse", + params, + &purse_refund_coin_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_purse_deposits_by_purse.h b/src/exchangedb/pg_select_purse_deposits_by_purse.h new file mode 100644 index 000000000..203f9a151 --- /dev/null +++ b/src/exchangedb/pg_select_purse_deposits_by_purse.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_purse_deposits_by_purse.h + * @brief implementation of the select_purse_deposits_by_purse function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_PURSE_DEPOSITS_BY_PURSE_H +#define PG_SELECT_PURSE_DEPOSITS_BY_PURSE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Select coin affected by purse refund. + * + * @param cls closure + * @param purse_pub purse that was refunded + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_purse_deposits_by_purse ( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + TALER_EXCHANGEDB_PurseRefundCoinCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_select_recoup_above_serial_id.c b/src/exchangedb/pg_select_recoup_above_serial_id.c new file mode 100644 index 000000000..9047a86f8 --- /dev/null +++ b/src/exchangedb/pg_select_recoup_above_serial_id.c @@ -0,0 +1,196 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_recoup_above_serial_id.c + * @brief Implementation of the select_recoup_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_recoup_above_serial_id.h" +#include "pg_helper.h" + + + +/** + * Closure for #recoup_serial_helper_cb(). + */ +struct RecoupSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_RecoupCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct RecoupSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +recoup_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct RecoupSerialContext *psc = cls; + struct PostgresClosure *pg = psc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ret = psc->cb (psc->cb_cls, + rowid, + timestamp, + &amount, + &reserve_pub, + &coin, + &denom_pub, + &coin_sig, + &coin_blind); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + +enum GNUNET_DB_QueryStatus +TEH_PG_select_recoup_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_RecoupCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct RecoupSerialContext psc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Used in #postgres_select_recoup_above_serial_id() to obtain recoup transactions */ + PREPARE (pg, + "recoup_get_incr", + "SELECT" + " recoup_uuid" + ",recoup_timestamp" + ",reserves.reserve_pub" + ",coins.coin_pub" + ",coin_sig" + ",coin_blind" + ",ro.h_blind_ev" + ",denoms.denom_pub_hash" + ",coins.denom_sig" + ",coins.age_commitment_hash" + ",denoms.denom_pub" + ",amount_val" + ",amount_frac" + " FROM recoup" + " JOIN known_coins coins" + " USING (coin_pub)" + " JOIN reserves_out ro" + " USING (reserve_out_serial_id)" + " JOIN reserves" + " USING (reserve_uuid)" + " JOIN denominations denoms" + " ON (coins.denominations_serial = denoms.denominations_serial)" + " WHERE recoup_uuid>=$1" + " ORDER BY recoup_uuid ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "recoup_get_incr", + params, + &recoup_serial_helper_cb, + &psc); + if (GNUNET_OK != psc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_recoup_above_serial_id.h b/src/exchangedb/pg_select_recoup_above_serial_id.h new file mode 100644 index 000000000..9be0b5c35 --- /dev/null +++ b/src/exchangedb/pg_select_recoup_above_serial_id.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_recoup_above_serial_id.h + * @brief implementation of the select_recoup_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_RECOUP_ABOVE_SERIAL_ID_H +#define PG_SELECT_RECOUP_ABOVE_SERIAL_ID_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Function called to select recoup requests the exchange + * received, ordered by serial ID (monotonically increasing). + * + * @param cls closure + * @param serial_id lowest serial ID to include (select larger or equal) + * @param cb function to call for ONE unfinished item + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_recoup_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_RecoupCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c new file mode 100644 index 000000000..a3f6bc93d --- /dev/null +++ b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c @@ -0,0 +1,207 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_recoup_refresh_above_serial_id.c + * @brief Implementation of the select_recoup_refresh_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_recoup_refresh_above_serial_id.h" +#include "pg_helper.h" + + +/** + * Closure for #recoup_refresh_serial_helper_cb(). + */ +struct RecoupRefreshSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_RecoupRefreshCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct RecoupRefreshSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +recoup_refresh_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct RecoupRefreshSerialContext *psc = cls; + struct PostgresClosure *pg = psc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ret = psc->cb (psc->cb_cls, + rowid, + timestamp, + &amount, + &old_coin_pub, + &old_denom_pub_hash, + &coin, + &denom_pub, + &coin_sig, + &coin_blind); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_recoup_refresh_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_RecoupRefreshCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct RecoupRefreshSerialContext psc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Used in #postgres_select_recoup_refresh_above_serial_id() to obtain + recoup-refresh transactions */ + PREPARE (pg, + "recoup_refresh_get_incr", + "SELECT" + " recoup_refresh_uuid" + ",recoup_timestamp" + ",old_coins.coin_pub AS old_coin_pub" + ",new_coins.age_commitment_hash" + ",old_denoms.denom_pub_hash AS old_denom_pub_hash" + ",new_coins.coin_pub As coin_pub" + ",coin_sig" + ",coin_blind" + ",new_denoms.denom_pub AS denom_pub" + ",rrc.h_coin_ev AS h_blind_ev" + ",new_denoms.denom_pub_hash" + ",new_coins.denom_sig AS denom_sig" + ",amount_val" + ",amount_frac" + " FROM recoup_refresh" + " INNER JOIN refresh_revealed_coins rrc" + " USING (rrc_serial)" + " INNER JOIN refresh_commitments rfc" + " ON (rrc.melt_serial_id = rfc.melt_serial_id)" + " INNER JOIN known_coins old_coins" + " ON (rfc.old_coin_pub = old_coins.coin_pub)" + " INNER JOIN known_coins new_coins" + " ON (new_coins.coin_pub = recoup_refresh.coin_pub)" + " INNER JOIN denominations new_denoms" + " ON (new_coins.denominations_serial = new_denoms.denominations_serial)" + " INNER JOIN denominations old_denoms" + " ON (old_coins.denominations_serial = old_denoms.denominations_serial)" + " WHERE recoup_refresh_uuid>=$1" + " ORDER BY recoup_refresh_uuid ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "recoup_refresh_get_incr", + params, + &recoup_refresh_serial_helper_cb, + &psc); + if (GNUNET_OK != psc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_recoup_refresh_above_serial_id.h b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.h new file mode 100644 index 000000000..0d7b72fc3 --- /dev/null +++ b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_recoup_refresh_above_serial_id.h + * @brief implementation of the select_recoup_refresh_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_RECOUP_REFRESH_ABOVE_SERIAL_ID_H +#define PG_SELECT_RECOUP_REFRESH_ABOVE_SERIAL_ID_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to select recoup requests the exchange received for + * refreshed coins, ordered by serial ID (monotonically increasing). + * + * @param cls closure + * @param serial_id lowest serial ID to include (select larger or equal) + * @param cb function to call for ONE unfinished item + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_recoup_refresh_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_RecoupRefreshCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_select_refreshes_above_serial_id.c b/src/exchangedb/pg_select_refreshes_above_serial_id.c new file mode 100644 index 000000000..d2b4a7fa6 --- /dev/null +++ b/src/exchangedb/pg_select_refreshes_above_serial_id.c @@ -0,0 +1,185 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_refreshes_above_serial_id.c + * @brief Implementation of the select_refreshes_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_refreshes_above_serial_id.h" +#include "pg_helper.h" + + +/** + * Closure for #refreshs_serial_helper_cb(). + */ +struct RefreshsSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_RefreshesCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct RefreshsSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +refreshs_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct RefreshsSerialContext *rsc = cls; + struct PostgresClosure *pg = rsc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + + ret = rsc->cb (rsc->cb_cls, + rowid, + &denom_pub, + ac_isnull ? NULL : &h_age_commitment, + &coin_pub, + &coin_sig, + &amount_with_fee, + noreveal_index, + &rc); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + + + + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_refreshes_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_RefreshesCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct RefreshsSerialContext rsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + /* Used in #postgres_select_refreshes_above_serial_id() to fetch + refresh session with id '\geq' the given parameter */ + PREPARE (pg, + "audit_get_refresh_commitments_incr", + "SELECT" + " denom.denom_pub" + ",kc.coin_pub AS old_coin_pub" + ",kc.age_commitment_hash" + ",old_coin_sig" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",noreveal_index" + ",melt_serial_id" + ",rc" + " FROM refresh_commitments" + " JOIN known_coins kc" + " ON (refresh_commitments.old_coin_pub = kc.coin_pub)" + " JOIN denominations denom" + " ON (kc.denominations_serial = denom.denominations_serial)" + " WHERE melt_serial_id>=$1" + " ORDER BY melt_serial_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_refresh_commitments_incr", + params, + &refreshs_serial_helper_cb, + &rsc); + if (GNUNET_OK != rsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_refreshes_above_serial_id.h b/src/exchangedb/pg_select_refreshes_above_serial_id.h new file mode 100644 index 000000000..2d1db275c --- /dev/null +++ b/src/exchangedb/pg_select_refreshes_above_serial_id.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_refreshes_above_serial_id.h + * @brief implementation of the select_refreshes_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_REFRESHES_ABOVE_SERIAL_ID_H +#define PG_SELECT_REFRESHES_ABOVE_SERIAL_ID_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Select refresh sessions above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_refreshes_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_RefreshesCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_select_refunds_above_serial_id.c b/src/exchangedb/pg_select_refunds_above_serial_id.c new file mode 100644 index 000000000..a5f7d3df6 --- /dev/null +++ b/src/exchangedb/pg_select_refunds_above_serial_id.c @@ -0,0 +1,211 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_refunds_above_serial_id.c + * @brief Implementation of the select_refunds_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_refunds_above_serial_id.h" +#include "pg_helper.h" + +/** + * Closure for #refunds_serial_helper_cb(). + */ +struct RefundsSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_RefundCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct RefundsSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +refunds_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct RefundsSerialContext *rsc = cls; + struct PostgresClosure *pg = rsc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&rowid), + GNUNET_PQ_query_param_end + }; + struct TALER_Amount amount_with_fee; + uint64_t s_f; + uint64_t s_v; + struct GNUNET_PQ_ResultSpec rs2[] = { + GNUNET_PQ_result_spec_uint64 ("s_v", + &s_v), + GNUNET_PQ_result_spec_uint64 ("s_f", + &s_f), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &amount_with_fee), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + qs = GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "test_refund_full", + params, + rs2); + if (qs <= 0) + { + GNUNET_break (0); + rsc->status = GNUNET_SYSERR; + return; + } + /* normalize */ + s_v += s_f / TALER_AMOUNT_FRAC_BASE; + s_f %= TALER_AMOUNT_FRAC_BASE; + full_refund = (s_v >= amount_with_fee.value) && + (s_f >= amount_with_fee.fraction); + } + ret = rsc->cb (rsc->cb_cls, + rowid, + &denom_pub, + &refund.coin.coin_pub, + &refund.details.merchant_pub, + &refund.details.merchant_sig, + &refund.details.h_contract_terms, + refund.details.rtransaction_id, + full_refund, + &refund.details.refund_amount); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_refunds_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_RefundCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct RefundsSerialContext rsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Fetch refunds with rowid '\geq' the given parameter */ + PREPARE (pg, + "audit_get_refunds_incr", + "SELECT" + " dep.merchant_pub" + ",ref.merchant_sig" + ",dep.h_contract_terms" + ",ref.rtransaction_id" + ",denom.denom_pub" + ",kc.coin_pub" + ",ref.amount_with_fee_val" + ",ref.amount_with_fee_frac" + ",ref.refund_serial_id" + " FROM refunds ref" + " JOIN deposits dep" + " ON (ref.coin_pub=dep.coin_pub AND ref.deposit_serial_id=dep.deposit_serial_id)" + " JOIN known_coins kc" + " ON (dep.coin_pub=kc.coin_pub)" + " JOIN denominations denom" + " ON (kc.denominations_serial=denom.denominations_serial)" + " WHERE ref.refund_serial_id>=$1" + " ORDER BY ref.refund_serial_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_refunds_incr", + params, + &refunds_serial_helper_cb, + &rsc); + if (GNUNET_OK != rsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_refunds_above_serial_id.h b/src/exchangedb/pg_select_refunds_above_serial_id.h new file mode 100644 index 000000000..b33816a94 --- /dev/null +++ b/src/exchangedb/pg_select_refunds_above_serial_id.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_refunds_above_serial_id.h + * @brief implementation of the select_refunds_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_REFUNDS_ABOVE_SERIAL_ID_H +#define PG_SELECT_REFUNDS_ABOVE_SERIAL_ID_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Select refunds above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_refunds_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_RefundCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_select_refunds_by_coin.c b/src/exchangedb/pg_select_refunds_by_coin.c new file mode 100644 index 000000000..17885a474 --- /dev/null +++ b/src/exchangedb/pg_select_refunds_by_coin.c @@ -0,0 +1,143 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_refunds_by_coin.c + * @brief Implementation of the select_refunds_by_coin function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_refunds_by_coin.h" +#include "pg_helper.h" + + +/** + * Closure for #get_refunds_cb(). + */ +struct SelectRefundContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_RefundCoinCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Set to #GNUNET_SYSERR on error. + */ + int status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct SelectRefundContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +get_refunds_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct SelectRefundContext *srctx = cls; + struct PostgresClosure *pg = srctx->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + if (GNUNET_OK != + srctx->cb (srctx->cb_cls, + &amount_with_fee)) + return; + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_refunds_by_coin ( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_PrivateContractHashP *h_contract, + TALER_EXCHANGEDB_RefundCoinCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_auto_from_type (h_contract), + GNUNET_PQ_query_param_end + }; + struct SelectRefundContext srctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + + /* Query the 'refunds' by coin public key */ + /* Query the 'refunds' by coin public key, merchant_pub and contract hash */ + PREPARE (pg, + "get_refunds_by_coin_and_contract", + "SELECT" + " ref.amount_with_fee_val" + ",ref.amount_with_fee_frac" + " FROM refunds ref" + " JOIN deposits dep" + " USING (coin_pub,deposit_serial_id)" + " WHERE ref.coin_pub=$1" + " AND dep.merchant_pub=$2" + " AND dep.h_contract_terms=$3;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "get_refunds_by_coin_and_contract", + params, + &get_refunds_cb, + &srctx); + if (GNUNET_SYSERR == srctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_refunds_by_coin.h b/src/exchangedb/pg_select_refunds_by_coin.h new file mode 100644 index 000000000..e1838b235 --- /dev/null +++ b/src/exchangedb/pg_select_refunds_by_coin.h @@ -0,0 +1,47 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_refunds_by_coin.h + * @brief implementation of the select_refunds_by_coin function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_REFUNDS_BY_COIN_H +#define PG_SELECT_REFUNDS_BY_COIN_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Select refunds by @a coin_pub, @a merchant_pub and @a h_contract. + * + * @param cls closure of plugin + * @param coin_pub coin to get refunds for + * @param merchant_pub merchant to get refunds for + * @param h_contract contract (hash) to get refunds for + * @param cb function to call for each refund found + * @param cb_cls closure for @a cb + * @return query result status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_refunds_by_coin ( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_PrivateContractHashP *h_contract, + TALER_EXCHANGEDB_RefundCoinCallback cb, + void *cb_cls); +#endif diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id.c b/src/exchangedb/pg_select_reserves_in_above_serial_id.c new file mode 100644 index 000000000..1a6efc66b --- /dev/null +++ b/src/exchangedb/pg_select_reserves_in_above_serial_id.c @@ -0,0 +1,167 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_reserves_in_above_serial_id.c + * @brief Implementation of the select_reserves_in_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_reserves_in_above_serial_id.h" +#include "pg_helper.h" + +/** + * Closure for #reserves_in_serial_helper_cb(). + */ +struct ReservesInSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_ReserveInCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct ReservesInSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +reserves_in_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReservesInSerialContext *risc = cls; + struct PostgresClosure *pg = risc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ret = risc->cb (risc->cb_cls, + rowid, + &reserve_pub, + &credit, + sender_account_details, + wire_reference, + execution_date); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_reserves_in_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_ReserveInCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct ReservesInSerialContext risc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound + transactions for reserves with serial id '\geq' the given parameter */ + PREPARE (pg, + "audit_reserves_in_get_transactions_incr", + "SELECT" + " reserves.reserve_pub" + ",wire_reference" + ",credit_val" + ",credit_frac" + ",execution_date" + ",payto_uri AS sender_account_details" + ",reserve_in_serial_id" + " FROM reserves_in" + " JOIN reserves" + " USING (reserve_pub)" + " JOIN wire_targets" + " ON (wire_source_h_payto = wire_target_h_payto)" + " WHERE reserve_in_serial_id>=$1" + " ORDER BY reserve_in_serial_id;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_reserves_in_get_transactions_incr", + params, + &reserves_in_serial_helper_cb, + &risc); + if (GNUNET_OK != risc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id.h b/src/exchangedb/pg_select_reserves_in_above_serial_id.h new file mode 100644 index 000000000..5f5dd2ecc --- /dev/null +++ b/src/exchangedb/pg_select_reserves_in_above_serial_id.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_reserves_in_above_serial_id.h + * @brief implementation of the select_reserves_in_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_H +#define PG_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Select inbound wire transfers into reserves_in above @a serial_id + * in monotonically increasing order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_reserves_in_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_ReserveInCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c b/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c new file mode 100644 index 000000000..ba73994f0 --- /dev/null +++ b/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c @@ -0,0 +1,169 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_reserves_in_above_serial_id_by_account.c + * @brief Implementation of the select_reserves_in_above_serial_id_by_account function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_reserves_in_above_serial_id_by_account.h" +#include "pg_helper.h" +/** + * Closure for #reserves_in_serial_helper_cb(). + */ +struct ReservesInSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_ReserveInCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct ReservesInSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +reserves_in_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReservesInSerialContext *risc = cls; + struct PostgresClosure *pg = risc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ret = risc->cb (risc->cb_cls, + rowid, + &reserve_pub, + &credit, + sender_account_details, + wire_reference, + execution_date); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_reserves_in_above_serial_id_by_account ( + void *cls, + const char *account_name, + uint64_t serial_id, + TALER_EXCHANGEDB_ReserveInCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_string (account_name), + GNUNET_PQ_query_param_end + }; + struct ReservesInSerialContext risc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound + transactions for reserves with serial id '\geq' the given parameter */ + PREPARE (pg, + "audit_reserves_in_get_transactions_incr_by_account", + "SELECT" + " reserves.reserve_pub" + ",wire_reference" + ",credit_val" + ",credit_frac" + ",execution_date" + ",payto_uri AS sender_account_details" + ",reserve_in_serial_id" + " FROM reserves_in" + " JOIN reserves " + " USING (reserve_pub)" + " JOIN wire_targets" + " ON (wire_source_h_payto = wire_target_h_payto)" + " WHERE reserve_in_serial_id>=$1 AND exchange_account_section=$2" + " ORDER BY reserve_in_serial_id;"); + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_reserves_in_get_transactions_incr_by_account", + params, + &reserves_in_serial_helper_cb, + &risc); + if (GNUNET_OK != risc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.h b/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.h new file mode 100644 index 000000000..81855ede9 --- /dev/null +++ b/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_reserves_in_above_serial_id_by_account.h + * @brief implementation of the select_reserves_in_above_serial_id_by_account function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_BY_ACCOUNT_H +#define PG_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_BY_ACCOUNT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Select inbound wire transfers into reserves_in above @a serial_id + * in monotonically increasing order by account. + * + * @param cls closure + * @param account_name name of the account to select by + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_reserves_in_above_serial_id_by_account ( + void *cls, + const char *account_name, + uint64_t serial_id, + TALER_EXCHANGEDB_ReserveInCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id.c b/src/exchangedb/pg_select_wire_out_above_serial_id.c new file mode 100644 index 000000000..e219f5d4b --- /dev/null +++ b/src/exchangedb/pg_select_wire_out_above_serial_id.c @@ -0,0 +1,159 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_wire_out_above_serial_id.c + * @brief Implementation of the select_wire_out_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_wire_out_above_serial_id.h" +#include "pg_helper.h" + +/** + * Closure for #wire_out_serial_helper_cb(). + */ +struct WireOutSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_WireTransferOutCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + int status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct WireOutSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +wire_out_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct WireOutSerialContext *wosc = cls; + struct PostgresClosure *pg = wosc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ret = wosc->cb (wosc->cb_cls, + rowid, + date, + &wtid, + payto_uri, + &amount); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_wire_out_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_WireTransferOutCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct WireOutSerialContext wosc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + /* Used in #postgres_select_wire_out_above_serial_id() */ + PREPARE (pg, + "audit_get_wire_incr", + "SELECT" + " wireout_uuid" + ",execution_date" + ",wtid_raw" + ",payto_uri" + ",amount_val" + ",amount_frac" + " FROM wire_out" + " JOIN wire_targets" + " USING (wire_target_h_payto)" + " WHERE wireout_uuid>=$1" + " ORDER BY wireout_uuid ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_wire_incr", + params, + &wire_out_serial_helper_cb, + &wosc); + if (GNUNET_OK != wosc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id.h b/src/exchangedb/pg_select_wire_out_above_serial_id.h new file mode 100644 index 000000000..e42cb9b0f --- /dev/null +++ b/src/exchangedb/pg_select_wire_out_above_serial_id.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_wire_out_above_serial_id.h + * @brief implementation of the select_wire_out_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_H +#define PG_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to select all wire transfers the exchange + * executed. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call for ONE unfinished item + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_wire_out_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_WireTransferOutCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c new file mode 100644 index 000000000..08883c9a4 --- /dev/null +++ b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c @@ -0,0 +1,162 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_wire_out_above_serial_id_by_account.c + * @brief Implementation of the select_wire_out_above_serial_id_by_account function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_wire_out_above_serial_id_by_account.h" +#include "pg_helper.h" + +/** + * Closure for #wire_out_serial_helper_cb(). + */ +struct WireOutSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_WireTransferOutCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + int status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct WireOutSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +wire_out_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct WireOutSerialContext *wosc = cls; + struct PostgresClosure *pg = wosc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ret = wosc->cb (wosc->cb_cls, + rowid, + date, + &wtid, + payto_uri, + &amount); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + +enum GNUNET_DB_QueryStatus +TEH_PG_select_wire_out_above_serial_id_by_account ( + void *cls, + const char *account_name, + uint64_t serial_id, + TALER_EXCHANGEDB_WireTransferOutCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_string (account_name), + GNUNET_PQ_query_param_end + }; + struct WireOutSerialContext wosc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Used in #postgres_select_wire_out_above_serial_id_by_account() */ + PREPARE (pg, + "audit_get_wire_incr_by_account", + "SELECT" + " wireout_uuid" + ",execution_date" + ",wtid_raw" + ",payto_uri" + ",amount_val" + ",amount_frac" + " FROM wire_out" + " JOIN wire_targets" + " USING (wire_target_h_payto)" + " WHERE " + " wireout_uuid>=$1 " + " AND exchange_account_section=$2" + " ORDER BY wireout_uuid ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_wire_incr_by_account", + params, + &wire_out_serial_helper_cb, + &wosc); + if (GNUNET_OK != wosc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.h b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.h new file mode 100644 index 000000000..98315cace --- /dev/null +++ b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_wire_out_above_serial_id_by_account.h + * @brief implementation of the select_wire_out_above_serial_id_by_account function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_BY_ACCOUNT_H +#define PG_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_BY_ACCOUNT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to select all wire transfers the exchange + * executed by account. + * + * @param cls closure + * @param account_name account to select + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call for ONE unfinished item + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_wire_out_above_serial_id_by_account ( + void *cls, + const char *account_name, + uint64_t serial_id, + TALER_EXCHANGEDB_WireTransferOutCallback cb, + void *cb_cls); +#endif diff --git a/src/exchangedb/pg_select_withdrawals_above_serial_id.c b/src/exchangedb/pg_select_withdrawals_above_serial_id.c new file mode 100644 index 000000000..4718a62ae --- /dev/null +++ b/src/exchangedb/pg_select_withdrawals_above_serial_id.c @@ -0,0 +1,175 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_withdrawals_above_serial_id.c + * @brief Implementation of the select_withdrawals_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_withdrawals_above_serial_id.h" +#include "pg_helper.h" + +/** + * Closure for #reserves_out_serial_helper_cb(). + */ +struct ReservesOutSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_WithdrawCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct ReservesOutSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +reserves_out_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReservesOutSerialContext *rosc = cls; + struct PostgresClosure *pg = rosc->pg; + + for (unsigned int i = 0; istatus = GNUNET_SYSERR; + return; + } + ret = rosc->cb (rosc->cb_cls, + rowid, + &h_blind_ev, + &denom_pub, + &reserve_pub, + &reserve_sig, + execution_date, + &amount_with_fee); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_withdrawals_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_WithdrawCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct ReservesOutSerialContext rosc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Fetch deposits with rowid '\geq' the given parameter */ + + PREPARE (pg, + "audit_get_reserves_out_incr", + "SELECT" + " h_blind_ev" + ",denom.denom_pub" + ",reserve_sig" + ",reserves.reserve_pub" + ",execution_date" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",reserve_out_serial_id" + " FROM reserves_out" + " JOIN reserves" + " USING (reserve_uuid)" + " JOIN denominations denom" + " USING (denominations_serial)" + " WHERE reserve_out_serial_id>=$1" + " ORDER BY reserve_out_serial_id ASC;"); + + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_reserves_out_incr", + params, + &reserves_out_serial_helper_cb, + &rosc); + if (GNUNET_OK != rosc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_select_withdrawals_above_serial_id.h b/src/exchangedb/pg_select_withdrawals_above_serial_id.h new file mode 100644 index 000000000..adc23fb30 --- /dev/null +++ b/src/exchangedb/pg_select_withdrawals_above_serial_id.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_select_withdrawals_above_serial_id.h + * @brief implementation of the select_withdrawals_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_WITHDRAWALS_ABOVE_SERIAL_ID_H +#define PG_SELECT_WITHDRAWALS_ABOVE_SERIAL_ID_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Select withdraw operations from reserves_out above @a serial_id + * in monotonically increasing order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_withdrawals_above_serial_id ( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_WithdrawCallback cb, + void *cb_cls); +#endif diff --git a/src/exchangedb/pg_set_extension_manifest.c b/src/exchangedb/pg_set_extension_manifest.c new file mode 100644 index 000000000..86e9d3f08 --- /dev/null +++ b/src/exchangedb/pg_set_extension_manifest.c @@ -0,0 +1,56 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_set_extension_manifest.c + * @brief Implementation of the set_extension_manifest function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_set_extension_manifest.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_set_extension_manifest (void *cls, + const char *extension_name, + const char *manifest) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam pcfg = + (NULL == manifest || 0 == *manifest) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (manifest); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (extension_name), + pcfg, + GNUNET_PQ_query_param_end + }; + + + PREPARE (pg, + "set_extension_manifest", + "INSERT INTO extensions (name, manifest) VALUES ($1, $2) " + "ON CONFLICT (name) " + "DO UPDATE SET manifest=$2"); + + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "set_extension_manifest", + params); +} diff --git a/src/exchangedb/pg_set_extension_manifest.h b/src/exchangedb/pg_set_extension_manifest.h new file mode 100644 index 000000000..ead3abd28 --- /dev/null +++ b/src/exchangedb/pg_set_extension_manifest.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_set_extension_manifest.h + * @brief implementation of the set_extension_manifest function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SET_EXTENSION_MANIFEST_H +#define PG_SET_EXTENSION_MANIFEST_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to save the manifest of an extension + * (age-restriction, policy_extension_...) After successful storage of the + * configuration it triggers the corresponding event. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param extension_name the name of the extension + * @param manifest JSON object of the configuration as string + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_set_extension_manifest (void *cls, + const char *extension_name, + const char *manifest); + +#endif diff --git a/src/exchangedb/pg_set_purse_balance.c b/src/exchangedb/pg_set_purse_balance.c new file mode 100644 index 000000000..a996104bc --- /dev/null +++ b/src/exchangedb/pg_set_purse_balance.c @@ -0,0 +1,55 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_set_purse_balance.c + * @brief Implementation of the set_purse_balance function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_set_purse_balance.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_set_purse_balance ( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + TALER_PQ_query_param_amount (balance), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "set_purse_balance", + "UPDATE purse_requests" + " SET balance_val=$2" + " ,balance_frac=$3" + " WHERE purse_pub=$1;"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "set_purse_balance", + params); +} + + + diff --git a/src/exchangedb/pg_set_purse_balance.h b/src/exchangedb/pg_set_purse_balance.h new file mode 100644 index 000000000..44b765568 --- /dev/null +++ b/src/exchangedb/pg_set_purse_balance.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_set_purse_balance.h + * @brief implementation of the set_purse_balance function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SET_PURSE_BALANCE_H +#define PG_SET_PURSE_BALANCE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Set the current @a balance in the purse + * identified by @a purse_pub. Used by the auditor + * to update the balance as calculated by the auditor. + * + * @param cls closure + * @param purse_pub public key of a purse + * @param balance new balance to store under the purse + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_set_purse_balance ( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance); + +#endif diff --git a/src/exchangedb/pg_setup_foreign_servers.c b/src/exchangedb/pg_setup_foreign_servers.c new file mode 100644 index 000000000..490ae4c24 --- /dev/null +++ b/src/exchangedb/pg_setup_foreign_servers.c @@ -0,0 +1,118 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_setup_foreign_servers.c + * @brief Implementation of the setup_foreign_servers function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_setup_foreign_servers.h" +#include "pg_helper.h" + + + +enum GNUNET_GenericReturnValue +TEH_PG_setup_foreign_servers (void *cls, + uint32_t num) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_Context *conn; + enum GNUNET_GenericReturnValue ret = GNUNET_OK; + char *shard_domain = NULL; + char *remote_user = NULL; + char *remote_user_pw = NULL; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (pg->cfg, + "exchange", + "SHARD_DOMAIN", + &shard_domain)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "exchange", + "SHARD_DOMAIN"); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (pg->cfg, + "exchangedb-postgres", + "SHARD_REMOTE_USER", + &remote_user)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "exchangedb-postgres", + "SHARD_REMOTE_USER"); + GNUNET_free (shard_domain); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (pg->cfg, + "exchangedb-postgres", + "SHARD_REMOTE_USER_PW", + &remote_user_pw)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "exchangedb-postgres", + "SHARD_REMOTE_USER_PW"); + GNUNET_free (shard_domain); + GNUNET_free (remote_user); + return GNUNET_SYSERR; + } + + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint32 (&num), + GNUNET_PQ_query_param_string (shard_domain), + GNUNET_PQ_query_param_string (remote_user), + GNUNET_PQ_query_param_string (remote_user_pw), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + struct GNUNET_PQ_PreparedStatement ps[] = { + GNUNET_PQ_make_prepare ("create_foreign_servers", + "SELECT" + " create_foreign_servers" + " ($1, $2, $3, $4);"), + GNUNET_PQ_PREPARED_STATEMENT_END + }; + + conn = GNUNET_PQ_connect_with_cfg (pg->cfg, + "exchangedb-postgres", + NULL, + es, + ps); + if (NULL == conn) + { + ret = GNUNET_SYSERR; + } + else if (0 > GNUNET_PQ_eval_prepared_non_select (conn, + "create_foreign_servers", + params)) + { + ret = GNUNET_SYSERR; + } + GNUNET_free (shard_domain); + GNUNET_free (remote_user); + GNUNET_free (remote_user_pw); + GNUNET_PQ_disconnect (conn); + return ret; +} + diff --git a/src/exchangedb/pg_setup_foreign_servers.h b/src/exchangedb/pg_setup_foreign_servers.h new file mode 100644 index 000000000..65ba03430 --- /dev/null +++ b/src/exchangedb/pg_setup_foreign_servers.h @@ -0,0 +1,39 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_setup_foreign_servers.h + * @brief implementation of the setup_foreign_servers function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SETUP_FOREIGN_SERVERS_H +#define PG_SETUP_FOREIGN_SERVERS_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + + +/** + * Setup foreign servers (shards) for already existing tables + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param num the number of foreign servers (shards) to create for each partitioned table + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + */ +enum GNUNET_GenericReturnValue +TEH_PG_setup_foreign_servers (void *cls, + uint32_t num); +#endif diff --git a/src/exchangedb/pg_setup_wire_target.c b/src/exchangedb/pg_setup_wire_target.c new file mode 100644 index 000000000..a2d890c50 --- /dev/null +++ b/src/exchangedb/pg_setup_wire_target.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_setup_wire_target.c + * @brief Implementation of the setup_wire_target function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_setup_wire_target.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_setup_wire_target( + struct PostgresClosure *pg, + const char *payto_uri, + struct TALER_PaytoHashP *h_payto) +{ + struct GNUNET_PQ_QueryParam iparams[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_string (payto_uri), + GNUNET_PQ_query_param_end + }; + + TALER_payto_hash (payto_uri, + h_payto); + + PREPARE (pg, + "insert_kyc_status", + "INSERT INTO wire_targets" + " (wire_target_h_payto" + " ,payto_uri" + " ) VALUES " + " ($1, $2)" + " ON CONFLICT DO NOTHING"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_kyc_status", + iparams); +} diff --git a/src/exchangedb/pg_setup_wire_target.h b/src/exchangedb/pg_setup_wire_target.h new file mode 100644 index 000000000..12c0e59b0 --- /dev/null +++ b/src/exchangedb/pg_setup_wire_target.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_setup_wire_target.h + * @brief implementation of the setup_wire_target function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SETUP_WIRE_TARGET_H +#define PG_SETUP_WIRE_TARGET_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "pg_helper.h" +#include "taler_exchangedb_plugin.h" + +/** + * Setup new wire target for @a payto_uri. + * + * @param pg the plugin-specific state + * @param payto_uri the payto URI to check + * @param[out] h_payto set to the hash of @a payto_uri + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_setup_wire_target( + struct PostgresClosure *pg, + const char *payto_uri, + struct TALER_PaytoHashP *h_payto); + +#endif diff --git a/src/exchangedb/pg_start_deferred_wire_out.c b/src/exchangedb/pg_start_deferred_wire_out.c new file mode 100644 index 000000000..abdc16028 --- /dev/null +++ b/src/exchangedb/pg_start_deferred_wire_out.c @@ -0,0 +1,59 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_start_deferred_wire_out.c + * @brief Implementation of the start_deferred_wire_out function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_start_deferred_wire_out.h" +#include "pg_helper.h" +#include "pg_preflight.h" +#include "pg_rollback.h" + +enum GNUNET_GenericReturnValue +TEH_PG_start_deferred_wire_out (void *cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_execute ( + "START TRANSACTION ISOLATION LEVEL READ COMMITTED;"), + GNUNET_PQ_make_execute ("SET CONSTRAINTS ALL DEFERRED;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + if (GNUNET_SYSERR == + TEH_PG_preflight (pg)) + return GNUNET_SYSERR; + if (GNUNET_OK != + GNUNET_PQ_exec_statements (pg->conn, + es)) + { + TALER_LOG_ERROR ( + "Failed to defer wire_out_ref constraint on transaction\n"); + GNUNET_break (0); + TEH_PG_rollback (pg); + return GNUNET_SYSERR; + } + pg->transaction_name = "deferred wire out"; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Starting READ COMMITTED DEFERRED transaction `%s'\n", + pg->transaction_name); + return GNUNET_OK; +} diff --git a/src/exchangedb/pg_start_deferred_wire_out.h b/src/exchangedb/pg_start_deferred_wire_out.h new file mode 100644 index 000000000..ed444ef70 --- /dev/null +++ b/src/exchangedb/pg_start_deferred_wire_out.h @@ -0,0 +1,39 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_start_deferred_wire_out.h + * @brief implementation of the start_deferred_wire_out function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_START_DEFERRED_WIRE_OUT_H +#define PG_START_DEFERRED_WIRE_OUT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Starts a READ COMMITTED transaction where we transiently violate the foreign + * constraints on the "wire_out" table as we insert aggregations + * and only add the wire transfer out at the end. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TEH_PG_start_deferred_wire_out (void *cls); + +#endif diff --git a/src/exchangedb/pg_store_wire_transfer_out.c b/src/exchangedb/pg_store_wire_transfer_out.c new file mode 100644 index 000000000..8bc0147dd --- /dev/null +++ b/src/exchangedb/pg_store_wire_transfer_out.c @@ -0,0 +1,63 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_store_wire_transfer_out.c + * @brief Implementation of the store_wire_transfer_out function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_store_wire_transfer_out.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_store_wire_transfer_out ( + void *cls, + struct GNUNET_TIME_Timestamp date, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_PaytoHashP *h_payto, + const char *exchange_account_section, + const struct TALER_Amount *amount) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&date), + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_string (exchange_account_section), + TALER_PQ_query_param_amount (amount), + GNUNET_PQ_query_param_end + }; + + /* Used in #postgres_store_wire_transfer_out */ + PREPARE (pg, + "insert_wire_out", + "INSERT INTO wire_out " + "(execution_date" + ",wtid_raw" + ",wire_target_h_payto" + ",exchange_account_section" + ",amount_val" + ",amount_frac" + ") VALUES " + "($1, $2, $3, $4, $5, $6);"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_wire_out", + params); +} diff --git a/src/exchangedb/pg_store_wire_transfer_out.h b/src/exchangedb/pg_store_wire_transfer_out.h new file mode 100644 index 000000000..79950e65a --- /dev/null +++ b/src/exchangedb/pg_store_wire_transfer_out.h @@ -0,0 +1,48 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_store_wire_transfer_out.h + * @brief implementation of the store_wire_transfer_out function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_STORE_WIRE_TRANSFER_OUT_H +#define PG_STORE_WIRE_TRANSFER_OUT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Store information about an outgoing wire transfer that was executed. + * + * @param cls closure + * @param date time of the wire transfer + * @param wtid subject of the wire transfer + * @param h_payto identifies the receiver account of the wire transfer + * @param exchange_account_section configuration section of the exchange specifying the + * exchange's bank account being used + * @param amount amount that was transmitted + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_store_wire_transfer_out ( + void *cls, + struct GNUNET_TIME_Timestamp date, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_PaytoHashP *h_payto, + const char *exchange_account_section, + const struct TALER_Amount *amount); + +#endif diff --git a/src/exchangedb/pg_update_aggregation_transient.c b/src/exchangedb/pg_update_aggregation_transient.c new file mode 100644 index 000000000..1d91301c3 --- /dev/null +++ b/src/exchangedb/pg_update_aggregation_transient.c @@ -0,0 +1,60 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_update_aggregation_transient.c + * @brief Implementation of the update_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_update_aggregation_transient.h" +#include "pg_helper.h" + + + +enum GNUNET_DB_QueryStatus +TEH_PG_update_aggregation_transient ( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, + const struct TALER_Amount *total) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + TALER_PQ_query_param_amount (total), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_uint64 (&kyc_requirement_row), + GNUNET_PQ_query_param_end + }; + + + /* Used in #postgres_update_aggregation_transient() */ + PREPARE (pg, + "update_aggregation_transient", + "UPDATE aggregation_transient" + " SET amount_val=$1" + " ,amount_frac=$2" + " ,legitimization_requirement_serial_id=$5" + " WHERE wire_target_h_payto=$3" + " AND wtid_raw=$4"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_aggregation_transient", + params); +} diff --git a/src/exchangedb/pg_update_aggregation_transient.h b/src/exchangedb/pg_update_aggregation_transient.h new file mode 100644 index 000000000..c444e85bb --- /dev/null +++ b/src/exchangedb/pg_update_aggregation_transient.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_update_aggregation_transient.h + * @brief implementation of the update_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_UPDATE_AGGREGATION_TRANSIENT_H +#define PG_UPDATE_AGGREGATION_TRANSIENT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Update existing entry in the transient aggregation table. + * @a h_payto is only needed for query performance. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto destination of the wire transfer + * @param wtid the raw wire transfer identifier to update + * @param kyc_requirement_row row in legitimization_requirements that need to be satisfied to continue, or 0 for none + * @param total new total amount to be wired in the future + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_update_aggregation_transient ( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, + const struct TALER_Amount *total); + +#endif diff --git a/src/exchangedb/pg_update_wire.c b/src/exchangedb/pg_update_wire.c new file mode 100644 index 000000000..f5f5672cb --- /dev/null +++ b/src/exchangedb/pg_update_wire.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_update_wire.c + * @brief Implementation of the update_wire function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_update_wire.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_update_wire (void *cls, + const char *payto_uri, + struct GNUNET_TIME_Timestamp change_date, + bool enabled) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (payto_uri), + GNUNET_PQ_query_param_bool (enabled), + GNUNET_PQ_query_param_timestamp (&change_date), + GNUNET_PQ_query_param_end + }; + + /* used in #postgres_update_wire() */ + PREPARE (pg, + "update_wire", + "UPDATE wire_accounts" + " SET" + " is_active=$2" + " ,last_change=$3" + " WHERE payto_uri=$1"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_wire", + params); +} diff --git a/src/exchangedb/pg_update_wire.h b/src/exchangedb/pg_update_wire.h new file mode 100644 index 000000000..c01d68a46 --- /dev/null +++ b/src/exchangedb/pg_update_wire.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_update_wire.h + * @brief implementation of the update_wire function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_UPDATE_WIRE_H +#define PG_UPDATE_WIRE_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +/** + * Update information about a wire account of the exchange. + * + * @param cls closure + * @param payto_uri account the update is about + * @param change_date date when the account status was last changed + * (only to be used for replay detection) + * @param enabled true to enable, false to disable (the actual change) + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_update_wire (void *cls, + const char *payto_uri, + struct GNUNET_TIME_Timestamp change_date, + bool enabled); + +#endif diff --git a/src/exchangedb/pg_wire_prepare_data_get.c b/src/exchangedb/pg_wire_prepare_data_get.c new file mode 100644 index 000000000..d45413010 --- /dev/null +++ b/src/exchangedb/pg_wire_prepare_data_get.c @@ -0,0 +1,142 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_wire_prepare_data_get.c + * @brief Implementation of the wire_prepare_data_get function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_wire_prepare_data_get.h" +#include "pg_helper.h" + +/** + * Closure for #prewire_cb(). + */ +struct PrewireContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_WirePreparationIterator cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * #GNUNET_OK if everything went fine. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct MissingWireContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +prewire_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct PrewireContext *pc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + uint64_t prewire_uuid; + char *wire_method; + void *buf = NULL; + size_t buf_size; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("prewire_uuid", + &prewire_uuid), + GNUNET_PQ_result_spec_string ("wire_method", + &wire_method), + GNUNET_PQ_result_spec_variable_size ("buf", + &buf, + &buf_size), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + pc->status = GNUNET_SYSERR; + return; + } + pc->cb (pc->cb_cls, + prewire_uuid, + wire_method, + buf, + buf_size); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_wire_prepare_data_get (void *cls, + uint64_t start_row, + uint64_t limit, + TALER_EXCHANGEDB_WirePreparationIterator cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&start_row), + GNUNET_PQ_query_param_uint64 (&limit), + GNUNET_PQ_query_param_end + }; + struct PrewireContext pc = { + .cb = cb, + .cb_cls = cb_cls, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + + /* Used in #postgres_wire_prepare_data_get() */ + PREPARE (pg, + "wire_prepare_data_get", + "SELECT" + " prewire_uuid" + ",wire_method" + ",buf" + " FROM prewire" + " WHERE prewire_uuid >= $1" + " AND finished=FALSE" + " AND failed=FALSE" + " ORDER BY prewire_uuid ASC" + " LIMIT $2;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "wire_prepare_data_get", + params, + &prewire_cb, + &pc); + if (GNUNET_OK != pc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/pg_wire_prepare_data_get.h b/src/exchangedb/pg_wire_prepare_data_get.h new file mode 100644 index 000000000..91e21d27e --- /dev/null +++ b/src/exchangedb/pg_wire_prepare_data_get.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_wire_prepare_data_get.h + * @brief implementation of the wire_prepare_data_get function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_WIRE_PREPARE_DATA_GET_H +#define PG_WIRE_PREPARE_DATA_GET_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to get an unfinished wire transfer + * preparation data. Fetches at most one item. + * + * @param cls closure + * @param start_row offset to query table at + * @param limit maximum number of results to return + * @param cb function to call for ONE unfinished item + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_wire_prepare_data_get (void *cls, + uint64_t start_row, + uint64_t limit, + TALER_EXCHANGEDB_WirePreparationIterator cb, + void *cb_cls); +#endif diff --git a/src/exchangedb/pg_wire_prepare_data_insert.c b/src/exchangedb/pg_wire_prepare_data_insert.c new file mode 100644 index 000000000..903f22a5b --- /dev/null +++ b/src/exchangedb/pg_wire_prepare_data_insert.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_wire_prepare_data_insert.c + * @brief Implementation of the wire_prepare_data_insert function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_wire_prepare_data_insert.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_wire_prepare_data_insert (void *cls, + const char *type, + const char *buf, + size_t buf_size) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (type), + GNUNET_PQ_query_param_fixed_size (buf, buf_size), + GNUNET_PQ_query_param_end + }; + + + /* Used in #postgres_wire_prepare_data_insert() to store + wire transfer information before actually committing it with the bank */ + PREPARE (pg, + "wire_prepare_data_insert", + "INSERT INTO prewire " + "(wire_method" + ",buf" + ") VALUES " + "($1, $2);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "wire_prepare_data_insert", + params); +} diff --git a/src/exchangedb/pg_wire_prepare_data_insert.h b/src/exchangedb/pg_wire_prepare_data_insert.h new file mode 100644 index 000000000..2b6050d05 --- /dev/null +++ b/src/exchangedb/pg_wire_prepare_data_insert.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_wire_prepare_data_insert.h + * @brief implementation of the wire_prepare_data_insert function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_WIRE_PREPARE_DATA_INSERT_H +#define PG_WIRE_PREPARE_DATA_INSERT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to insert wire transfer commit data into the DB. + * + * @param cls closure + * @param type type of the wire transfer (i.e. "iban") + * @param buf buffer with wire transfer preparation data + * @param buf_size number of bytes in @a buf + * @return query status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_wire_prepare_data_insert (void *cls, + const char *type, + const char *buf, + size_t buf_size); +#endif diff --git a/src/exchangedb/pg_wire_prepare_data_mark_failed.c b/src/exchangedb/pg_wire_prepare_data_mark_failed.c new file mode 100644 index 000000000..fe2236b82 --- /dev/null +++ b/src/exchangedb/pg_wire_prepare_data_mark_failed.c @@ -0,0 +1,50 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_wire_prepare_data_mark_failed.c + * @brief Implementation of the wire_prepare_data_mark_failed function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_wire_prepare_data_mark_failed.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_wire_prepare_data_mark_failed ( + void *cls, + uint64_t rowid) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&rowid), + GNUNET_PQ_query_param_end + }; + + /* Used in #postgres_wire_prepare_data_mark_failed() */ + + PREPARE (pg, + "wire_prepare_data_mark_failed", + "UPDATE prewire" + " SET failed=TRUE" + " WHERE prewire_uuid=$1;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "wire_prepare_data_mark_failed", + params); +} diff --git a/src/exchangedb/pg_wire_prepare_data_mark_failed.h b/src/exchangedb/pg_wire_prepare_data_mark_failed.h new file mode 100644 index 000000000..cae1523d1 --- /dev/null +++ b/src/exchangedb/pg_wire_prepare_data_mark_failed.h @@ -0,0 +1,39 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_wire_prepare_data_mark_failed.h + * @brief implementation of the wire_prepare_data_mark_failed function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_WIRE_PREPARE_DATA_MARK_FAILED_H +#define PG_WIRE_PREPARE_DATA_MARK_FAILED_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to mark wire transfer commit data as failed. + * + * @param cls closure + * @param rowid which entry to mark as failed + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_wire_prepare_data_mark_failed ( + void *cls, + uint64_t rowid); +#endif diff --git a/src/exchangedb/pg_wire_prepare_data_mark_finished.c b/src/exchangedb/pg_wire_prepare_data_mark_finished.c new file mode 100644 index 000000000..de8738e40 --- /dev/null +++ b/src/exchangedb/pg_wire_prepare_data_mark_finished.c @@ -0,0 +1,49 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_wire_prepare_data_mark_finished.c + * @brief Implementation of the wire_prepare_data_mark_finished function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_wire_prepare_data_mark_finished.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TEH_PG_wire_prepare_data_mark_finished ( + void *cls, + uint64_t rowid) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&rowid), + GNUNET_PQ_query_param_end + }; + + /* Used in #postgres_wire_prepare_data_mark_finished() */ + PREPARE (pg, + "wire_prepare_data_mark_done", + "UPDATE prewire" + " SET finished=TRUE" + " WHERE prewire_uuid=$1;"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "wire_prepare_data_mark_done", + params); +} diff --git a/src/exchangedb/pg_wire_prepare_data_mark_finished.h b/src/exchangedb/pg_wire_prepare_data_mark_finished.h new file mode 100644 index 000000000..19db2ca99 --- /dev/null +++ b/src/exchangedb/pg_wire_prepare_data_mark_finished.h @@ -0,0 +1,39 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + */ +/** + * @file exchangedb/pg_wire_prepare_data_mark_finished.h + * @brief implementation of the wire_prepare_data_mark_finished function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_WIRE_PREPARE_DATA_MARK_FINISHED_H +#define PG_WIRE_PREPARE_DATA_MARK_FINISHED_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + +/** + * Function called to mark wire transfer commit data as finished. + * + * @param cls closure + * @param rowid which entry to mark as finished + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TEH_PG_wire_prepare_data_mark_finished ( + void *cls, + uint64_t rowid); +#endif diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index aa16e7ffc..6a2a473c1 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -104,6 +104,110 @@ #include "pg_lookup_wire_fee_by_time.h" #include "pg_start.h" #include "pg_rollback.h" +#include "pg_create_tables.h" +#include "pg_setup_foreign_servers.h" +#include "pg_event_listen.h" +#include "pg_event_listen_cancel.h" +#include "pg_event_notify.h" +#include "pg_get_denomination_info.h" +#include "pg_iterate_denomination_info.h" +#include "pg_iterate_denominations.h" +#include "pg_iterate_active_auditors.h" +#include "pg_iterate_auditor_denominations.h" +#include "pg_reserves_get.h" +#include "pg_reserves_get_origin.h" +#include "pg_drain_kyc_alert.h" +#include "pg_reserves_in_insert.h" +#include "pg_get_withdraw_info.h" +#include "pg_do_batch_withdraw.h" +#include "pg_get_policy_details.h" +#include "pg_persist_policy_details.h" +#include "pg_do_deposit.h" +#include "pg_add_policy_fulfillment_proof.h" +#include "pg_do_melt.h" +#include "pg_do_refund.h" +#include "pg_do_recoup.h" +#include "pg_do_recoup_refresh.h" +#include "pg_get_reserve_balance.h" +#include "pg_count_known_coins.h" +#include "pg_ensure_coin_known.h" +#include "pg_get_known_coin.h" +#include "pg_get_coin_denomination.h" +#include "pg_have_deposit2.h" +#include "pg_aggregate.h" +#include "pg_create_aggregation_transient.h" +#include "pg_select_aggregation_transient.h" +#include "pg_find_aggregation_transient.h" +#include "pg_update_aggregation_transient.h" +#include "pg_get_ready_deposit.h" +#include "pg_insert_deposit.h" +#include "pg_insert_refund.h" +#include "pg_select_refunds_by_coin.h" +#include "pg_get_melt.h" +#include "pg_insert_refresh_reveal.h" +#include "pg_get_refresh_reveal.h" +#include "pg_lookup_wire_transfer.h" +#include "pg_lookup_transfer_by_deposit.h" +#include "pg_insert_wire_fee.h" +#include "pg_insert_global_fee.h" +#include "pg_get_wire_fee.h" +#include "pg_get_global_fee.h" +#include "pg_get_global_fees.h" +#include "pg_insert_reserve_closed.h" +#include "pg_wire_prepare_data_insert.h" +#include "pg_wire_prepare_data_mark_finished.h" +#include "pg_wire_prepare_data_mark_failed.h" +#include "pg_wire_prepare_data_get.h" +#include "pg_start_deferred_wire_out.h" +#include "pg_store_wire_transfer_out.h" +#include "pg_gc.h" +#include "pg_select_deposits_above_serial_id.h" +#include "pg_select_history_requests_above_serial_id.h" +#include "pg_select_purse_decisions_above_serial_id.h" +#include "pg_select_purse_deposits_by_purse.h" +#include "pg_select_refreshes_above_serial_id.h" +#include "pg_select_refunds_above_serial_id.h" +#include "pg_select_reserves_in_above_serial_id.h" +#include "pg_select_reserves_in_above_serial_id_by_account.h" +#include "pg_select_withdrawals_above_serial_id.h" +#include "pg_select_wire_out_above_serial_id.h" +#include "pg_select_wire_out_above_serial_id_by_account.h" +#include "pg_select_recoup_above_serial_id.h" +#include "pg_select_recoup_refresh_above_serial_id.h" +#include "pg_get_reserve_by_h_blind.h" +#include "pg_get_old_coin_by_h_blind.h" +#include "pg_insert_denomination_revocation.h" +#include "pg_get_denomination_revocation.h" +#include "pg_select_deposits_missing_wire.h" +#include "pg_lookup_auditor_timestamp.h" +#include "pg_lookup_auditor_status.h" +#include "pg_insert_auditor.h" +#include "pg_lookup_wire_timestamp.h" +#include "pg_insert_wire.h" +#include "pg_update_wire.h" +#include "pg_get_wire_accounts.h" +#include "pg_get_wire_fees.h" +#include "pg_insert_signkey_revocation.h" +#include "pg_lookup_signkey_revocation.h" +#include "pg_lookup_denomination_key.h" +#include "pg_insert_auditor_denom_sig.h" +#include "pg_select_auditor_denom_sig.h" +#include "pg_add_denomination_key.h" +#include "pg_lookup_signing_key.h" +#include "pg_begin_shard.h" +#include "pg_abort_shard.h" +#include "pg_complete_shard.h" +#include "pg_release_revolving_shard.h" +#include "pg_delete_shard_locks.h" +#include "pg_set_extension_manifest.h" +#include "pg_insert_partner.h" +#include "pg_expire_purse.h" +#include "pg_select_purse_by_merge_pub.h" +#include "pg_set_purse_balance.h" +#include "pg_reserves_update.h" +#include "pg_setup_wire_target.h" +#include "pg_compute_shard.h" + /** * Set to 1 to enable Postgres auto_explain module. This will * slow down things a _lot_, but also provide extensive logging @@ -130,130 +234,6 @@ } while (0) -/** - * Create the necessary tables if they are not present - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -static enum GNUNET_GenericReturnValue -postgres_create_tables (void *cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_Context *conn; - enum GNUNET_GenericReturnValue ret; - - conn = GNUNET_PQ_connect_with_cfg (pg->cfg, - "exchangedb-postgres", - "exchange-", - NULL, - NULL); - if (NULL == conn) - return GNUNET_SYSERR; - ret = GNUNET_PQ_exec_sql (conn, - "procedures"); - GNUNET_PQ_disconnect (conn); - return ret; -} - - -/** - * Setup foreign servers (shards) for already existing tables - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param num the number of foreign servers (shards) to create for each partitioned table - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -static enum GNUNET_GenericReturnValue -postgres_setup_foreign_servers (void *cls, - uint32_t num) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_Context *conn; - enum GNUNET_GenericReturnValue ret = GNUNET_OK; - char *shard_domain = NULL; - char *remote_user = NULL; - char *remote_user_pw = NULL; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (pg->cfg, - "exchange", - "SHARD_DOMAIN", - &shard_domain)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "exchange", - "SHARD_DOMAIN"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (pg->cfg, - "exchangedb-postgres", - "SHARD_REMOTE_USER", - &remote_user)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "exchangedb-postgres", - "SHARD_REMOTE_USER"); - GNUNET_free (shard_domain); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (pg->cfg, - "exchangedb-postgres", - "SHARD_REMOTE_USER_PW", - &remote_user_pw)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "exchangedb-postgres", - "SHARD_REMOTE_USER_PW"); - GNUNET_free (shard_domain); - GNUNET_free (remote_user); - return GNUNET_SYSERR; - } - - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint32 (&num), - GNUNET_PQ_query_param_string (shard_domain), - GNUNET_PQ_query_param_string (remote_user), - GNUNET_PQ_query_param_string (remote_user_pw), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - struct GNUNET_PQ_PreparedStatement ps[] = { - GNUNET_PQ_make_prepare ("create_foreign_servers", - "SELECT" - " create_foreign_servers" - " ($1, $2, $3, $4);"), - GNUNET_PQ_PREPARED_STATEMENT_END - }; - - conn = GNUNET_PQ_connect_with_cfg (pg->cfg, - "exchangedb-postgres", - NULL, - es, - ps); - if (NULL == conn) - { - ret = GNUNET_SYSERR; - } - else if (0 > GNUNET_PQ_eval_prepared_non_select (conn, - "create_foreign_servers", - params)) - { - ret = GNUNET_SYSERR; - } - GNUNET_free (shard_domain); - GNUNET_free (remote_user); - GNUNET_free (remote_user_pw); - GNUNET_PQ_disconnect (conn); - return ret; -} - - /** * Initialize prepared statements for @a pg. * @@ -265,151 +245,6 @@ prepare_statements (struct PostgresClosure *pg) { enum GNUNET_GenericReturnValue ret; struct GNUNET_PQ_PreparedStatement ps[] = { - /* Used in #postgres_add_denomination_key() */ - GNUNET_PQ_make_prepare ( - "add_denomination_key", - "INSERT INTO denominations " - "(denom_pub_hash" - ",denom_pub" - ",master_sig" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin_val" /* value of this denom */ - ",coin_frac" /* fractional value of this denom */ - ",fee_withdraw_val" - ",fee_withdraw_frac" - ",fee_deposit_val" - ",fee_deposit_frac" - ",fee_refresh_val" - ",fee_refresh_frac" - ",fee_refund_val" - ",fee_refund_frac" - ",age_mask" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," - " $11, $12, $13, $14, $15, $16, $17, $18);"), - /* Used in #postgres_iterate_denomination_info() */ - GNUNET_PQ_make_prepare ( - "denomination_iterate", - "SELECT" - " master_sig" - ",denom_pub_hash" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin_val" /* value of this denom */ - ",coin_frac" /* fractional value of this denom */ - ",fee_withdraw_val" - ",fee_withdraw_frac" - ",fee_deposit_val" - ",fee_deposit_frac" - ",fee_refresh_val" - ",fee_refresh_frac" - ",fee_refund_val" - ",fee_refund_frac" - ",denom_pub" - ",age_mask" - " FROM denominations;"), - /* Used in #postgres_iterate_denominations() */ - GNUNET_PQ_make_prepare ( - "select_denominations", - "SELECT" - " denominations.master_sig" - ",denom_revocations_serial_id IS NOT NULL AS revoked" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin_val" /* value of this denom */ - ",coin_frac" /* fractional value of this denom */ - ",fee_withdraw_val" - ",fee_withdraw_frac" - ",fee_deposit_val" - ",fee_deposit_frac" - ",fee_refresh_val" - ",fee_refresh_frac" - ",fee_refund_val" - ",fee_refund_frac" - ",denom_type" - ",age_mask" - ",denom_pub" - " FROM denominations" - " LEFT JOIN " - " denomination_revocations USING (denominations_serial);"), - - /* Used in #postgres_iterate_auditor_denominations() */ - GNUNET_PQ_make_prepare ( - "select_auditor_denoms", - "SELECT" - " auditors.auditor_pub" - ",denominations.denom_pub_hash" - ",auditor_denom_sigs.auditor_sig" - " FROM auditor_denom_sigs" - " JOIN auditors USING (auditor_uuid)" - " JOIN denominations USING (denominations_serial)" - " WHERE auditors.is_active;"), - /* Used in #postgres_iterate_active_auditors() */ - GNUNET_PQ_make_prepare ( - "select_auditors", - "SELECT" - " auditor_pub" - ",auditor_url" - ",auditor_name" - " FROM auditors" - " WHERE" - " is_active;"), - /* Used in #postgres_get_denomination_info() */ - GNUNET_PQ_make_prepare ( - "denomination_get", - "SELECT" - " master_sig" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin_val" /* value of this denom */ - ",coin_frac" /* fractional value of this denom */ - ",fee_withdraw_val" - ",fee_withdraw_frac" - ",fee_deposit_val" - ",fee_deposit_frac" - ",fee_refresh_val" - ",fee_refresh_frac" - ",fee_refund_val" - ",fee_refund_frac" - ",age_mask" - " FROM denominations" - " WHERE denom_pub_hash=$1;"), - /* Used in #postgres_insert_denomination_revocation() */ - GNUNET_PQ_make_prepare ( - "denomination_revocation_insert", - "INSERT INTO denomination_revocations " - "(denominations_serial" - ",master_sig" - ") SELECT denominations_serial,$2" - " FROM denominations" - " WHERE denom_pub_hash=$1;"), - /* Used in #postgres_get_denomination_revocation() */ - GNUNET_PQ_make_prepare ( - "denomination_revocation_get", - "SELECT" - " master_sig" - ",denom_revocations_serial_id" - " FROM denomination_revocations" - " WHERE denominations_serial=" - " (SELECT denominations_serial" - " FROM denominations" - " WHERE denom_pub_hash=$1);"), - /* Used in #postgres_reserves_get_origin() */ - GNUNET_PQ_make_prepare ( - "get_h_wire_source_of_reserve", - "SELECT" - " wire_source_h_payto" - " FROM reserves_in" - " WHERE reserve_pub=$1"), GNUNET_PQ_make_prepare ( "get_kyc_h_payto", "SELECT" @@ -417,287 +252,8 @@ prepare_statements (struct PostgresClosure *pg) " FROM wire_targets" " WHERE wire_target_h_payto=$1" " LIMIT 1;"), - /* Used in #postgres_insert_partner() */ - GNUNET_PQ_make_prepare ( - "insert_partner", - "INSERT INTO partners" - " (partner_master_pub" - " ,start_date" - " ,end_date" - " ,wad_frequency" - " ,wad_fee_val" - " ,wad_fee_frac" - " ,master_sig" - " ,partner_base_url" - " ) VALUES " - " ($1, $2, $3, $4, $5, $6, $7, $8);"), - /* Used in #setup_wire_target() */ - GNUNET_PQ_make_prepare ( - "insert_kyc_status", - "INSERT INTO wire_targets" - " (wire_target_h_payto" - " ,payto_uri" - " ) VALUES " - " ($1, $2)" - " ON CONFLICT DO NOTHING"), - /* Used in #postgres_drain_kyc_alert() */ - GNUNET_PQ_make_prepare ( - "drain_kyc_alert", - "DELETE FROM kyc_alerts" - " WHERE trigger_type=$1" - " AND h_payto = " - " (SELECT h_payto " - " FROM kyc_alerts" - " WHERE trigger_type=$1" - " LIMIT 1)" - " RETURNING h_payto;"), - /* Used in #postgres_reserves_get() */ - GNUNET_PQ_make_prepare ( - "reserves_get", - "SELECT" - " current_balance_val" - ",current_balance_frac" - ",expiration_date" - ",gc_date" - " FROM reserves" - " WHERE reserve_pub=$1" - " LIMIT 1;"), - GNUNET_PQ_make_prepare ( - "reserve_create", - "INSERT INTO reserves " - "(reserve_pub" - ",current_balance_val" - ",current_balance_frac" - ",expiration_date" - ",gc_date" - ") VALUES " - "($1, $2, $3, $4, $5)" - " ON CONFLICT DO NOTHING" - " RETURNING reserve_uuid;"), - /* Used in #postgres_insert_reserve_closed() */ - GNUNET_PQ_make_prepare ( - "reserves_close_insert", - "INSERT INTO reserves_close " - "(reserve_pub" - ",execution_date" - ",wtid" - ",wire_target_h_payto" - ",amount_val" - ",amount_frac" - ",closing_fee_val" - ",closing_fee_frac" - ",close_request_row" - ") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9);"), - /* Used in #postgres_reserves_update() when the reserve is updated */ - GNUNET_PQ_make_prepare ( - "reserve_update", - "UPDATE reserves" - " SET" - " expiration_date=$1" - ",gc_date=$2" - ",current_balance_val=$3" - ",current_balance_frac=$4" - " WHERE reserve_pub=$5;"), - /* Used in #postgres_reserves_in_insert() to store transaction details */ - GNUNET_PQ_make_prepare ( - "reserves_in_add_transaction", - "INSERT INTO reserves_in " - "(reserve_pub" - ",wire_reference" - ",credit_val" - ",credit_frac" - ",exchange_account_section" - ",wire_source_h_payto" - ",execution_date" - ") VALUES ($1, $2, $3, $4, $5, $6, $7)" - " ON CONFLICT DO NOTHING;"), - /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound - transactions for reserves with serial id '\geq' the given parameter */ - GNUNET_PQ_make_prepare ( - "audit_reserves_in_get_transactions_incr", - "SELECT" - " reserves.reserve_pub" - ",wire_reference" - ",credit_val" - ",credit_frac" - ",execution_date" - ",payto_uri AS sender_account_details" - ",reserve_in_serial_id" - " FROM reserves_in" - " JOIN reserves" - " USING (reserve_pub)" - " JOIN wire_targets" - " ON (wire_source_h_payto = wire_target_h_payto)" - " WHERE reserve_in_serial_id>=$1" - " ORDER BY reserve_in_serial_id;"), - /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound - transactions for reserves with serial id '\geq' the given parameter */ - GNUNET_PQ_make_prepare ( - "audit_reserves_in_get_transactions_incr_by_account", - "SELECT" - " reserves.reserve_pub" - ",wire_reference" - ",credit_val" - ",credit_frac" - ",execution_date" - ",payto_uri AS sender_account_details" - ",reserve_in_serial_id" - " FROM reserves_in" - " JOIN reserves " - " USING (reserve_pub)" - " JOIN wire_targets" - " ON (wire_source_h_payto = wire_target_h_payto)" - " WHERE reserve_in_serial_id>=$1 AND exchange_account_section=$2" - " ORDER BY reserve_in_serial_id;"), - /* Used in #postgres_do_batch_withdraw() to - update the reserve balance and check its status */ - GNUNET_PQ_make_prepare ( - "call_batch_withdraw", - "SELECT " - " reserve_found" - ",balance_ok" - ",ruuid" - " FROM exchange_do_batch_withdraw" - " ($1,$2,$3,$4,$5);"), - - /* Used in #postgres_do_deposit() to execute a deposit, - checking the coin's balance in the process as needed. */ - GNUNET_PQ_make_prepare ( - "call_deposit", - "SELECT " - " out_exchange_timestamp AS exchange_timestamp" - ",out_balance_ok AS balance_ok" - ",out_conflict AS conflicted" - " FROM exchange_do_deposit" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17);"), - - /* Used in #postgres_update_aggregation_transient() */ - GNUNET_PQ_make_prepare ( - "set_purse_balance", - "UPDATE purse_requests" - " SET balance_val=$2" - " ,balance_frac=$3" - " WHERE purse_pub=$1;"), - /* used in #postgres_expire_purse() */ - GNUNET_PQ_make_prepare ( - "call_expire_purse", - "SELECT " - " out_found AS found" - " FROM exchange_do_expire_purse" - " ($1,$2,$3);"), - /* Used in #postgres_do_melt() to melt a coin. */ - GNUNET_PQ_make_prepare ( - "call_melt", - "SELECT " - " out_balance_ok AS balance_ok" - ",out_zombie_bad AS zombie_required" - ",out_noreveal_index AS noreveal_index" - " FROM exchange_do_melt" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9);"), - /* Used in #postgres_do_refund() to refund a deposit. */ - GNUNET_PQ_make_prepare ( - "call_refund", - "SELECT " - " out_not_found AS not_found" - ",out_refund_ok AS refund_ok" - ",out_gone AS gone" - ",out_conflict AS conflict" - " FROM exchange_do_refund" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13);"), - /* Used in #postgres_do_recoup() to recoup a coin to a reserve. */ - GNUNET_PQ_make_prepare ( - "call_recoup", - "SELECT " - " out_recoup_timestamp AS recoup_timestamp" - ",out_recoup_ok AS recoup_ok" - ",out_internal_failure AS internal_failure" - " FROM exchange_do_recoup_to_reserve" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9);"), - /* Used in #postgres_do_recoup_refresh() to recoup a coin to a zombie coin. */ - GNUNET_PQ_make_prepare ( - "call_recoup_refresh", - "SELECT " - " out_recoup_timestamp AS recoup_timestamp" - ",out_recoup_ok AS recoup_ok" - ",out_internal_failure AS internal_failure" - " FROM exchange_do_recoup_to_coin" - " ($1,$2,$3,$4,$5,$6,$7);"), - /* Used in #postgres_get_withdraw_info() to - locate the response for a /reserve/withdraw request - using the hash of the blinded message. Used to - make sure /reserve/withdraw requests are idempotent. */ - GNUNET_PQ_make_prepare ( - "get_withdraw_info", - "SELECT" - " denom.denom_pub_hash" - ",denom_sig" - ",reserve_sig" - ",reserves.reserve_pub" - ",execution_date" - ",h_blind_ev" - ",amount_with_fee_val" - ",amount_with_fee_frac" - ",denom.fee_withdraw_val" - ",denom.fee_withdraw_frac" - " FROM reserves_out" - " JOIN reserves" - " USING (reserve_uuid)" - " JOIN denominations denom" - " USING (denominations_serial)" - " WHERE h_blind_ev=$1;"), - /* Used in #postgres_select_withdrawals_above_serial_id() */ - GNUNET_PQ_make_prepare ( - "get_reserve_balance", - "SELECT" - " current_balance_val" - ",current_balance_frac" - " FROM reserves" - " WHERE reserve_pub=$1;"), - /* Fetch deposits with rowid '\geq' the given parameter */ - - GNUNET_PQ_make_prepare ( - "audit_get_reserves_out_incr", - "SELECT" - " h_blind_ev" - ",denom.denom_pub" - ",reserve_sig" - ",reserves.reserve_pub" - ",execution_date" - ",amount_with_fee_val" - ",amount_with_fee_frac" - ",reserve_out_serial_id" - " FROM reserves_out" - " JOIN reserves" - " USING (reserve_uuid)" - " JOIN denominations denom" - " USING (denominations_serial)" - " WHERE reserve_out_serial_id>=$1" - " ORDER BY reserve_out_serial_id ASC;"), - - /* Used in #postgres_count_known_coins() */ - GNUNET_PQ_make_prepare ( - "count_known_coins", - "SELECT" - " COUNT(*) AS count" - " FROM known_coins" - " WHERE denominations_serial=" - " (SELECT denominations_serial" - " FROM denominations" - " WHERE denom_pub_hash=$1);"), - /* Used in #postgres_get_known_coin() to fetch - the denomination public key and signature for - a coin known to the exchange. */ - GNUNET_PQ_make_prepare ( - "get_known_coin", - "SELECT" - " denominations.denom_pub_hash" - ",age_commitment_hash" - ",denom_sig" - " FROM known_coins" - " JOIN denominations USING (denominations_serial)" - " WHERE coin_pub=$1;"), /* Used in #postgres_ensure_coin_known() */ GNUNET_PQ_make_prepare ( "get_known_coin_dh", @@ -706,145 +262,6 @@ prepare_statements (struct PostgresClosure *pg) " FROM known_coins" " JOIN denominations USING (denominations_serial)" " WHERE coin_pub=$1;"), - /* Used in #postgres_get_coin_denomination() to fetch - the denomination public key hash for - a coin known to the exchange. */ - GNUNET_PQ_make_prepare ( - "get_coin_denomination", - "SELECT" - " denominations.denom_pub_hash" - ",known_coin_id" - " FROM known_coins" - " JOIN denominations USING (denominations_serial)" - " WHERE coin_pub=$1" - " FOR SHARE;"), - /* Used in #postgres_insert_known_coin() to store the denomination public - key and signature for a coin known to the exchange. - - See also: - https://stackoverflow.com/questions/34708509/how-to-use-returning-with-on-conflict-in-postgresql/37543015#37543015 - */ - GNUNET_PQ_make_prepare ( - "insert_known_coin", - "WITH dd" - " (denominations_serial" - " ,coin_val" - " ,coin_frac" - " ) AS (" - " SELECT " - " denominations_serial" - " ,coin_val" - " ,coin_frac" - " FROM denominations" - " WHERE denom_pub_hash=$2" - " ), input_rows" - " (coin_pub) AS (" - " VALUES ($1::BYTEA)" - " ), ins AS (" - " INSERT INTO known_coins " - " (coin_pub" - " ,denominations_serial" - " ,age_commitment_hash" - " ,denom_sig" - " ,remaining_val" - " ,remaining_frac" - " ) SELECT " - " $1" - " ,denominations_serial" - " ,$3" - " ,$4" - " ,coin_val" - " ,coin_frac" - " FROM dd" - " ON CONFLICT DO NOTHING" /* CONFLICT on (coin_pub) */ - " RETURNING " - " known_coin_id" - " ) " - "SELECT " - " FALSE AS existed" - " ,known_coin_id" - " ,NULL AS denom_pub_hash" - " ,NULL AS age_commitment_hash" - " FROM ins " - "UNION ALL " - "SELECT " - " TRUE AS existed" - " ,known_coin_id" - " ,denom_pub_hash" - " ,kc.age_commitment_hash" - " FROM input_rows" - " JOIN known_coins kc USING (coin_pub)" - " JOIN denominations USING (denominations_serial)" - " LIMIT 1"), - - /* Used in #postgres_get_melt() to fetch - high-level information about a melt operation */ - GNUNET_PQ_make_prepare ( - "get_melt", - /* "SELECT" - " denoms.denom_pub_hash" - ",denoms.fee_refresh_val" - ",denoms.fee_refresh_frac" - ",old_coin_pub" - ",old_coin_sig" - ",kc.age_commitment_hash" - ",amount_with_fee_val" - ",amount_with_fee_frac" - ",noreveal_index" - ",melt_serial_id" - " FROM refresh_commitments" - " JOIN known_coins kc" - " ON (old_coin_pub = kc.coin_pub)" - " JOIN denominations denoms" - " ON (kc.denominations_serial = denoms.denominations_serial)" - " WHERE rc=$1;", */ - "WITH rc AS MATERIALIZED ( " - " SELECT" - " * FROM refresh_commitments" - " WHERE rc=$1" - ")" - "SELECT" - " denoms.denom_pub_hash" - ",denoms.fee_refresh_val" - ",denoms.fee_refresh_frac" - ",rc.old_coin_pub" - ",rc.old_coin_sig" - ",kc.age_commitment_hash" - ",amount_with_fee_val" - ",amount_with_fee_frac" - ",noreveal_index" - ",melt_serial_id " - "FROM (" - " SELECT" - " * " - " FROM known_coins" - " WHERE coin_pub=(SELECT old_coin_pub from rc)" - ") kc " - "JOIN rc" - " ON (kc.coin_pub=rc.old_coin_pub) " - "JOIN denominations denoms" - " USING (denominations_serial);"), - /* Used in #postgres_select_refreshes_above_serial_id() to fetch - refresh session with id '\geq' the given parameter */ - GNUNET_PQ_make_prepare ( - "audit_get_refresh_commitments_incr", - "SELECT" - " denom.denom_pub" - ",kc.coin_pub AS old_coin_pub" - ",kc.age_commitment_hash" - ",old_coin_sig" - ",amount_with_fee_val" - ",amount_with_fee_frac" - ",noreveal_index" - ",melt_serial_id" - ",rc" - " FROM refresh_commitments" - " JOIN known_coins kc" - " ON (refresh_commitments.old_coin_pub = kc.coin_pub)" - " JOIN denominations denom" - " ON (kc.denominations_serial = denom.denominations_serial)" - " WHERE melt_serial_id>=$1" - " ORDER BY melt_serial_id ASC;"), /* Store information about the desired denominations for a refresh operation, used in #postgres_insert_refresh_reveal() */ GNUNET_PQ_make_prepare ( @@ -863,85 +280,6 @@ prepare_statements (struct PostgresClosure *pg) " FROM denominations" " WHERE denom_pub_hash=$4" " ON CONFLICT DO NOTHING;"), - /* Obtain information about the coins created in a refresh - operation, used in #postgres_get_refresh_reveal() */ - GNUNET_PQ_make_prepare ( - "get_refresh_revealed_coins", - "SELECT " - " rrc.freshcoin_index" - ",denom.denom_pub_hash" - ",rrc.h_coin_ev" - ",rrc.link_sig" - ",rrc.coin_ev" - ",rrc.ewv" - ",rrc.ev_sig" - " FROM refresh_commitments" - " JOIN refresh_revealed_coins rrc" - " USING (melt_serial_id)" - " JOIN denominations denom " - " USING (denominations_serial)" - " WHERE rc=$1;"), - - /* Used in #postgres_insert_refresh_reveal() to store the transfer - keys we learned */ - GNUNET_PQ_make_prepare ( - "insert_refresh_transfer_keys", - "INSERT INTO refresh_transfer_keys " - "(melt_serial_id" - ",transfer_pub" - ",transfer_privs" - ") VALUES ($1, $2, $3)" - " ON CONFLICT DO NOTHING;"), - /* Used in #postgres_insert_refund() to store refund information */ - GNUNET_PQ_make_prepare ( - "insert_refund", - "INSERT INTO refunds " - "(coin_pub " - ",deposit_serial_id" - ",merchant_sig " - ",rtransaction_id " - ",amount_with_fee_val " - ",amount_with_fee_frac " - ") SELECT $1, deposit_serial_id, $3, $5, $6, $7" - " FROM deposits" - " WHERE coin_pub=$1" - " AND h_contract_terms=$4" - " AND merchant_pub=$2"), - /* Query the 'refunds' by coin public key */ - /* Query the 'refunds' by coin public key, merchant_pub and contract hash */ - GNUNET_PQ_make_prepare ( - "get_refunds_by_coin_and_contract", - "SELECT" - " ref.amount_with_fee_val" - ",ref.amount_with_fee_frac" - " FROM refunds ref" - " JOIN deposits dep" - " USING (coin_pub,deposit_serial_id)" - " WHERE ref.coin_pub=$1" - " AND dep.merchant_pub=$2" - " AND dep.h_contract_terms=$3;"), - /* Fetch refunds with rowid '\geq' the given parameter */ - GNUNET_PQ_make_prepare ( - "audit_get_refunds_incr", - "SELECT" - " dep.merchant_pub" - ",ref.merchant_sig" - ",dep.h_contract_terms" - ",ref.rtransaction_id" - ",denom.denom_pub" - ",kc.coin_pub" - ",ref.amount_with_fee_val" - ",ref.amount_with_fee_frac" - ",ref.refund_serial_id" - " FROM refunds ref" - " JOIN deposits dep" - " ON (ref.coin_pub=dep.coin_pub AND ref.deposit_serial_id=dep.deposit_serial_id)" - " JOIN known_coins kc" - " ON (dep.coin_pub=kc.coin_pub)" - " JOIN denominations denom" - " ON (kc.denominations_serial=denom.denominations_serial)" - " WHERE ref.refund_serial_id>=$1" - " ORDER BY ref.refund_serial_id ASC;"), GNUNET_PQ_make_prepare ( "test_refund_full", "SELECT" @@ -954,887 +292,12 @@ prepare_statements (struct PostgresClosure *pg) " ON (ref.coin_pub=dep.coin_pub AND ref.deposit_serial_id=dep.deposit_serial_id)" " WHERE ref.refund_serial_id=$1" " GROUP BY (dep.amount_with_fee_val, dep.amount_with_fee_frac);"), - - /* Store information about a /deposit the exchange is to execute. - Used in #postgres_insert_deposit(). Only used in test cases. */ - GNUNET_PQ_make_prepare ( - "insert_deposit", - "INSERT INTO deposits " - "(known_coin_id" - ",coin_pub" - ",amount_with_fee_val" - ",amount_with_fee_frac" - ",wallet_timestamp" - ",refund_deadline" - ",wire_deadline" - ",merchant_pub" - ",h_contract_terms" - ",wire_salt" - ",wire_target_h_payto" - ",coin_sig" - ",exchange_timestamp" - ",shard" - ") SELECT known_coin_id, $1, $2, $3, $4, $5, $6, " - " $7, $8, $9, $10, $11, $12, $13" - " FROM known_coins" - " WHERE coin_pub=$1" - " ON CONFLICT DO NOTHING;"), - /* Fetch an existing deposit request, used to ensure idempotency - during /deposit processing. Used in #postgres_have_deposit(). */ - GNUNET_PQ_make_prepare ( - "get_deposit", - "SELECT" - " dep.amount_with_fee_val" - ",dep.amount_with_fee_frac" - ",denominations.fee_deposit_val" - ",denominations.fee_deposit_frac" - ",dep.wallet_timestamp" - ",dep.exchange_timestamp" - ",dep.refund_deadline" - ",dep.wire_deadline" - ",dep.h_contract_terms" - ",dep.wire_salt" - ",wt.payto_uri AS receiver_wire_account" - " FROM deposits dep" - " JOIN known_coins kc ON (kc.coin_pub = dep.coin_pub)" - " JOIN denominations USING (denominations_serial)" - " JOIN wire_targets wt USING (wire_target_h_payto)" - " WHERE dep.coin_pub=$1" - " AND dep.merchant_pub=$3" - " AND dep.h_contract_terms=$2;"), - /* Fetch deposits with rowid '\geq' the given parameter */ - GNUNET_PQ_make_prepare ( - "audit_get_deposits_incr", - "SELECT" - " amount_with_fee_val" - ",amount_with_fee_frac" - ",wallet_timestamp" - ",exchange_timestamp" - ",merchant_pub" - ",denom.denom_pub" - ",kc.coin_pub" - ",kc.age_commitment_hash" - ",coin_sig" - ",refund_deadline" - ",wire_deadline" - ",h_contract_terms" - ",wire_salt" - ",payto_uri AS receiver_wire_account" - ",done" - ",deposit_serial_id" - " FROM deposits" - " JOIN wire_targets USING (wire_target_h_payto)" - " JOIN known_coins kc USING (coin_pub)" - " JOIN denominations denom USING (denominations_serial)" - " WHERE (" - " (deposit_serial_id>=$1)" - " )" - " ORDER BY deposit_serial_id ASC;"), - - GNUNET_PQ_make_prepare ( - "audit_get_history_requests_incr", - "SELECT" - " history_request_serial_id" - ",history_fee_val" - ",history_fee_frac" - ",request_timestamp" - ",reserve_pub" - ",reserve_sig" - " FROM history_requests" - " WHERE (" - " (history_request_serial_id>=$1)" - " )" - " ORDER BY history_request_serial_id ASC;"), - - GNUNET_PQ_make_prepare ( - "audit_get_purse_deposits_by_purse", - "SELECT" - " pd.purse_deposit_serial_id" - ",pd.amount_with_fee_val" - ",pd.amount_with_fee_frac" - ",pd.coin_pub" - ",denom.denom_pub" - " FROM purse_deposits pd" - " JOIN known_coins kc USING (coin_pub)" - " JOIN denominations denom USING (denominations_serial)" - " WHERE purse_pub=$1;"), - GNUNET_PQ_make_prepare ( - "audit_get_purse_decisions_incr", - "SELECT" - " pd.purse_pub" - ",pm.reserve_pub" - ",pd.purse_decision_serial_id" - ",pr.amount_with_fee_val" - ",pr.amount_with_fee_frac" - " FROM purse_decision pd" - " JOIN purse_requests pr ON (pd.purse_pub = pr.purse_pub)" - " LEFT JOIN purse_merges pm ON (pm.purse_pub = pd.purse_pub)" - " WHERE (" - " (purse_decision_serial_id>=$1) AND " - " (refunded=$2)" - " )" - " ORDER BY purse_decision_serial_id ASC;"), - /* Fetch an existing deposit request. - Used in #postgres_lookup_transfer_by_deposit(). */ - GNUNET_PQ_make_prepare ( - "get_deposit_without_wtid", - "SELECT" - " agt.legitimization_requirement_serial_id" - ",dep.wire_salt" - ",wt.payto_uri" - ",dep.amount_with_fee_val" - ",dep.amount_with_fee_frac" - ",denom.fee_deposit_val" - ",denom.fee_deposit_frac" - ",dep.wire_deadline" - " FROM deposits dep" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " JOIN known_coins kc" - " ON (kc.coin_pub = dep.coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " LEFT JOIN aggregation_transient agt " - " ON ( (dep.wire_target_h_payto = agt.wire_target_h_payto) AND" - " (dep.merchant_pub = agt.merchant_pub) )" - " WHERE dep.coin_pub=$1" - " AND dep.merchant_pub=$3" - " AND dep.h_contract_terms=$2" - " LIMIT 1;"), - /* Used in #postgres_get_ready_deposit() */ - GNUNET_PQ_make_prepare ( - "deposits_get_ready", - "SELECT" - " payto_uri" - ",merchant_pub" - " FROM deposits_by_ready dbr" - " JOIN deposits dep" - " ON (dbr.coin_pub = dep.coin_pub AND" - " dbr.deposit_serial_id = dep.deposit_serial_id)" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " WHERE dbr.wire_deadline<=$1" - " AND dbr.shard >= $2" - " AND dbr.shard <= $3" - " ORDER BY " - " dbr.wire_deadline ASC" - " ,dbr.shard ASC" - " LIMIT 1;"), - /* Used in #postgres_aggregate() */ - GNUNET_PQ_make_prepare ( - "aggregate", - "WITH rdy AS (" /* find deposits ready by merchant */ - " SELECT" - " coin_pub" - " FROM deposits_for_matching" - " WHERE refund_deadline<$1" /* filter by shard, only actually executable deposits */ - " AND merchant_pub=$2" /* filter by target merchant */ - " ORDER BY refund_deadline ASC" /* ordering is not critical */ - " LIMIT " - TALER_QUOTE (TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) /* limits transaction size */ - " )" - " ,dep AS (" /* restrict to our merchant and account and mark as done */ - " UPDATE deposits" - " SET done=TRUE" - " WHERE coin_pub IN (SELECT coin_pub FROM rdy)" - " AND merchant_pub=$2" /* theoretically, same coin could be spent at another merchant */ - " AND wire_target_h_payto=$3" /* merchant could have a 2nd bank account */ - " AND done=FALSE" /* theoretically, same coin could be spend at the same merchant a 2nd time */ - " RETURNING" - " deposit_serial_id" - " ,coin_pub" - " ,amount_with_fee_val AS amount_val" - " ,amount_with_fee_frac AS amount_frac)" - " ,ref AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ - " SELECT" - " amount_with_fee_val AS refund_val" - " ,amount_with_fee_frac AS refund_frac" - " ,coin_pub" - " ,deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ - " FROM refunds" - " WHERE coin_pub IN (SELECT coin_pub FROM dep)" - " AND deposit_serial_id IN (SELECT deposit_serial_id FROM dep))" - " ,ref_by_coin AS (" /* total up refunds by coin */ - " SELECT" - " SUM(refund_val) AS sum_refund_val" - " ,SUM(refund_frac) AS sum_refund_frac" - " ,coin_pub" - " ,deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ - " FROM ref" - " GROUP BY coin_pub, deposit_serial_id)" - " ,norm_ref_by_coin AS (" /* normalize */ - " SELECT" - " sum_refund_val + sum_refund_frac / 100000000 AS norm_refund_val" - " ,sum_refund_frac % 100000000 AS norm_refund_frac" - " ,coin_pub" - " ,deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ - " FROM ref_by_coin)" - " ,fully_refunded_coins AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ - " SELECT" - " dep.coin_pub" - " FROM norm_ref_by_coin norm" - " JOIN dep" - " ON (norm.coin_pub = dep.coin_pub" - " AND norm.deposit_serial_id = dep.deposit_Serial_id" - " AND norm.norm_refund_val = dep.amount_val" - " AND norm.norm_refund_frac = dep.amount_frac))" - " ,fees AS (" /* find deposit fees for not fully refunded deposits */ - " SELECT" - " denom.fee_deposit_val AS fee_val" - " ,denom.fee_deposit_frac AS fee_frac" - " ,cs.deposit_serial_id" /* ensures we get the fee for each coin, not once per denomination */ - " FROM dep cs" - " JOIN known_coins kc" /* NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ - " USING (coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " WHERE coin_pub NOT IN (SELECT coin_pub FROM fully_refunded_coins))" - " ,dummy AS (" /* add deposits to aggregation_tracking */ - " INSERT INTO aggregation_tracking" - " (deposit_serial_id" - " ,wtid_raw)" - " SELECT deposit_serial_id,$4" - " FROM dep)" - "SELECT" /* calculate totals (deposits, refunds and fees) */ - " CAST(COALESCE(SUM(dep.amount_val),0) AS INT8) AS sum_deposit_value" /* cast needed, otherwise we get NUMBER */ - " ,COALESCE(SUM(dep.amount_frac),0) AS sum_deposit_fraction" /* SUM over INT returns INT8 */ - " ,CAST(COALESCE(SUM(ref.refund_val),0) AS INT8) AS sum_refund_value" - " ,COALESCE(SUM(ref.refund_frac),0) AS sum_refund_fraction" - " ,CAST(COALESCE(SUM(fees.fee_val),0) AS INT8) AS sum_fee_value" - " ,COALESCE(SUM(fees.fee_frac),0) AS sum_fee_fraction" - " FROM dep " - " FULL OUTER JOIN ref ON (FALSE)" /* We just want all sums */ - " FULL OUTER JOIN fees ON (FALSE);"), - - - /* Used in #postgres_create_aggregation_transient() */ - GNUNET_PQ_make_prepare ( - "create_aggregation_transient", - "INSERT INTO aggregation_transient" - " (amount_val" - " ,amount_frac" - " ,merchant_pub" - " ,wire_target_h_payto" - " ,legitimization_requirement_serial_id" - " ,exchange_account_section" - " ,wtid_raw)" - " VALUES ($1, $2, $3, $4, $5, $6, $7);"), - /* Used in #postgres_select_aggregation_transient() */ - GNUNET_PQ_make_prepare ( - "select_aggregation_transient", - "SELECT" - " amount_val" - " ,amount_frac" - " ,wtid_raw" - " FROM aggregation_transient" - " WHERE wire_target_h_payto=$1" - " AND merchant_pub=$2" - " AND exchange_account_section=$3;"), - /* Used in #postgres_find_aggregation_transient() */ - GNUNET_PQ_make_prepare ( - "find_transient_aggregations", - "SELECT" - " amount_val" - " ,amount_frac" - " ,wtid_raw" - " ,merchant_pub" - " ,payto_uri" - " FROM aggregation_transient atr" - " JOIN wire_targets wt USING (wire_target_h_payto)" - " WHERE atr.wire_target_h_payto=$1;"), - /* Used in #postgres_update_aggregation_transient() */ - GNUNET_PQ_make_prepare ( - "update_aggregation_transient", - "UPDATE aggregation_transient" - " SET amount_val=$1" - " ,amount_frac=$2" - " ,legitimization_requirement_serial_id=$5" - " WHERE wire_target_h_payto=$3" - " AND wtid_raw=$4"), - /* Used in #postgres_lookup_wire_transfer */ - GNUNET_PQ_make_prepare ( - "lookup_transactions", - "SELECT" - " aggregation_serial_id" - ",deposits.h_contract_terms" - ",payto_uri" - ",wire_targets.wire_target_h_payto" - ",kc.coin_pub" - ",deposits.merchant_pub" - ",wire_out.execution_date" - ",deposits.amount_with_fee_val" - ",deposits.amount_with_fee_frac" - ",denom.fee_deposit_val" - ",denom.fee_deposit_frac" - ",denom.denom_pub" - " FROM aggregation_tracking" - " JOIN deposits" - " USING (deposit_serial_id)" - " JOIN wire_targets" - " USING (wire_target_h_payto)" - " JOIN known_coins kc" - " USING (coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " JOIN wire_out" - " USING (wtid_raw)" - " WHERE wtid_raw=$1;"), - /* Used in #postgres_lookup_transfer_by_deposit */ - GNUNET_PQ_make_prepare ( - "lookup_deposit_wtid", - "SELECT" - " aggregation_tracking.wtid_raw" - ",wire_out.execution_date" - ",dep.amount_with_fee_val" - ",dep.amount_with_fee_frac" - ",dep.wire_salt" - ",wt.payto_uri" - ",denom.fee_deposit_val" - ",denom.fee_deposit_frac" - " FROM deposits dep" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " JOIN aggregation_tracking" - " USING (deposit_serial_id)" - " JOIN known_coins kc" - " ON (kc.coin_pub = dep.coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " JOIN wire_out" - " USING (wtid_raw)" - " WHERE dep.coin_pub=$1" - " AND dep.merchant_pub=$3" - " AND dep.h_contract_terms=$2"), - - /* Used in #postgres_get_wire_fee() */ - GNUNET_PQ_make_prepare ( - "get_wire_fee", - "SELECT " - " start_date" - ",end_date" - ",wire_fee_val" - ",wire_fee_frac" - ",closing_fee_val" - ",closing_fee_frac" - ",master_sig" - " FROM wire_fee" - " WHERE wire_method=$1" - " AND start_date <= $2" - " AND end_date > $2;"), - /* Used in #postgres_get_global_fee() */ - GNUNET_PQ_make_prepare ( - "get_global_fee", - "SELECT " - " start_date" - ",end_date" - ",history_fee_val" - ",history_fee_frac" - ",account_fee_val" - ",account_fee_frac" - ",purse_fee_val" - ",purse_fee_frac" - ",purse_timeout" - ",history_expiration" - ",purse_account_limit" - ",master_sig" - " FROM global_fee" - " WHERE start_date <= $1" - " AND end_date > $1;"), - /* Used in #postgres_get_global_fees() */ - GNUNET_PQ_make_prepare ( - "get_global_fees", - "SELECT " - " start_date" - ",end_date" - ",history_fee_val" - ",history_fee_frac" - ",account_fee_val" - ",account_fee_frac" - ",purse_fee_val" - ",purse_fee_frac" - ",purse_timeout" - ",history_expiration" - ",purse_account_limit" - ",master_sig" - " FROM global_fee" - " WHERE start_date >= $1"), - /* Used in #postgres_insert_wire_fee */ - GNUNET_PQ_make_prepare ( - "insert_wire_fee", - "INSERT INTO wire_fee " - "(wire_method" - ",start_date" - ",end_date" - ",wire_fee_val" - ",wire_fee_frac" - ",closing_fee_val" - ",closing_fee_frac" - ",master_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8);"), - /* Used in #postgres_insert_global_fee */ - GNUNET_PQ_make_prepare ( - "insert_global_fee", - "INSERT INTO global_fee " - "(start_date" - ",end_date" - ",history_fee_val" - ",history_fee_frac" - ",account_fee_val" - ",account_fee_frac" - ",purse_fee_val" - ",purse_fee_frac" - ",purse_timeout" - ",history_expiration" - ",purse_account_limit" - ",master_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);"), - /* Used in #postgres_store_wire_transfer_out */ - GNUNET_PQ_make_prepare ( - "insert_wire_out", - "INSERT INTO wire_out " - "(execution_date" - ",wtid_raw" - ",wire_target_h_payto" - ",exchange_account_section" - ",amount_val" - ",amount_frac" - ") VALUES " - "($1, $2, $3, $4, $5, $6);"), - /* Used in #postgres_wire_prepare_data_insert() to store - wire transfer information before actually committing it with the bank */ - GNUNET_PQ_make_prepare ( - "wire_prepare_data_insert", - "INSERT INTO prewire " - "(wire_method" - ",buf" - ") VALUES " - "($1, $2);"), - /* Used in #postgres_wire_prepare_data_mark_finished() */ - GNUNET_PQ_make_prepare ( - "wire_prepare_data_mark_done", - "UPDATE prewire" - " SET finished=TRUE" - " WHERE prewire_uuid=$1;"), - /* Used in #postgres_wire_prepare_data_mark_failed() */ - GNUNET_PQ_make_prepare ( - "wire_prepare_data_mark_failed", - "UPDATE prewire" - " SET failed=TRUE" - " WHERE prewire_uuid=$1;"), - /* Used in #postgres_wire_prepare_data_get() */ - GNUNET_PQ_make_prepare ( - "wire_prepare_data_get", - "SELECT" - " prewire_uuid" - ",wire_method" - ",buf" - " FROM prewire" - " WHERE prewire_uuid >= $1" - " AND finished=FALSE" - " AND failed=FALSE" - " ORDER BY prewire_uuid ASC" - " LIMIT $2;"), - /* Used in #postgres_select_deposits_missing_wire */ - // FIXME: used by the auditor; can probably be done - // smarter by checking if 'done' or 'blocked' - // are set correctly when going over deposits, instead - // of JOINing with refunds. - GNUNET_PQ_make_prepare ( - "deposits_get_overdue", - "SELECT" - " deposit_serial_id" - ",coin_pub" - ",amount_with_fee_val" - ",amount_with_fee_frac" - ",payto_uri" - ",wire_deadline" - ",done" - " FROM deposits d" - " JOIN known_coins" - " USING (coin_pub)" - " JOIN wire_targets" - " USING (wire_target_h_payto)" - " WHERE wire_deadline >= $1" - " AND wire_deadline < $2" - " AND NOT (EXISTS (SELECT 1" - " FROM refunds r" - " WHERE (r.coin_pub = d.coin_pub) AND (r.deposit_serial_id = d.deposit_serial_id))" - " OR EXISTS (SELECT 1" - " FROM aggregation_tracking" - " WHERE (aggregation_tracking.deposit_serial_id = d.deposit_serial_id)))" - " ORDER BY wire_deadline ASC"), - /* Used in #postgres_select_wire_out_above_serial_id() */ - GNUNET_PQ_make_prepare ( - "audit_get_wire_incr", - "SELECT" - " wireout_uuid" - ",execution_date" - ",wtid_raw" - ",payto_uri" - ",amount_val" - ",amount_frac" - " FROM wire_out" - " JOIN wire_targets" - " USING (wire_target_h_payto)" - " WHERE wireout_uuid>=$1" - " ORDER BY wireout_uuid ASC;"), - /* Used in #postgres_select_wire_out_above_serial_id_by_account() */ - GNUNET_PQ_make_prepare ( - "audit_get_wire_incr_by_account", - "SELECT" - " wireout_uuid" - ",execution_date" - ",wtid_raw" - ",payto_uri" - ",amount_val" - ",amount_frac" - " FROM wire_out" - " JOIN wire_targets" - " USING (wire_target_h_payto)" - " WHERE " - " wireout_uuid>=$1 " - " AND exchange_account_section=$2" - " ORDER BY wireout_uuid ASC;"), - /* Used in #postgres_select_recoup_above_serial_id() to obtain recoup transactions */ - GNUNET_PQ_make_prepare ( - "recoup_get_incr", - "SELECT" - " recoup_uuid" - ",recoup_timestamp" - ",reserves.reserve_pub" - ",coins.coin_pub" - ",coin_sig" - ",coin_blind" - ",ro.h_blind_ev" - ",denoms.denom_pub_hash" - ",coins.denom_sig" - ",coins.age_commitment_hash" - ",denoms.denom_pub" - ",amount_val" - ",amount_frac" - " FROM recoup" - " JOIN known_coins coins" - " USING (coin_pub)" - " JOIN reserves_out ro" - " USING (reserve_out_serial_id)" - " JOIN reserves" - " USING (reserve_uuid)" - " JOIN denominations denoms" - " ON (coins.denominations_serial = denoms.denominations_serial)" - " WHERE recoup_uuid>=$1" - " ORDER BY recoup_uuid ASC;"), - /* Used in #postgres_select_recoup_refresh_above_serial_id() to obtain - recoup-refresh transactions */ - GNUNET_PQ_make_prepare ( - "recoup_refresh_get_incr", - "SELECT" - " recoup_refresh_uuid" - ",recoup_timestamp" - ",old_coins.coin_pub AS old_coin_pub" - ",new_coins.age_commitment_hash" - ",old_denoms.denom_pub_hash AS old_denom_pub_hash" - ",new_coins.coin_pub As coin_pub" - ",coin_sig" - ",coin_blind" - ",new_denoms.denom_pub AS denom_pub" - ",rrc.h_coin_ev AS h_blind_ev" - ",new_denoms.denom_pub_hash" - ",new_coins.denom_sig AS denom_sig" - ",amount_val" - ",amount_frac" - " FROM recoup_refresh" - " INNER JOIN refresh_revealed_coins rrc" - " USING (rrc_serial)" - " INNER JOIN refresh_commitments rfc" - " ON (rrc.melt_serial_id = rfc.melt_serial_id)" - " INNER JOIN known_coins old_coins" - " ON (rfc.old_coin_pub = old_coins.coin_pub)" - " INNER JOIN known_coins new_coins" - " ON (new_coins.coin_pub = recoup_refresh.coin_pub)" - " INNER JOIN denominations new_denoms" - " ON (new_coins.denominations_serial = new_denoms.denominations_serial)" - " INNER JOIN denominations old_denoms" - " ON (old_coins.denominations_serial = old_denoms.denominations_serial)" - " WHERE recoup_refresh_uuid>=$1" - " ORDER BY recoup_refresh_uuid ASC;"), - /* Used in #postgres_get_reserve_by_h_blind() */ - GNUNET_PQ_make_prepare ( - "reserve_by_h_blind", - "SELECT" - " reserves.reserve_pub" - ",reserve_out_serial_id" - " FROM reserves_out" - " JOIN reserves" - " USING (reserve_uuid)" - " WHERE h_blind_ev=$1" - " LIMIT 1;"), - /* Used in #postgres_get_old_coin_by_h_blind() */ - GNUNET_PQ_make_prepare ( - "old_coin_by_h_blind", - "SELECT" - " okc.coin_pub AS old_coin_pub" - ",rrc_serial" - " FROM refresh_revealed_coins rrc" - " JOIN refresh_commitments rcom USING (melt_serial_id)" - " JOIN known_coins okc ON (rcom.old_coin_pub = okc.coin_pub)" - " WHERE h_coin_ev=$1" - " LIMIT 1;"), - /* Used in #postgres_lookup_auditor_timestamp() */ - GNUNET_PQ_make_prepare ( - "lookup_auditor_timestamp", - "SELECT" - " last_change" - " FROM auditors" - " WHERE auditor_pub=$1;"), - /* Used in #postgres_lookup_auditor_status() */ - GNUNET_PQ_make_prepare ( - "lookup_auditor_status", - "SELECT" - " auditor_url" - ",is_active" - " FROM auditors" - " WHERE auditor_pub=$1;"), - /* Used in #postgres_lookup_wire_timestamp() */ - GNUNET_PQ_make_prepare ( - "lookup_wire_timestamp", - "SELECT" - " last_change" - " FROM wire_accounts" - " WHERE payto_uri=$1;"), - /* used in #postgres_insert_auditor() */ - GNUNET_PQ_make_prepare ( - "insert_auditor", - "INSERT INTO auditors " - "(auditor_pub" - ",auditor_name" - ",auditor_url" - ",is_active" - ",last_change" - ") VALUES " - "($1, $2, $3, true, $4);"), - - /* used in #postgres_insert_wire() */ - GNUNET_PQ_make_prepare ( - "insert_wire", - "INSERT INTO wire_accounts " - "(payto_uri" - ",master_sig" - ",is_active" - ",last_change" - ") VALUES " - "($1, $2, true, $3);"), - /* used in #postgres_update_wire() */ - GNUNET_PQ_make_prepare ( - "update_wire", - "UPDATE wire_accounts" - " SET" - " is_active=$2" - " ,last_change=$3" - " WHERE payto_uri=$1"), - /* used in #postgres_update_wire() */ - GNUNET_PQ_make_prepare ( - "get_wire_accounts", - "SELECT" - " payto_uri" - ",master_sig" - " FROM wire_accounts" - " WHERE is_active"), - /* used in #postgres_update_wire() */ - GNUNET_PQ_make_prepare ( - "get_wire_fees", - "SELECT" - " wire_fee_val" - ",wire_fee_frac" - ",closing_fee_val" - ",closing_fee_frac" - ",start_date" - ",end_date" - ",master_sig" - " FROM wire_fee" - " WHERE wire_method=$1"), - /* used in #postgres_insert_signkey_revocation() */ - GNUNET_PQ_make_prepare ( - "insert_signkey_revocation", - "INSERT INTO signkey_revocations " - "(esk_serial" - ",master_sig" - ") SELECT esk_serial, $2 " - " FROM exchange_sign_keys" - " WHERE exchange_pub=$1;"), - /* used in #postgres_insert_signkey_revocation() */ - GNUNET_PQ_make_prepare ( - "lookup_signkey_revocation", - "SELECT " - " master_sig" - " FROM signkey_revocations" - " WHERE esk_serial=" - " (SELECT esk_serial" - " FROM exchange_sign_keys" - " WHERE exchange_pub=$1);"), - - /* used in #postgres_lookup_signing_key() */ - GNUNET_PQ_make_prepare ( - "lookup_signing_key", - "SELECT" - " valid_from" - ",expire_sign" - ",expire_legal" - " FROM exchange_sign_keys" - " WHERE exchange_pub=$1"), - /* used in #postgres_lookup_denomination_key() */ - GNUNET_PQ_make_prepare ( - "lookup_denomination_key", - "SELECT" - " valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin_val" - ",coin_frac" - ",fee_withdraw_val" - ",fee_withdraw_frac" - ",fee_deposit_val" - ",fee_deposit_frac" - ",fee_refresh_val" - ",fee_refresh_frac" - ",fee_refund_val" - ",fee_refund_frac" - ",age_mask" - " FROM denominations" - " WHERE denom_pub_hash=$1;"), - /* used in #postgres_insert_auditor_denom_sig() */ - GNUNET_PQ_make_prepare ( - "insert_auditor_denom_sig", - "WITH ax AS" - " (SELECT auditor_uuid" - " FROM auditors" - " WHERE auditor_pub=$1)" - "INSERT INTO auditor_denom_sigs " - "(auditor_uuid" - ",denominations_serial" - ",auditor_sig" - ") SELECT ax.auditor_uuid, denominations_serial, $3 " - " FROM denominations" - " CROSS JOIN ax" - " WHERE denom_pub_hash=$2;"), - /* used in #postgres_select_auditor_denom_sig() */ - GNUNET_PQ_make_prepare ( - "select_auditor_denom_sig", - "SELECT" - " auditor_sig" - " FROM auditor_denom_sigs" - " WHERE auditor_uuid=" - " (SELECT auditor_uuid" - " FROM auditors" - " WHERE auditor_pub=$1)" - " AND denominations_serial=" - " (SELECT denominations_serial" - " FROM denominations" - " WHERE denom_pub_hash=$2);"), - - - /* Used in #postgres_begin_shard() */ - GNUNET_PQ_make_prepare ( - "get_open_shard", - "SELECT" - " start_row" - ",end_row" - " FROM work_shards" - " WHERE job_name=$1" - " AND completed=FALSE" - " AND last_attempt<$2" - " ORDER BY last_attempt ASC" - " LIMIT 1;"), - - /* Used in #postgres_begin_shard() */ - GNUNET_PQ_make_prepare ( - "reclaim_shard", - "UPDATE work_shards" - " SET last_attempt=$2" - " WHERE job_name=$1" - " AND start_row=$3" - " AND end_row=$4"), - - /* Used in #postgres_begin_shard() */ - GNUNET_PQ_make_prepare ( - "get_last_shard", - "SELECT" - " end_row" - " FROM work_shards" - " WHERE job_name=$1" - " ORDER BY end_row DESC" - " LIMIT 1;"), - - /* Used in #postgres_abort_shard() */ - GNUNET_PQ_make_prepare ( - "abort_shard", - "UPDATE work_shards" - " SET last_attempt=0" - " WHERE job_name = $1 " - " AND start_row = $2 " - " AND end_row = $3;"), - /* Used in #postgres_begin_shard() */ - GNUNET_PQ_make_prepare ( - "claim_next_shard", - "INSERT INTO work_shards" - "(job_name" - ",last_attempt" - ",start_row" - ",end_row" - ") VALUES " - "($1, $2, $3, $4);"), - - /* Used in #postgres_complete_shard() */ - GNUNET_PQ_make_prepare ( - "complete_shard", - "UPDATE work_shards" - " SET completed=TRUE" - " WHERE job_name=$1" - " AND start_row=$2" - " AND end_row=$3"), - /* Used in #postgres_complete_shard() */ - GNUNET_PQ_make_prepare ( - "release_revolving_shard", - "UPDATE revolving_work_shards" - " SET active=FALSE" - " WHERE job_name=$1" - " AND start_row=$2" - " AND end_row=$3"), - /* Used in #postgres_set_extension_manifest */ - GNUNET_PQ_make_prepare ( - "set_extension_manifest", - "INSERT INTO extensions (name, manifest) VALUES ($1, $2) " - "ON CONFLICT (name) " - "DO UPDATE SET manifest=$2"), - - - /* Used in #postgres_select_purse_by_merge_pub */ - GNUNET_PQ_make_prepare ( - "select_purse_by_merge_pub", - "SELECT " - " purse_pub" - ",purse_expiration" - ",h_contract_terms" - ",age_limit" - ",amount_with_fee_val" - ",amount_with_fee_frac" - ",balance_val" - ",balance_frac" - ",purse_sig" - " FROM purse_requests" - " WHERE merge_pub=$1;"), - - /* Used in #postgres_do_account_merge() */ GNUNET_PQ_make_prepare ( "call_account_merge", "SELECT 1" " FROM exchange_do_account_merge" " ($1, $2, $3);"), - - /* Used in #postgres_update_kyc_requirement_by_row() */ GNUNET_PQ_make_prepare ( "update_legitimization_process", @@ -1846,8 +309,6 @@ prepare_statements (struct PostgresClosure *pg) " h_payto=$3" " AND legitimization_process_serial_id=$1" " AND provider_section=$2;"), - - GNUNET_PQ_PREPARED_STATEMENT_END }; @@ -1923,141 +384,21 @@ TEH_PG_internal_setup (struct PostgresClosure *pg, } -/** - * Register callback to be invoked on events of type @a es. - * - * @param cls database context to use - * @param timeout how long until to generate a timeout event - * @param es specification of the event to listen for - * @param cb function to call when the event happens, possibly - * multiple times (until cancel is invoked) - * @param cb_cls closure for @a cb - * @return handle useful to cancel the listener - */ -static struct GNUNET_DB_EventHandler * -postgres_event_listen (void *cls, - struct GNUNET_TIME_Relative timeout, - const struct GNUNET_DB_EventHeaderP *es, - GNUNET_DB_EventCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - return GNUNET_PQ_event_listen (pg->conn, - es, - timeout, - cb, - cb_cls); -} /** - * Stop notifications. - * - * @param cls the plugin's `struct PostgresClosure` - * @param eh handle to unregister. + * Closure for #get_refunds_cb(). */ -static void -postgres_event_listen_cancel (void *cls, - struct GNUNET_DB_EventHandler *eh) -{ - (void) cls; - GNUNET_PQ_event_listen_cancel (eh); -} - - -/** - * Notify all that listen on @a es of an event. - * - * @param cls database context to use - * @param es specification of the event to generate - * @param extra additional event data provided - * @param extra_size number of bytes in @a extra - */ -static void -postgres_event_notify (void *cls, - const struct GNUNET_DB_EventHeaderP *es, - const void *extra, - size_t extra_size) -{ - struct PostgresClosure *pg = cls; - - GNUNET_PQ_event_notify (pg->conn, - es, - extra, - extra_size); -} - - -/** - * Fetch information about a denomination key. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param denom_pub_hash hash of 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 - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_get_denomination_info ( - void *cls, - const struct TALER_DenominationHashP *denom_pub_hash, - struct TALER_EXCHANGEDB_DenominationKeyInformation *issue) -{ - struct PostgresClosure *pg = cls; - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &issue->signature), - GNUNET_PQ_result_spec_timestamp ("valid_from", - &issue->start), - GNUNET_PQ_result_spec_timestamp ("expire_withdraw", - &issue->expire_withdraw), - GNUNET_PQ_result_spec_timestamp ("expire_deposit", - &issue->expire_deposit), - GNUNET_PQ_result_spec_timestamp ("expire_legal", - &issue->expire_legal), - TALER_PQ_RESULT_SPEC_AMOUNT ("coin", - &issue->value), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", - &issue->fees.withdraw), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &issue->fees.deposit), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", - &issue->fees.refresh), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", - &issue->fees.refund), - GNUNET_PQ_result_spec_uint32 ("age_mask", - &issue->age_mask.bits), - GNUNET_PQ_result_spec_end - }; - - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "denomination_get", - params, - rs); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) - return qs; - issue->denom_hash = *denom_pub_hash; - return qs; -} - - -/** - * Closure for #domination_cb_helper() - */ -struct DenomIteratorContext +struct SelectRefundContext { /** - * Function to call with the results. + * Function to call on each result. */ - TALER_EXCHANGEDB_DenominationCallback cb; + TALER_EXCHANGEDB_RefundCoinCallback cb; /** - * Closure to pass to @e cb + * Closure for @a cb. */ void *cb_cls; @@ -2065,57 +406,36 @@ struct DenomIteratorContext * Plugin context. */ struct PostgresClosure *pg; + + /** + * Set to #GNUNET_SYSERR on error. + */ + int status; }; /** - * Helper function for #postgres_iterate_denomination_info(). - * Calls the callback with each denomination key. + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. * - * @param cls a `struct DenomIteratorContext` - * @param result db results - * @param num_results number of results in @a result + * @param cls closure of type `struct SelectRefundContext *` + * @param result the postgres result + * @param num_results the number of results in @a result */ static void -domination_cb_helper (void *cls, - PGresult *result, - unsigned int num_results) +get_refunds_cb (void *cls, + PGresult *result, + unsigned int num_results) { - struct DenomIteratorContext *dic = cls; - struct PostgresClosure *pg = dic->pg; + struct SelectRefundContext *srctx = cls; + struct PostgresClosure *pg = srctx->pg; for (unsigned int i = 0; istatus = GNUNET_SYSERR; return; } - - /* Unfortunately we have to carry the age mask in both, the - * TALER_DenominationPublicKey and - * TALER_EXCHANGEDB_DenominationKeyInformation at different times. - * Here we use _both_ so let's make sure the values are the same. */ - denom_pub.age_mask = issue.age_mask; - TALER_denom_pub_hash (&denom_pub, - &issue.denom_hash); - if (0 != - GNUNET_memcmp (&issue.denom_hash, - &denom_hash)) - { - GNUNET_break (0); - } - else - { - dic->cb (dic->cb_cls, - &denom_pub, - &issue); - } - TALER_denom_pub_free (&denom_pub); - } -} - - -/** - * Fetch information about all known denomination keys. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param cb function to call on each denomination key - * @param cb_cls closure for @a cb - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_iterate_denomination_info (void *cls, - TALER_EXCHANGEDB_DenominationCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - struct DenomIteratorContext dic = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg - }; - - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "denomination_iterate", - params, - &domination_cb_helper, - &dic); -} - - -/** - * Closure for #dominations_cb_helper() - */ -struct DenomsIteratorContext -{ - /** - * Function to call with the results. - */ - TALER_EXCHANGEDB_DenominationsCallback cb; - - /** - * Closure to pass to @e cb - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct PostgresClosure *pg; -}; - - -/** - * Helper function for #postgres_iterate_denominations(). - * Calls the callback with each denomination key. - * - * @param cls a `struct DenomsIteratorContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -dominations_cb_helper (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct DenomsIteratorContext *dic = cls; - struct PostgresClosure *pg = dic->pg; - - for (unsigned int i = 0; icb (srctx->cb_cls, + &amount_with_fee)) return; - } - - /* make sure the mask information is the same */ - denom_pub.age_mask = meta.age_mask; - - TALER_denom_pub_hash (&denom_pub, - &h_denom_pub); - dic->cb (dic->cb_cls, - &denom_pub, - &h_denom_pub, - &meta, - &master_sig, - revoked); - GNUNET_PQ_cleanup_result (rs); } } -/** - * Function called to invoke @a cb on every known denomination key (revoked - * and non-revoked) that has been signed by the master key. Runs in its own - * read-only transaction. - * - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param cb function to call on each denomination key - * @param cb_cls closure for @a cb - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_iterate_denominations (void *cls, - TALER_EXCHANGEDB_DenominationsCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - struct DenomsIteratorContext dic = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg - }; - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "select_denominations", - params, - &dominations_cb_helper, - &dic); -} - - -/** - * Closure for #auditors_cb_helper() - */ -struct AuditorsIteratorContext -{ - /** - * Function to call with the results. - */ - TALER_EXCHANGEDB_AuditorsCallback cb; - - /** - * Closure to pass to @e cb - */ - void *cb_cls; - -}; - - -/** - * Helper function for #postgres_iterate_active_auditors(). - * Calls the callback with each auditor. - * - * @param cls a `struct SignkeysIteratorContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -auditors_cb_helper (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct AuditorsIteratorContext *dic = cls; - - for (unsigned int i = 0; icb (dic->cb_cls, - &auditor_pub, - auditor_url, - auditor_name); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called to invoke @a cb on every active auditor. Disabled - * auditors are skipped. Runs in its own read-only transaction. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param cb function to call on each active auditor - * @param cb_cls closure for @a cb - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_iterate_active_auditors (void *cls, - TALER_EXCHANGEDB_AuditorsCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - struct AuditorsIteratorContext dic = { - .cb = cb, - .cb_cls = cb_cls, - }; - - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "select_auditors", - params, - &auditors_cb_helper, - &dic); -} - - -/** - * Closure for #auditor_denoms_cb_helper() - */ -struct AuditorDenomsIteratorContext -{ - /** - * Function to call with the results. - */ - TALER_EXCHANGEDB_AuditorDenominationsCallback cb; - - /** - * Closure to pass to @e cb - */ - void *cb_cls; -}; - - -/** - * Helper function for #postgres_iterate_auditor_denominations(). - * Calls the callback with each auditor and denomination pair. - * - * @param cls a `struct AuditorDenomsIteratorContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -auditor_denoms_cb_helper (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct AuditorDenomsIteratorContext *dic = cls; - - for (unsigned int i = 0; icb (dic->cb_cls, - &auditor_pub, - &h_denom_pub, - &auditor_sig); - } -} - - -/** - * Function called to invoke @a cb on every denomination with an active - * auditor. Disabled auditors and denominations without auditor are - * skipped. Runs in its own read-only transaction. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param cb function to call on each active auditor - * @param cb_cls closure for @a cb - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_iterate_auditor_denominations ( - void *cls, - TALER_EXCHANGEDB_AuditorDenominationsCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - struct AuditorDenomsIteratorContext dic = { - .cb = cb, - .cb_cls = cb_cls, - }; - - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "select_auditor_denoms", - params, - &auditor_denoms_cb_helper, - &dic); -} - - -/** - * Get the summary of a reserve. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param[in,out] reserve the reserve data. The public key of the reserve should be - * set in this structure; it is used to query the database. The balance - * and expiration are then filled accordingly. - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_reserves_get (void *cls, - struct TALER_EXCHANGEDB_Reserve *reserve) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&reserve->pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance", - &reserve->balance), - GNUNET_PQ_result_spec_timestamp ("expiration_date", - &reserve->expiry), - GNUNET_PQ_result_spec_timestamp ("gc_date", - &reserve->gc), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "reserves_get", - params, - rs); -} - - -/** - * Get the origin of funds of a reserve. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param reserve_pub public key of the reserve - * @param[out] h_payto set to hash of the wire source payto://-URI - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_reserves_get_origin ( - void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct TALER_PaytoHashP *h_payto) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("wire_source_h_payto", - h_payto), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_h_wire_source_of_reserve", - params, - rs); -} - - -/** - * Extract next KYC alert. Deletes the alert. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param trigger_type which type of alert to drain - * @param[out] h_payto set to hash of payto-URI where KYC status changed - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_drain_kyc_alert (void *cls, - uint32_t trigger_type, - struct TALER_PaytoHashP *h_payto) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint32 (&trigger_type), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("h_payto", - h_payto), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "drain_kyc_alert", - params, - rs); -} - - -/** - * Updates a reserve with the data from the given reserve structure. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param reserve the reserve structure whose data will be used to update the - * corresponding record in the database. - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -reserves_update (void *cls, - const struct TALER_EXCHANGEDB_Reserve *reserve) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&reserve->expiry), - GNUNET_PQ_query_param_timestamp (&reserve->gc), - TALER_PQ_query_param_amount (&reserve->balance), - GNUNET_PQ_query_param_auto_from_type (&reserve->pub), - GNUNET_PQ_query_param_end - }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "reserve_update", - params); -} - - -/** - * Setup new wire target for @a payto_uri. - * - * @param pg the plugin-specific state - * @param payto_uri the payto URI to check - * @param[out] h_payto set to the hash of @a payto_uri - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -setup_wire_target ( - struct PostgresClosure *pg, - const char *payto_uri, - struct TALER_PaytoHashP *h_payto) -{ - struct GNUNET_PQ_QueryParam iparams[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_string (payto_uri), - GNUNET_PQ_query_param_end - }; - - TALER_payto_hash (payto_uri, - h_payto); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_kyc_status", - iparams); -} - - -/** - * Generate event notification for the reserve - * change. - * - * @param pg plugin state - * @param reserve_pub reserve to notfiy on - */ -static void -notify_on_reserve (struct PostgresClosure *pg, - const struct TALER_ReservePublicKeyP *reserve_pub) -{ - struct TALER_ReserveEventP rep = { - .header.size = htons (sizeof (rep)), - .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING), - .reserve_pub = *reserve_pub - }; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Notifying on reserve!\n"); - postgres_event_notify (pg, - &rep.header, - NULL, - 0); -} - - -/** - * Insert an incoming transaction into reserves. New reserves are also - * created through this function. Started within the scope of an ongoing - * transaction. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param reserve_pub public key of the reserve - * @param balance the amount that has to be added to the reserve - * @param execution_time when was the amount added - * @param sender_account_details account information for the sender (payto://-URL) - * @param exchange_account_section name of the section in the configuration for the exchange's - * account into which the deposit was made - * @param wire_ref unique reference identifying the wire transfer - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_reserves_in_insert (void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *balance, - struct GNUNET_TIME_Timestamp execution_time, - const char *sender_account_details, - const char *exchange_account_section, - uint64_t wire_ref) -{ - struct PostgresClosure *pg = cls; - enum GNUNET_DB_QueryStatus qs1; - struct TALER_EXCHANGEDB_Reserve reserve; - struct GNUNET_TIME_Timestamp expiry; - struct GNUNET_TIME_Timestamp gc; - uint64_t reserve_uuid; - - reserve.pub = *reserve_pub; - expiry = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_add (execution_time.abs_time, - pg->idle_reserve_expiration_time)); - gc = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), - pg->legal_reserve_expiration_time)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating reserve %s with expiration in %s\n", - TALER_B2S (reserve_pub), - GNUNET_STRINGS_relative_time_to_string ( - pg->idle_reserve_expiration_time, - GNUNET_NO)); - /* Optimistically assume this is a new reserve, create balance for the first - time; we do this before adding the actual transaction to "reserves_in", - as for a new reserve it can't be a duplicate 'add' operation, and as - the 'add' operation needs the reserve entry as a foreign key. */ - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - TALER_PQ_query_param_amount (balance), - GNUNET_PQ_query_param_timestamp (&expiry), - GNUNET_PQ_query_param_timestamp (&gc), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("reserve_uuid", - &reserve_uuid), - GNUNET_PQ_result_spec_end - }; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Reserve does not exist; creating a new one\n"); - /* Note: query uses 'on conflict do nothing' */ - qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "reserve_create", - params, - rs); - if (qs1 < 0) - return qs1; - } - - /* Create new incoming transaction, "ON CONFLICT DO NOTHING" - is again used to guard against duplicates. */ - { - enum GNUNET_DB_QueryStatus qs2; - enum GNUNET_DB_QueryStatus qs3; - struct TALER_PaytoHashP h_payto; - - qs3 = setup_wire_target (pg, - sender_account_details, - &h_payto); - if (qs3 < 0) - return qs3; - /* We do not have the UUID, so insert by public key */ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&reserve.pub), - GNUNET_PQ_query_param_uint64 (&wire_ref), - TALER_PQ_query_param_amount (balance), - GNUNET_PQ_query_param_string (exchange_account_section), - GNUNET_PQ_query_param_auto_from_type (&h_payto), - GNUNET_PQ_query_param_timestamp (&execution_time), - GNUNET_PQ_query_param_end - }; - - qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "reserves_in_add_transaction", - params); - /* qs2 could be 0 as statement used 'ON CONFLICT DO NOTHING' */ - if (0 >= qs2) - { - if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs2) && - (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1) ) - { - /* Conflict for the transaction, but the reserve was - just now created, that should be impossible. */ - GNUNET_break (0); /* should be impossible: reserve was fresh, - but transaction already known */ - return GNUNET_DB_STATUS_HARD_ERROR; - } - /* Transaction was already known or error. We are finished. */ - return qs2; - } - } - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs1) - { - /* New reserve, we are finished */ - notify_on_reserve (pg, - reserve_pub); - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } - - /* we were wrong with our optimistic assumption: - reserve did already exist, need to do an update instead */ - { - /* We need to move away from 'read committed' to serializable. - Also, we know that it should be safe to commit at this point. - (We are only run in a larger transaction for performance.) */ - enum GNUNET_DB_QueryStatus cs; - - cs = TEH_PG_commit (pg); - if (cs < 0) - return cs; - if (GNUNET_OK != - TEH_PG_start (pg, - "reserve-update-serializable")) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - } - { - enum GNUNET_DB_QueryStatus reserve_exists; - - reserve_exists = postgres_reserves_get (pg, - &reserve); - switch (reserve_exists) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - return reserve_exists; - case GNUNET_DB_STATUS_SOFT_ERROR: - return reserve_exists; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - /* First we got a conflict, but then we cannot select? Very strange. */ - GNUNET_break (0); - return GNUNET_DB_STATUS_SOFT_ERROR; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - /* continued below */ - break; - } - } - - { - struct TALER_EXCHANGEDB_Reserve updated_reserve; - enum GNUNET_DB_QueryStatus qs3; - - /* If the reserve already existed, we need to still update the - balance; we do this after checking for duplication, as - otherwise we might have to actually pay the cost to roll this - back for duplicate transactions; like this, we should virtually - never actually have to rollback anything. */ - updated_reserve.pub = reserve.pub; - if (0 > - TALER_amount_add (&updated_reserve.balance, - &reserve.balance, - balance)) - { - /* currency overflow or incompatible currency */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Attempt to deposit incompatible amount into reserve\n"); - return GNUNET_DB_STATUS_HARD_ERROR; - } - updated_reserve.expiry = GNUNET_TIME_timestamp_max (expiry, - reserve.expiry); - updated_reserve.gc = GNUNET_TIME_timestamp_max (gc, - reserve.gc); - qs3 = reserves_update (pg, - &updated_reserve); - switch (qs3) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - return qs3; - case GNUNET_DB_STATUS_SOFT_ERROR: - return qs3; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - /* How can the UPDATE not work here? Very strange. */ - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - /* continued below */ - break; - } - } - notify_on_reserve (pg, - reserve_pub); - /* Go back to original transaction mode */ - { - enum GNUNET_DB_QueryStatus cs; - - cs = TEH_PG_commit (pg); - if (cs < 0) - return cs; - if (GNUNET_OK != - TEH_PG_start_read_committed (pg, "reserve-insert-continued")) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - } - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; -} - - -/** - * Locate the response for a /reserve/withdraw request under the - * key of the hash of the blinded message. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param bch hash that uniquely identifies the withdraw operation - * @param collectable corresponding collectable coin (blind signature) - * if a coin is found - * @return statement execution status - */ -static enum GNUNET_DB_QueryStatus -postgres_get_withdraw_info ( - void *cls, - const struct TALER_BlindedCoinHashP *bch, - struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (bch), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &collectable->denom_pub_hash), - TALER_PQ_result_spec_blinded_denom_sig ("denom_sig", - &collectable->sig), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &collectable->reserve_sig), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &collectable->reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", - &collectable->h_coin_envelope), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &collectable->amount_with_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", - &collectable->withdraw_fee), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_withdraw_info", - params, - rs); -} - - -/** - * Perform reserve update as part of a batch withdraw operation, checking - * for sufficient balance. Persisting the withdrawal details is done - * separately! - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param now current time (rounded) - * @param reserve_pub public key of the reserve to debit - * @param amount total amount to withdraw - * @param[out] found set to true if the reserve was found - * @param[out] balance_ok set to true if the balance was sufficient - * @param[out] ruuid set to the reserve's UUID (reserves table row) - * @return query execution status - */ -static enum GNUNET_DB_QueryStatus -postgres_do_batch_withdraw ( - void *cls, - struct GNUNET_TIME_Timestamp now, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *amount, - bool *found, - bool *balance_ok, - uint64_t *ruuid) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_TIME_Timestamp gc; - struct GNUNET_PQ_QueryParam params[] = { - TALER_PQ_query_param_amount (amount), - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_timestamp (&now), - GNUNET_PQ_query_param_timestamp (&gc), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("reserve_found", - found), - GNUNET_PQ_result_spec_bool ("balance_ok", - balance_ok), - GNUNET_PQ_result_spec_uint64 ("ruuid", - ruuid), - GNUNET_PQ_result_spec_end - }; - - gc = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_add (now.abs_time, - pg->legal_reserve_expiration_time)); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_batch_withdraw", - params, - rs); -} - - -/** - * Compute the shard number of a given @a merchant_pub. - * - * @param merchant_pub merchant public key to compute shard for - * @return shard number - */ -static uint64_t -compute_shard (const struct TALER_MerchantPublicKeyP *merchant_pub) -{ - uint32_t res; - - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (&res, - sizeof (res), - merchant_pub, - sizeof (*merchant_pub), - "VOID", - 4, - NULL, 0)); - /* interpret hash result as NBO for platform independence, - convert to HBO and map to [0..2^31-1] range */ - res = ntohl (res); - if (res > INT32_MAX) - res += INT32_MIN; - GNUNET_assert (res <= INT32_MAX); - return (uint64_t) res; -} - - -/** - * Perform deposit operation, checking for sufficient balance - * of the coin and possibly persisting the deposit details. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param deposit deposit operation details - * @param known_coin_id row of the coin in the known_coins table - * @param h_payto hash of the merchant's bank account details - * @param policy_details_serial_id pointer to the ID of the entry in policy_details, maybe NULL - * @param[in,out] exchange_timestamp time to use for the deposit (possibly updated) - * @param[out] balance_ok set to true if the balance was sufficient - * @param[out] in_conflict set to true if the deposit conflicted - * @return query execution status - */ -static enum GNUNET_DB_QueryStatus -postgres_do_deposit ( - void *cls, - const struct TALER_EXCHANGEDB_Deposit *deposit, - uint64_t known_coin_id, - const struct TALER_PaytoHashP *h_payto, - uint64_t *policy_details_serial_id, - struct GNUNET_TIME_Timestamp *exchange_timestamp, - bool *balance_ok, - bool *in_conflict) -{ - struct PostgresClosure *pg = cls; - uint64_t deposit_shard = compute_shard (&deposit->merchant_pub); - struct GNUNET_PQ_QueryParam params[] = { - TALER_PQ_query_param_amount (&deposit->amount_with_fee), - GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (&deposit->wire_salt), - GNUNET_PQ_query_param_timestamp (&deposit->timestamp), - GNUNET_PQ_query_param_timestamp (exchange_timestamp), - GNUNET_PQ_query_param_timestamp (&deposit->refund_deadline), - GNUNET_PQ_query_param_timestamp (&deposit->wire_deadline), - GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub), - GNUNET_PQ_query_param_string (deposit->receiver_wire_account), - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_uint64 (&known_coin_id), - GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub), - GNUNET_PQ_query_param_auto_from_type (&deposit->csig), - GNUNET_PQ_query_param_uint64 (&deposit_shard), - GNUNET_PQ_query_param_bool (deposit->has_policy), - (NULL == policy_details_serial_id) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 (policy_details_serial_id), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("balance_ok", - balance_ok), - GNUNET_PQ_result_spec_bool ("conflicted", - in_conflict), - GNUNET_PQ_result_spec_timestamp ("exchange_timestamp", - exchange_timestamp), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_deposit", - params, - rs); -} /* Get the details of a policy, referenced by its hash code @@ -3288,7 +640,7 @@ postgres_do_refund ( bool *conflict) { struct PostgresClosure *pg = cls; - uint64_t deposit_shard = compute_shard (&refund->details.merchant_pub); + uint64_t deposit_shard = TEH_PG_compute_shard (&refund->details.merchant_pub); struct TALER_Amount amount_without_fee; struct GNUNET_PQ_QueryParam params[] = { TALER_PQ_query_param_amount (&refund->details.refund_amount), @@ -3456,7 +808,7 @@ postgres_do_recoup_refresh ( } -/* +/** * Compares two indices into an array of hash codes according to * GNUNET_CRYPTO_hash_cmp of the content at those index positions. * @@ -4275,7 +1627,33 @@ postgres_ensure_coin_known (void *cls, return TALER_EXCHANGEDB_CKS_PRESENT; } +enum GNUNET_DB_QueryStatus +setup_wire_target( + struct PostgresClosure *pg, + const char *payto_uri, + struct TALER_PaytoHashP *h_payto) +{ + struct GNUNET_PQ_QueryParam iparams[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_string (payto_uri), + GNUNET_PQ_query_param_end + }; + TALER_payto_hash (payto_uri, + h_payto); + + PREPARE (pg, + "insert_kyc_status", + "INSERT INTO wire_targets" + " (wire_target_h_payto" + " ,payto_uri" + " ) VALUES " + " ($1, $2)" + " ON CONFLICT DO NOTHING"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_kyc_status", + iparams); +} /** * Insert information about deposited coin into the database. * @@ -4305,7 +1683,7 @@ postgres_insert_deposit (void *cls, GNUNET_break (0); } { - uint64_t shard = compute_shard (&deposit->merchant_pub); + uint64_t shard = TEH_PG_compute_shard (&deposit->merchant_pub); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub), TALER_PQ_query_param_amount (&deposit->amount_with_fee), @@ -4367,75 +1745,6 @@ postgres_insert_refund (void *cls, } -/** - * Closure for #get_refunds_cb(). - */ -struct SelectRefundContext -{ - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_RefundCoinCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct PostgresClosure *pg; - - /** - * Set to #GNUNET_SYSERR on error. - */ - int status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct SelectRefundContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -get_refunds_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct SelectRefundContext *srctx = cls; - struct PostgresClosure *pg = srctx->pg; - - for (unsigned int i = 0; istatus = GNUNET_SYSERR; - return; - } - if (GNUNET_OK != - srctx->cb (srctx->cb_cls, - &amount_with_fee)) - return; - } -} - - /** * Select refunds by @a coin_pub, @a merchant_pub and @a h_contract. * @@ -5556,7 +2865,7 @@ postgres_insert_reserve_closed ( /* update reserve balance */ reserve.pub = *reserve_pub; if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - (qs = postgres_reserves_get (cls, + (qs = TEH_PG_reserves_get (cls, &reserve))) { /* Existence should have been checked before we got here... */ @@ -5583,7 +2892,7 @@ postgres_insert_reserve_closed ( } GNUNET_break (TALER_AAR_RESULT_ZERO == ret); } - return reserves_update (cls, + return TEH_PG_reserves_update (cls, &reserve); } @@ -7606,1439 +4915,6 @@ postgres_get_reserve_by_h_blind ( } -/** - * Obtain information about which old coin a coin was refreshed - * given the hash of the blinded (fresh) coin. - * - * @param cls closure - * @param h_blind_ev hash of the blinded coin - * @param[out] old_coin_pub set to information about the old coin (on success only) - * @param[out] rrc_serial set to serial number of the entry in the database - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_get_old_coin_by_h_blind ( - void *cls, - const struct TALER_BlindedCoinHashP *h_blind_ev, - struct TALER_CoinSpendPublicKeyP *old_coin_pub, - uint64_t *rrc_serial) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_blind_ev), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", - old_coin_pub), - GNUNET_PQ_result_spec_uint64 ("rrc_serial", - rrc_serial), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "old_coin_by_h_blind", - params, - rs); -} - - -/** - * Store information that a denomination key was revoked - * in the database. - * - * @param cls closure - * @param denom_pub_hash hash of the revoked denomination key - * @param master_sig signature affirming the revocation - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_insert_denomination_revocation ( - void *cls, - const struct TALER_DenominationHashP *denom_pub_hash, - const struct TALER_MasterSignatureP *master_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_end - }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "denomination_revocation_insert", - params); -} - - -/** - * Obtain information about a denomination key's revocation from - * the database. - * - * @param cls closure - * @param denom_pub_hash hash of the revoked denomination key - * @param[out] master_sig signature affirming the revocation - * @param[out] rowid row where the information is stored - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_get_denomination_revocation ( - void *cls, - const struct TALER_DenominationHashP *denom_pub_hash, - struct TALER_MasterSignatureP *master_sig, - uint64_t *rowid) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - master_sig), - GNUNET_PQ_result_spec_uint64 ("denom_revocations_serial_id", - rowid), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "denomination_revocation_get", - params, - rs); -} - - -/** - * Closure for #missing_wire_cb(). - */ -struct MissingWireContext -{ - /** - * Function to call per result. - */ - TALER_EXCHANGEDB_WireMissingCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct PostgresClosure *pg; - - /** - * Set to #GNUNET_SYSERR on error. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Invoke the callback for each result. - * - * @param cls a `struct MissingWireContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -missing_wire_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct MissingWireContext *mwc = cls; - struct PostgresClosure *pg = mwc->pg; - - while (0 < num_results) - { - uint64_t rowid; - struct TALER_CoinSpendPublicKeyP coin_pub; - struct TALER_Amount amount; - char *payto_uri; - struct GNUNET_TIME_Timestamp deadline; - bool done; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("deposit_serial_id", - &rowid), - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &coin_pub), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &amount), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri), - GNUNET_PQ_result_spec_timestamp ("wire_deadline", - &deadline), - GNUNET_PQ_result_spec_bool ("done", - &done), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - mwc->status = GNUNET_SYSERR; - return; - } - mwc->cb (mwc->cb_cls, - rowid, - &coin_pub, - &amount, - payto_uri, - deadline, - done); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Select all of those deposits in the database for which we do - * not have a wire transfer (or a refund) and which should have - * been deposited between @a start_date and @a end_date. - * - * @param cls closure - * @param start_date lower bound on the requested wire execution date - * @param end_date upper bound on the requested wire execution date - * @param cb function to call on all such deposits - * @param cb_cls closure for @a cb - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_select_deposits_missing_wire (void *cls, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - TALER_EXCHANGEDB_WireMissingCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&start_date), - GNUNET_PQ_query_param_timestamp (&end_date), - GNUNET_PQ_query_param_end - }; - struct MissingWireContext mwc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "deposits_get_overdue", - params, - &missing_wire_cb, - &mwc); - if (GNUNET_OK != mwc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} - - -/** - * Check the last date an auditor was modified. - * - * @param cls closure - * @param auditor_pub key to look up information for - * @param[out] last_date last modification date to auditor status - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_auditor_timestamp ( - void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - struct GNUNET_TIME_Timestamp *last_date) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (auditor_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("last_change", - last_date), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_auditor_timestamp", - params, - rs); -} - - -/** - * Lookup current state of an auditor. - * - * @param cls closure - * @param auditor_pub key to look up information for - * @param[out] auditor_url set to the base URL of the auditor's REST API; memory to be - * released by the caller! - * @param[out] enabled set if the auditor is currently in use - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_auditor_status ( - void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - char **auditor_url, - bool *enabled) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (auditor_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("auditor_url", - auditor_url), - GNUNET_PQ_result_spec_bool ("is_active", - enabled), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_auditor_status", - params, - rs); -} - - -/** - * Insert information about an auditor that will audit this exchange. - * - * @param cls closure - * @param auditor_pub key of the auditor - * @param auditor_url base URL of the auditor's REST service - * @param auditor_name name of the auditor (for humans) - * @param start_date date when the auditor was added by the offline system - * (only to be used for replay detection) - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_insert_auditor (void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const char *auditor_url, - const char *auditor_name, - struct GNUNET_TIME_Timestamp start_date) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (auditor_pub), - GNUNET_PQ_query_param_string (auditor_name), - GNUNET_PQ_query_param_string (auditor_url), - GNUNET_PQ_query_param_timestamp (&start_date), - GNUNET_PQ_query_param_end - }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_auditor", - params); -} - - -/** - * Check the last date an exchange wire account was modified. - * - * @param cls closure - * @param payto_uri key to look up information for - * @param[out] last_date last modification date to auditor status - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_wire_timestamp (void *cls, - const char *payto_uri, - struct GNUNET_TIME_Timestamp *last_date) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (payto_uri), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("last_change", - last_date), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_wire_timestamp", - params, - rs); -} - - -/** - * Insert information about an wire account used by this exchange. - * - * @param cls closure - * @param payto_uri wire account of the exchange - * @param start_date date when the account was added by the offline system - * (only to be used for replay detection) - * @param master_sig public signature affirming the existence of the account, - * must be of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_insert_wire (void *cls, - const char *payto_uri, - struct GNUNET_TIME_Timestamp start_date, - const struct TALER_MasterSignatureP *master_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (payto_uri), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_timestamp (&start_date), - GNUNET_PQ_query_param_end - }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_wire", - params); -} - - -/** - * Update information about a wire account of the exchange. - * - * @param cls closure - * @param payto_uri account the update is about - * @param change_date date when the account status was last changed - * (only to be used for replay detection) - * @param enabled true to enable, false to disable (the actual change) - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_update_wire (void *cls, - const char *payto_uri, - struct GNUNET_TIME_Timestamp change_date, - bool enabled) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (payto_uri), - GNUNET_PQ_query_param_bool (enabled), - GNUNET_PQ_query_param_timestamp (&change_date), - GNUNET_PQ_query_param_end - }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_wire", - params); -} - - -/** - * Closure for #get_wire_accounts_cb(). - */ -struct GetWireAccountsContext -{ - /** - * Function to call per result. - */ - TALER_EXCHANGEDB_WireAccountCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Flag set to #GNUNET_OK as long as everything is fine. - */ - enum GNUNET_GenericReturnValue status; - -}; - - -/** - * Invoke the callback for each result. - * - * @param cls a `struct MissingWireContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -get_wire_accounts_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct GetWireAccountsContext *ctx = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - char *payto_uri; - struct TALER_MasterSignatureP master_sig; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &master_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ctx->cb (ctx->cb_cls, - payto_uri, - &master_sig); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Obtain information about the enabled wire accounts of the exchange. - * - * @param cls closure - * @param cb function to call on each account - * @param cb_cls closure for @a cb - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_get_wire_accounts (void *cls, - TALER_EXCHANGEDB_WireAccountCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct GetWireAccountsContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .status = GNUNET_OK - }; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "get_wire_accounts", - params, - &get_wire_accounts_cb, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; - -} - - -/** - * Closure for #get_wire_fees_cb(). - */ -struct GetWireFeesContext -{ - /** - * Function to call per result. - */ - TALER_EXCHANGEDB_WireFeeCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct PostgresClosure *pg; - - /** - * Flag set to #GNUNET_OK as long as everything is fine. - */ - enum GNUNET_GenericReturnValue status; - -}; - - -/** - * Invoke the callback for each result. - * - * @param cls a `struct GetWireFeesContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -get_wire_fees_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct GetWireFeesContext *ctx = cls; - struct PostgresClosure *pg = ctx->pg; - - for (unsigned int i = 0; i < num_results; i++) - { - struct TALER_MasterSignatureP master_sig; - struct TALER_WireFeeSet fees; - struct GNUNET_TIME_Timestamp start_date; - struct GNUNET_TIME_Timestamp end_date; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", - &fees.wire), - TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", - &fees.closing), - GNUNET_PQ_result_spec_timestamp ("start_date", - &start_date), - GNUNET_PQ_result_spec_timestamp ("end_date", - &end_date), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &master_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ctx->cb (ctx->cb_cls, - &fees, - start_date, - end_date, - &master_sig); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Obtain information about the fee structure of the exchange for - * a given @a wire_method - * - * @param cls closure - * @param wire_method which wire method to obtain fees for - * @param cb function to call on each account - * @param cb_cls closure for @a cb - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_get_wire_fees (void *cls, - const char *wire_method, - TALER_EXCHANGEDB_WireFeeCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (wire_method), - GNUNET_PQ_query_param_end - }; - struct GetWireFeesContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "get_wire_fees", - params, - &get_wire_fees_cb, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} - - -/** - * Store information about a revoked online signing key. - * - * @param cls closure - * @param exchange_pub exchange online signing key that was revoked - * @param master_sig signature affirming the revocation - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_insert_signkey_revocation ( - void *cls, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_MasterSignatureP *master_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (exchange_pub), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_end - }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_signkey_revocation", - params); -} - - -/** - * Obtain information about a revoked online signing key. - * - * @param cls closure - * @param exchange_pub exchange online signing key - * @param[out] master_sig set to signature affirming the revocation (if revoked) - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_signkey_revocation ( - void *cls, - const struct TALER_ExchangePublicKeyP *exchange_pub, - struct TALER_MasterSignatureP *master_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (exchange_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - master_sig), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_signkey_revocation", - params, - rs); -} - - -/** - * Lookup information about current denomination key. - * - * @param cls closure - * @param h_denom_pub hash of the denomination public key - * @param[out] meta set to various meta data about the key - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_denomination_key ( - void *cls, - const struct TALER_DenominationHashP *h_denom_pub, - struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_denom_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("valid_from", - &meta->start), - GNUNET_PQ_result_spec_timestamp ("expire_withdraw", - &meta->expire_withdraw), - GNUNET_PQ_result_spec_timestamp ("expire_deposit", - &meta->expire_deposit), - GNUNET_PQ_result_spec_timestamp ("expire_legal", - &meta->expire_legal), - TALER_PQ_RESULT_SPEC_AMOUNT ("coin", - &meta->value), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", - &meta->fees.withdraw), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &meta->fees.deposit), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", - &meta->fees.refresh), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", - &meta->fees.refund), - GNUNET_PQ_result_spec_uint32 ("age_mask", - &meta->age_mask.bits), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_denomination_key", - params, - rs); -} - - -/** - * Activate denomination key, turning it into a "current" or "valid" - * denomination key by adding the master signature. - * - * @param cls closure - * @param h_denom_pub hash of the denomination public key - * @param denom_pub the actual denomination key - * @param meta meta data about the denomination - * @param master_sig master signature to add - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_add_denomination_key ( - void *cls, - const struct TALER_DenominationHashP *h_denom_pub, - const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta, - const struct TALER_MasterSignatureP *master_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam iparams[] = { - GNUNET_PQ_query_param_auto_from_type (h_denom_pub), - TALER_PQ_query_param_denom_pub (denom_pub), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_timestamp (&meta->start), - GNUNET_PQ_query_param_timestamp (&meta->expire_withdraw), - GNUNET_PQ_query_param_timestamp (&meta->expire_deposit), - GNUNET_PQ_query_param_timestamp (&meta->expire_legal), - TALER_PQ_query_param_amount (&meta->value), - TALER_PQ_query_param_amount (&meta->fees.withdraw), - TALER_PQ_query_param_amount (&meta->fees.deposit), - TALER_PQ_query_param_amount (&meta->fees.refresh), - TALER_PQ_query_param_amount (&meta->fees.refund), - GNUNET_PQ_query_param_uint32 (&meta->age_mask.bits), - GNUNET_PQ_query_param_end - }; - - /* Sanity check: ensure fees match coin currency */ - GNUNET_assert (GNUNET_YES == - TALER_denom_fee_check_currency (meta->value.currency, - &meta->fees)); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "add_denomination_key", - iparams); -} - - -/** - * Lookup signing key meta data. - * - * @param cls closure - * @param exchange_pub the exchange online signing public key - * @param[out] meta meta data about @a exchange_pub - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_signing_key ( - void *cls, - const struct TALER_ExchangePublicKeyP *exchange_pub, - struct TALER_EXCHANGEDB_SignkeyMetaData *meta) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (exchange_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("valid_from", - &meta->start), - GNUNET_PQ_result_spec_timestamp ("expire_sign", - &meta->expire_sign), - GNUNET_PQ_result_spec_timestamp ("expire_legal", - &meta->expire_legal), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_signing_key", - params, - rs); -} - - -/** - * Insert information about an auditor auditing a denomination key. - * - * @param cls closure - * @param h_denom_pub the audited denomination - * @param auditor_pub the auditor's key - * @param auditor_sig signature affirming the auditor's audit activity - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_insert_auditor_denom_sig ( - void *cls, - const struct TALER_DenominationHashP *h_denom_pub, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const struct TALER_AuditorSignatureP *auditor_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (auditor_pub), - GNUNET_PQ_query_param_auto_from_type (h_denom_pub), - GNUNET_PQ_query_param_auto_from_type (auditor_sig), - GNUNET_PQ_query_param_end - }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_auditor_denom_sig", - params); -} - - -/** - * Select information about an auditor auditing a denomination key. - * - * @param cls closure - * @param h_denom_pub the audited denomination - * @param auditor_pub the auditor's key - * @param[out] auditor_sig set to signature affirming the auditor's audit activity - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_select_auditor_denom_sig ( - void *cls, - const struct TALER_DenominationHashP *h_denom_pub, - const struct TALER_AuditorPublicKeyP *auditor_pub, - struct TALER_AuditorSignatureP *auditor_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (auditor_pub), - GNUNET_PQ_query_param_auto_from_type (h_denom_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("auditor_sig", - auditor_sig), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "select_auditor_denom_sig", - params, - rs); -} - - -/** - * Function called to grab a work shard on an operation @a op. Runs in its - * own transaction. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param job_name name of the operation to grab a word shard for - * @param delay minimum age of a shard to grab - * @param shard_size desired shard size - * @param[out] start_row inclusive start row of the shard (returned) - * @param[out] end_row exclusive end row of the shard (returned) - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_begin_shard (void *cls, - const char *job_name, - struct GNUNET_TIME_Relative delay, - uint64_t shard_size, - uint64_t *start_row, - uint64_t *end_row) -{ - struct PostgresClosure *pg = cls; - - for (unsigned int retries = 0; retries<10; retries++) - { - if (GNUNET_OK != - TEH_PG_start (pg, - "begin_shard")) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - - { - struct GNUNET_TIME_Absolute past; - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_absolute_time (&past), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("start_row", - start_row), - GNUNET_PQ_result_spec_uint64 ("end_row", - end_row), - GNUNET_PQ_result_spec_end - }; - - past = GNUNET_TIME_absolute_get (); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_open_shard", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TEH_PG_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TEH_PG_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - { - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Absolute now; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_uint64 (start_row), - GNUNET_PQ_query_param_uint64 (end_row), - GNUNET_PQ_query_param_end - }; - - now = GNUNET_TIME_relative_to_absolute (delay); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "reclaim_shard", - params); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TEH_PG_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TEH_PG_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - goto commit; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - GNUNET_break (0); /* logic error, should be impossible */ - TEH_PG_rollback (pg); - return GNUNET_DB_STATUS_HARD_ERROR; - } - } - break; /* actually unreachable */ - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - break; /* continued below */ - } - } /* get_open_shard */ - - /* No open shard, find last 'end_row' */ - { - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("end_row", - start_row), - GNUNET_PQ_result_spec_end - }; - - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_last_shard", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TEH_PG_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TEH_PG_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - break; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - *start_row = 0; /* base-case: no shards yet */ - break; /* continued below */ - } - *end_row = *start_row + shard_size; - } /* get_last_shard */ - - /* Claim fresh shard */ - { - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Absolute now; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_uint64 (start_row), - GNUNET_PQ_query_param_uint64 (end_row), - GNUNET_PQ_query_param_end - }; - - now = GNUNET_TIME_relative_to_absolute (delay); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Trying to claim shard (%llu-%llu]\n", - (unsigned long long) *start_row, - (unsigned long long) *end_row); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "claim_next_shard", - params); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TEH_PG_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TEH_PG_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - /* continued below */ - break; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - /* someone else got this shard already, - try again */ - TEH_PG_rollback (pg); - continue; - } - } /* claim_next_shard */ - - /* commit */ -commit: - { - enum GNUNET_DB_QueryStatus qs; - - qs = TEH_PG_commit (pg); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TEH_PG_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TEH_PG_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } - } - } /* retry 'for' loop */ - return GNUNET_DB_STATUS_SOFT_ERROR; -} - - -/** - * Function called to abort work on a shard. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param job_name name of the operation to abort a word shard for - * @param start_row inclusive start row of the shard - * @param end_row exclusive end row of the shard - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_abort_shard (void *cls, - const char *job_name, - uint64_t start_row, - uint64_t end_row) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_uint64 (&start_row), - GNUNET_PQ_query_param_uint64 (&end_row), - GNUNET_PQ_query_param_end - }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "abort_shard", - params); -} - - -/** - * Function called to persist that work on a shard was completed. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param job_name name of the operation to grab a word shard for - * @param start_row inclusive start row of the shard - * @param end_row exclusive end row of the shard - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -postgres_complete_shard (void *cls, - const char *job_name, - uint64_t start_row, - uint64_t end_row) -{ - struct PostgresClosure *pg = cls; - - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_uint64 (&start_row), - GNUNET_PQ_query_param_uint64 (&end_row), - GNUNET_PQ_query_param_end - }; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Completing shard %llu-%llu\n", - (unsigned long long) start_row, - (unsigned long long) end_row); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "complete_shard", - params); -} - - -/** - * Function called to release a revolving shard - * back into the work pool. Clears the - * "completed" flag. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param job_name name of the operation to grab a word shard for - * @param start_row inclusive start row of the shard - * @param end_row exclusive end row of the shard - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -postgres_release_revolving_shard (void *cls, - const char *job_name, - uint32_t start_row, - uint32_t end_row) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_uint32 (&start_row), - GNUNET_PQ_query_param_uint32 (&end_row), - GNUNET_PQ_query_param_end - }; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Releasing revolving shard %s %u-%u\n", - job_name, - (unsigned int) start_row, - (unsigned int) end_row); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "release_revolving_shard", - params); -} - - -/** - * Function called to delete all revolving shards. - * To be used after a crash or when the shard size is - * changed. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @return transaction status code - */ -enum GNUNET_GenericReturnValue -postgres_delete_shard_locks (void *cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_execute ("DELETE FROM work_shards;"), - GNUNET_PQ_make_execute ("DELETE FROM revolving_work_shards;"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - - return GNUNET_PQ_exec_statements (pg->conn, - es); -} - - -/** - * Function called to save the manifest of an extension - * (age-restriction, policy_extension_...) After successful storage of the - * configuration it triggers the corresponding event. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param extension_name the name of the extension - * @param manifest JSON object of the configuration as string - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -postgres_set_extension_manifest (void *cls, - const char *extension_name, - const char *manifest) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam pcfg = - (NULL == manifest || 0 == *manifest) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (manifest); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (extension_name), - pcfg, - GNUNET_PQ_query_param_end - }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "set_extension_manifest", - params); -} - - -/** - * Function called to store configuration data about a partner - * exchange that we are federated with. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub public offline signing key of the partner exchange - * @param start_date when does the following data start to be valid - * @param end_date when does the validity end (exclusive) - * @param wad_frequency how often do we do exchange-to-exchange settlements? - * @param wad_fee how much do we charge for transfers to the partner - * @param partner_base_url base URL of the partner exchange - * @param master_sig signature with our offline signing key affirming the above - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_insert_partner (void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - struct GNUNET_TIME_Relative wad_frequency, - const struct TALER_Amount *wad_fee, - const char *partner_base_url, - const struct TALER_MasterSignatureP *master_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (master_pub), - GNUNET_PQ_query_param_timestamp (&start_date), - GNUNET_PQ_query_param_timestamp (&end_date), - GNUNET_PQ_query_param_relative_time (&wad_frequency), - TALER_PQ_query_param_amount (wad_fee), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_string (partner_base_url), - GNUNET_PQ_query_param_end - }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_partner", - params); -} - - -/** - * Function called to clean up one expired purse. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param start_time select purse expired after this time - * @param end_time select purse expired before this time - * @return transaction status code (#GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no purse expired in the given time interval). - */ -static enum GNUNET_DB_QueryStatus -postgres_expire_purse ( - void *cls, - struct GNUNET_TIME_Absolute start_time, - struct GNUNET_TIME_Absolute end_time) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_absolute_time (&start_time), - GNUNET_PQ_query_param_absolute_time (&end_time), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_end - }; - bool found = false; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("found", - &found), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_expire_purse", - params, - rs); - if (qs < 0) - return qs; - GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); - return found - ? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT - : GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; -} - - -/** - * Function called to return meta data about a purse by the - * merge capability key. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param merge_pub public key representing the merge capability - * @param[out] purse_pub public key of the purse - * @param[out] purse_expiration when would an unmerged purse expire - * @param[out] h_contract_terms contract associated with the purse - * @param[out] age_limit the age limit for deposits into the purse - * @param[out] target_amount amount to be put into the purse - * @param[out] balance amount put so far into the purse - * @param[out] purse_sig signature of the purse over the initialization data - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_select_purse_by_merge_pub ( - void *cls, - const struct TALER_PurseMergePublicKeyP *merge_pub, - struct TALER_PurseContractPublicKeyP *purse_pub, - struct GNUNET_TIME_Timestamp *purse_expiration, - struct TALER_PrivateContractHashP *h_contract_terms, - uint32_t *age_limit, - struct TALER_Amount *target_amount, - struct TALER_Amount *balance, - struct TALER_PurseContractSignatureP *purse_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (merge_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - purse_pub), - GNUNET_PQ_result_spec_timestamp ("purse_expiration", - purse_expiration), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - h_contract_terms), - GNUNET_PQ_result_spec_uint32 ("age_limit", - age_limit), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - target_amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("balance", - balance), - GNUNET_PQ_result_spec_auto_from_type ("purse_sig", - purse_sig), - GNUNET_PQ_result_spec_end - }; - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "select_purse_by_merge_pub", - params, - rs); -} - - -/** - * Set the current @a balance in the purse - * identified by @a purse_pub. Used by the auditor - * to update the balance as calculated by the auditor. - * - * @param cls closure - * @param purse_pub public key of a purse - * @param balance new balance to store under the purse - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_set_purse_balance ( - void *cls, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_Amount *balance) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - TALER_PQ_query_param_amount (balance), - GNUNET_PQ_query_param_end - }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "set_purse_balance", - params); -} - - /** * Initialize Postgres database subsystem. * @@ -9146,29 +5022,10 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) GNUNET_free (pg); return NULL; } - plugin = GNUNET_new (struct TALER_EXCHANGEDB_Plugin); plugin->cls = pg; - plugin->create_tables = &postgres_create_tables; - plugin->setup_foreign_servers = &postgres_setup_foreign_servers; - plugin->event_listen = &postgres_event_listen; - plugin->event_listen_cancel = &postgres_event_listen_cancel; - plugin->event_notify = &postgres_event_notify; - plugin->get_denomination_info = &postgres_get_denomination_info; - plugin->iterate_denomination_info = &postgres_iterate_denomination_info; - plugin->iterate_denominations = &postgres_iterate_denominations; - plugin->iterate_active_auditors = &postgres_iterate_active_auditors; - plugin->iterate_auditor_denominations = - &postgres_iterate_auditor_denominations; - plugin->reserves_get = &postgres_reserves_get; - plugin->reserves_get_origin = &postgres_reserves_get_origin; - plugin->drain_kyc_alert = &postgres_drain_kyc_alert; - plugin->reserves_in_insert = &postgres_reserves_in_insert; - plugin->get_withdraw_info = &postgres_get_withdraw_info; - plugin->do_batch_withdraw = &postgres_do_batch_withdraw; plugin->get_policy_details = &postgres_get_policy_details; plugin->persist_policy_details = &postgres_persist_policy_details; - plugin->do_deposit = &postgres_do_deposit; plugin->add_policy_fulfillment_proof = &postgres_add_policy_fulfillment_proof; plugin->do_melt = &postgres_do_melt; plugin->do_refund = &postgres_do_refund; @@ -9213,6 +5070,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) plugin->start_deferred_wire_out = &postgres_start_deferred_wire_out; plugin->store_wire_transfer_out = &postgres_store_wire_transfer_out; plugin->gc = &postgres_gc; + plugin->select_deposits_above_serial_id = &postgres_select_deposits_above_serial_id; plugin->select_history_requests_above_serial_id @@ -9241,67 +5099,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) = &postgres_select_recoup_refresh_above_serial_id; plugin->get_reserve_by_h_blind = &postgres_get_reserve_by_h_blind; - plugin->get_old_coin_by_h_blind - = &postgres_get_old_coin_by_h_blind; - plugin->insert_denomination_revocation - = &postgres_insert_denomination_revocation; - plugin->get_denomination_revocation - = &postgres_get_denomination_revocation; - plugin->select_deposits_missing_wire - = &postgres_select_deposits_missing_wire; - plugin->lookup_auditor_timestamp - = &postgres_lookup_auditor_timestamp; - plugin->lookup_auditor_status - = &postgres_lookup_auditor_status; - plugin->insert_auditor - = &postgres_insert_auditor; - plugin->lookup_wire_timestamp - = &postgres_lookup_wire_timestamp; - plugin->insert_wire - = &postgres_insert_wire; - plugin->update_wire - = &postgres_update_wire; - plugin->get_wire_accounts - = &postgres_get_wire_accounts; - plugin->get_wire_fees - = &postgres_get_wire_fees; - plugin->insert_signkey_revocation - = &postgres_insert_signkey_revocation; - plugin->lookup_signkey_revocation - = &postgres_lookup_signkey_revocation; - plugin->lookup_denomination_key - = &postgres_lookup_denomination_key; - plugin->insert_auditor_denom_sig - = &postgres_insert_auditor_denom_sig; - plugin->select_auditor_denom_sig - = &postgres_select_auditor_denom_sig; - plugin->add_denomination_key - = &postgres_add_denomination_key; - plugin->lookup_signing_key - = &postgres_lookup_signing_key; - plugin->begin_shard - = &postgres_begin_shard; - plugin->abort_shard - = &postgres_abort_shard; - plugin->complete_shard - = &postgres_complete_shard; - plugin->release_revolving_shard - = &postgres_release_revolving_shard; - plugin->delete_shard_locks - = &postgres_delete_shard_locks; - plugin->set_extension_manifest - = &postgres_set_extension_manifest; - plugin->insert_partner - = &postgres_insert_partner; - plugin->expire_purse - = &postgres_expire_purse; - plugin->select_purse_by_merge_pub - = &postgres_select_purse_by_merge_pub; - plugin->set_purse_balance - = &postgres_set_purse_balance; - - /* NEW style, sort alphabetically! */ + /* New style, sort alphabetically! */ plugin->do_reserve_open = &TEH_PG_do_reserve_open; plugin->drop_tables @@ -9386,8 +5185,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) = &TEH_PG_lookup_kyc_requirement_by_row; plugin->insert_kyc_requirement_for_account = &TEH_PG_insert_kyc_requirement_for_account; - - plugin->lookup_kyc_process_by_account = &TEH_PG_lookup_kyc_process_by_account; plugin->update_kyc_process_by_row @@ -9449,6 +5246,206 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) plugin->rollback = &TEH_PG_rollback; + plugin->create_tables + = &TEH_PG_create_tables; + plugin->setup_foreign_servers + = &TEH_PG_setup_foreign_servers; + plugin->event_listen + = &TEH_PG_event_listen; + plugin->event_listen_cancel + = &TEH_PG_event_listen_cancel; + plugin->event_notify + = &TEH_PG_event_notify; + plugin->get_denomination_info + = &TEH_PG_get_denomination_info; + plugin->iterate_denomination_info + = &TEH_PG_iterate_denomination_info; + plugin->iterate_denominations + = &TEH_PG_iterate_denominations; + plugin->iterate_active_auditors + = &TEH_PG_iterate_active_auditors; + plugin->iterate_auditor_denominations + = &TEH_PG_iterate_auditor_denominations; + plugin->reserves_get + = &TEH_PG_reserves_get; + plugin->reserves_get_origin + = &TEH_PG_reserves_get_origin; + plugin->drain_kyc_alert + = &TEH_PG_drain_kyc_alert; + plugin->reserves_in_insert + = &TEH_PG_reserves_in_insert; + plugin->get_withdraw_info + = &TEH_PG_get_withdraw_info; + plugin->do_batch_withdraw + = &TEH_PG_do_batch_withdraw; + plugin->get_policy_details + = &TEH_PG_get_policy_details; + plugin->persist_policy_details + = &TEH_PG_persist_policy_details; + plugin->do_deposit + = &TEH_PG_do_deposit; + plugin->add_policy_fulfillment_proof + = &TEH_PG_add_policy_fulfillment_proof; + plugin->do_melt + = &TEH_PG_do_melt; + plugin->do_refund + = &TEH_PG_do_refund; + plugin->do_recoup + = &TEH_PG_do_recoup; + plugin->do_recoup_refresh + = &TEH_PG_do_recoup_refresh; + plugin->get_reserve_balance + = &TEH_PG_get_reserve_balance; + plugin->count_known_coins + = &TEH_PG_count_known_coins; + plugin->ensure_coin_known + = &TEH_PG_ensure_coin_known; + plugin->get_known_coin + = &TEH_PG_get_known_coin; + plugin->get_coin_denomination + = &TEH_PG_get_coin_denomination; + plugin->have_deposit2 + = &TEH_PG_have_deposit2; + plugin->aggregate + = &TEH_PG_aggregate; + plugin->create_aggregation_transient + = &TEH_PG_create_aggregation_transient; + plugin->select_aggregation_transient + = &TEH_PG_select_aggregation_transient; + plugin->find_aggregation_transient + = &TEH_PG_find_aggregation_transient; + plugin->update_aggregation_transient + = &TEH_PG_update_aggregation_transient; + plugin->get_ready_deposit + = &TEH_PG_get_ready_deposit; + plugin->insert_deposit + = &TEH_PG_insert_deposit; + plugin->insert_refund + = &TEH_PG_insert_refund; + plugin->select_refunds_by_coin + = &TEH_PG_select_refunds_by_coin; + plugin->get_melt + = &TEH_PG_get_melt; + plugin->insert_refresh_reveal + = &TEH_PG_insert_refresh_reveal; + plugin->get_refresh_reveal + = &TEH_PG_get_refresh_reveal; + plugin->lookup_wire_transfer + = &TEH_PG_lookup_wire_transfer; + plugin->lookup_transfer_by_deposit + = &TEH_PG_lookup_transfer_by_deposit; + plugin->insert_wire_fee + = &TEH_PG_insert_wire_fee; + plugin->insert_global_fee + = &TEH_PG_insert_global_fee; + plugin->get_wire_fee + = &TEH_PG_get_wire_fee; + plugin->get_global_fee + = &TEH_PG_get_global_fee; + plugin->get_global_fees + = &TEH_PG_get_global_fees; + plugin->insert_reserve_closed + = &TEH_PG_insert_reserve_closed; + plugin->wire_prepare_data_insert + = &TEH_PG_wire_prepare_data_insert; + plugin->wire_prepare_data_mark_finished + = &TEH_PG_wire_prepare_data_mark_finished; + plugin->wire_prepare_data_mark_failed + = &TEH_PG_wire_prepare_data_mark_failed; + plugin->wire_prepare_data_get + = &TEH_PG_wire_prepare_data_get; + plugin->start_deferred_wire_out + = &TEH_PG_start_deferred_wire_out; + plugin->store_wire_transfer_out + = &TEH_PG_store_wire_transfer_out; + plugin->gc + = &TEH_PG_gc; + plugin->select_deposits_above_serial_id + = &TEH_PG_select_deposits_above_serial_id; + plugin->select_history_requests_above_serial_id + = &TEH_PG_select_history_requests_above_serial_id; + plugin->select_purse_decisions_above_serial_id + = &TEH_PG_select_purse_decisions_above_serial_id; + plugin->select_purse_deposits_by_purse + = &TEH_PG_select_purse_deposits_by_purse; + plugin->select_refreshes_above_serial_id + = &TEH_PG_select_refreshes_above_serial_id; + plugin->select_refunds_above_serial_id + = &TEH_PG_select_refunds_above_serial_id; + plugin->select_reserves_in_above_serial_id + = &TEH_PG_select_reserves_in_above_serial_id; + plugin->select_reserves_in_above_serial_id_by_account + = &TEH_PG_select_reserves_in_above_serial_id_by_account; + plugin->select_withdrawals_above_serial_id + = &TEH_PG_select_withdrawals_above_serial_id; + plugin->select_wire_out_above_serial_id + = &TEH_PG_select_wire_out_above_serial_id; + plugin->select_wire_out_above_serial_id_by_account + = &TEH_PG_select_wire_out_above_serial_id_by_account; + plugin->select_recoup_above_serial_id + = &TEH_PG_select_recoup_above_serial_id; + plugin->select_recoup_refresh_above_serial_id + = &TEH_PG_select_recoup_refresh_above_serial_id; + plugin->get_reserve_by_h_blind + = &TEH_PG_get_reserve_by_h_blind; + plugin->get_old_coin_by_h_blind + = &TEH_PG_get_old_coin_by_h_blind; + plugin->insert_denomination_revocation + = &TEH_PG_insert_denomination_revocation; + plugin->get_denomination_revocation + = &TEH_PG_get_denomination_revocation; + plugin->select_deposits_missing_wire + = &TEH_PG_select_deposits_missing_wire; + plugin->lookup_auditor_timestamp + = &TEH_PG_lookup_auditor_timestamp; + plugin->lookup_auditor_status + = &TEH_PG_lookup_auditor_status; + plugin->insert_auditor + = &TEH_PG_insert_auditor; + plugin->lookup_wire_timestamp + = &TEH_PG_lookup_wire_timestamp; + plugin->insert_wire + = &TEH_PG_insert_wire; + plugin->update_wire + = &TEH_PG_update_wire; + plugin->get_wire_accounts + = &TEH_PG_get_wire_accounts; + plugin->get_wire_fees + = &TEH_PG_get_wire_fees; + plugin->insert_signkey_revocation + = &TEH_PG_insert_signkey_revocation; + plugin->lookup_signkey_revocation + = &TEH_PG_lookup_signkey_revocation; + plugin->lookup_denomination_key + = &TEH_PG_lookup_denomination_key; + plugin->insert_auditor_denom_sig + = &TEH_PG_insert_auditor_denom_sig; + plugin->select_auditor_denom_sig + = &TEH_PG_select_auditor_denom_sig; + plugin->add_denomination_key + = &TEH_PG_add_denomination_key; + plugin->lookup_signing_key + = &TEH_PG_lookup_signing_key; + plugin->begin_shard + = &TEH_PG_begin_shard; + plugin->abort_shard + = &TEH_PG_abort_shard; + plugin->complete_shard + = &TEH_PG_complete_shard; + plugin->release_revolving_shard + = &TEH_PG_release_revolving_shard; + plugin->delete_shard_locks + = &TEH_PG_delete_shard_locks; + plugin->set_extension_manifest + = &TEH_PG_set_extension_manifest; + plugin->insert_partner + = &TEH_PG_insert_partner; + plugin->expire_purse + = &TEH_PG_expire_purse; + plugin->select_purse_by_merge_pub + = &TEH_PG_select_purse_by_merge_pub; + plugin->set_purse_balance + = &TEH_PG_set_purse_balance; return plugin; }