diff options
Diffstat (limited to 'src')
208 files changed, 15673 insertions, 4364 deletions
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am index bae4eba0..ac300a9c 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 00000000..de10f7d3 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..070b48da --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e115a44e --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..d131679e --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..bb06206a --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..77bddaf0 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..f1c4d677 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..1f986ef9 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..2d4a33af --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..39bd834e --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..5efea7c0 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..8693f402 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..1dea591f --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..d9bde2d3 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..28c4612f --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..f5dd4f27 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..4ced9da0 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..2f0a348b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..63211cf5 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..7fb7a56f --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e55cf25f --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e8df2d67 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..8ef1be26 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..ee4bf293 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..c8f25e5b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e71cf0e4 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..6f81ff38 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..554ce08b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..00f7bdd8 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..07a35078 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..be5e4705 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..3ac0f0a0 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..1059f9cb --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..7118858d --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..d635d95e --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..bfaf0489 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..6b2385ad --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..76581d4b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..c557ed3c --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..1be14077 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..5d65827c --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..258d7a58 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..577f4acb --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..3b937cba --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..6ef7a277 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..fe05fd52 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..a5f367b5 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_Amount amount; +    char *payto_uri; +    struct TALER_WireTransferIdentifierRawP wtid; +    struct TALER_MerchantPublicKeyP merchant_pub; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", +                                            &merchant_pub), +      GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", +                                            &wtid), +      GNUNET_PQ_result_spec_string ("payto_uri", +                                    &payto_uri), +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount", +                                   &amount), +      GNUNET_PQ_result_spec_end +    }; +    bool cont; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      srctx->status = 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 00000000..c7ba4ea3 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e01c1e10 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..9e6ffbc3 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e82b86aa --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..3b9f03f3 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..97250b62 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..84322775 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..4d29d88c --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..d022c822 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..6f6bbafe --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..0887d54d --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..0e1736bd --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_GlobalFeeSet fees; +    struct GNUNET_TIME_Relative purse_timeout; +    struct GNUNET_TIME_Relative history_expiration; +    uint32_t purse_account_limit; +    struct GNUNET_TIME_Timestamp start_date; +    struct GNUNET_TIME_Timestamp end_date; +    struct TALER_MasterSignatureP master_sig; +    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 +    }; +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      gctx->status = 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 00000000..c8f6f02c --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..fe5c683b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..d7f55b33 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..f239c605 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..73d757a0 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..385c3f1d --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..1404990d --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..5dacb600 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e3d2b0a2 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..741a480d --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..19b6dafe --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e2db082b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..0fcea26c --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e08261fc --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..fd15f0d8 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..2105b476 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..49c1c840 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..6986eaef --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..4ddda0ed --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..4b432476 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..92107fe3 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..a83db151 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..83bacd67 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..ef393626 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..7c3e06a0 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..1616858c --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..0e8119c2 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..757dfa62 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..7523282e --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..3643a87f --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..baa67cfe --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..061d7adc --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e3da8766 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..09247e28 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..15de39ef --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..c08fc23b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..9780d532 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..567f3776 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..eed40a80 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..098a3aed --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_rrcs; i++) +  { +    const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i]; +    struct GNUNET_PQ_QueryParam params[] = { +      GNUNET_PQ_query_param_uint64 (&melt_serial_id), +      GNUNET_PQ_query_param_uint32 (&i), +      GNUNET_PQ_query_param_auto_from_type (&rrc->orig_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 00000000..ad53ab19 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..047df033 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..02190bcc --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..d17c37ed --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..2ac1a6e3 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..9197be6a --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..534e6d45 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..646bce94 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..15ce0867 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..278ec2bc --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e53faf5a --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..11b10cb4 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_AuditorPublicKeyP auditor_pub; +    char *auditor_url; +    char *auditor_name; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("auditor_pub", +                                            &auditor_pub), +      GNUNET_PQ_result_spec_string ("auditor_url", +                                    &auditor_url), +      GNUNET_PQ_result_spec_string ("auditor_name", +                                    &auditor_name), +      GNUNET_PQ_result_spec_end +    }; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      return; +    } +    dic->cb (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 00000000..1247d2d3 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..6456ed1d --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_AuditorPublicKeyP auditor_pub; +    struct TALER_DenominationHashP h_denom_pub; +    struct TALER_AuditorSignatureP auditor_sig; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("auditor_pub", +                                            &auditor_pub), +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", +                                            &h_denom_pub), +      GNUNET_PQ_result_spec_auto_from_type ("auditor_sig", +                                            &auditor_sig), +      GNUNET_PQ_result_spec_end +    }; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      return; +    } +    dic->cb (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 00000000..da1f3670 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..bf39a65a --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_EXCHANGEDB_DenominationKeyInformation issue; +    struct TALER_DenominationPublicKey denom_pub; +    struct TALER_DenominationHashP denom_hash; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("master_sig", +                                            &issue.signature), +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", +                                            &denom_hash), +      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), +      TALER_PQ_result_spec_denom_pub ("denom_pub", +                                      &denom_pub), +      GNUNET_PQ_result_spec_uint32 ("age_mask", +                                    &issue.age_mask.bits), +      GNUNET_PQ_result_spec_end +    }; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      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 + */ +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 00000000..57847a51 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..d8a91f55 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0}; +    struct TALER_DenominationPublicKey denom_pub = {0}; +    struct TALER_MasterSignatureP master_sig = {0}; +    struct TALER_DenominationHashP h_denom_pub = {0}; +    bool revoked; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("master_sig", +                                            &master_sig), +      GNUNET_PQ_result_spec_bool ("revoked", +                                  &revoked), +      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), +      TALER_PQ_result_spec_denom_pub ("denom_pub", +                                      &denom_pub), +      GNUNET_PQ_result_spec_uint32 ("age_mask", +                                    &meta.age_mask.bits), +      GNUNET_PQ_result_spec_end +    }; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      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); +  } +} + + +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 00000000..a205fc6b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..5e62bfa9 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..b75788e1 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..3a4bd6be --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..5674ba22 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..36ada96e --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..b7317ac4 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..3f31a6f4 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..487d60d2 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..374aa7d5 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..de0fb1d7 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..686b67cc --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..ff5554dc --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..19e915d4 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..069dd940 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..39425170 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    uint64_t rowid; +    struct TALER_PrivateContractHashP h_contract_terms; +    struct TALER_CoinSpendPublicKeyP coin_pub; +    struct TALER_PaytoHashP h_payto; +    struct TALER_MerchantPublicKeyP merchant_pub; +    struct GNUNET_TIME_Timestamp exec_time; +    struct TALER_Amount amount_with_fee; +    struct TALER_Amount deposit_fee; +    struct TALER_DenominationPublicKey denom_pub; +    char *payto_uri; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", &rowid), +      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", +                                            &h_contract_terms), +      GNUNET_PQ_result_spec_string ("payto_uri", +                                    &payto_uri), +      GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto", +                                            &h_payto), +      TALER_PQ_result_spec_denom_pub ("denom_pub", +                                      &denom_pub), +      GNUNET_PQ_result_spec_auto_from_type ("coin_pub", +                                            &coin_pub), +      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", +                                            &merchant_pub), +      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 +    }; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      ctx->status = 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 00000000..1d66a211 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..28e2e4c5 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..ed9fd95d --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..f176972b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..f1712f53 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..bea0022d --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..8a96d53e --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..fd6c5658 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..22085d8f --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..38524bd6 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..85401938 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..4a886102 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..24cf671d --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..f3e39c53 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..fd82a97a --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..90e0c509 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..0f635cf4 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..52f96e5f --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_EXCHANGEDB_Deposit deposit; +    struct GNUNET_TIME_Timestamp exchange_timestamp; +    struct TALER_DenominationPublicKey denom_pub; +    bool done; +    uint64_t rowid; +    struct GNUNET_PQ_ResultSpec rs[] = { +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", +                                   &deposit.amount_with_fee), +      GNUNET_PQ_result_spec_timestamp ("wallet_timestamp", +                                       &deposit.timestamp), +      GNUNET_PQ_result_spec_timestamp ("exchange_timestamp", +                                       &exchange_timestamp), +      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", +                                            &deposit.merchant_pub), +      TALER_PQ_result_spec_denom_pub ("denom_pub", +                                      &denom_pub), +      GNUNET_PQ_result_spec_auto_from_type ("coin_pub", +                                            &deposit.coin.coin_pub), +      GNUNET_PQ_result_spec_allow_null ( +        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", +                                              &deposit.coin.h_age_commitment), +        &deposit.coin.no_age_commitment), +      GNUNET_PQ_result_spec_auto_from_type ("coin_sig", +                                            &deposit.csig), +      GNUNET_PQ_result_spec_timestamp ("refund_deadline", +                                       &deposit.refund_deadline), +      GNUNET_PQ_result_spec_timestamp ("wire_deadline", +                                       &deposit.wire_deadline), +      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", +                                            &deposit.h_contract_terms), +      GNUNET_PQ_result_spec_auto_from_type ("wire_salt", +                                            &deposit.wire_salt), +      GNUNET_PQ_result_spec_string ("receiver_wire_account", +                                    &deposit.receiver_wire_account), +      GNUNET_PQ_result_spec_bool ("done", +                                  &done), +      GNUNET_PQ_result_spec_uint64 ("deposit_serial_id", +                                    &rowid), +      GNUNET_PQ_result_spec_end +    }; +    enum GNUNET_GenericReturnValue ret; + +    memset (&deposit, +            0, +            sizeof (deposit)); +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      dsc->status = 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 00000000..e29937e0 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..2a260a36 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..f702c241 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..81e03811 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    uint64_t rowid; +    struct TALER_Amount history_fee; +    struct GNUNET_TIME_Timestamp ts; +    struct TALER_ReservePublicKeyP reserve_pub; +    struct TALER_ReserveSignatureP reserve_sig; +    struct GNUNET_PQ_ResultSpec rs[] = { +      TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee", +                                   &history_fee), +      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", +                                            &reserve_pub), +      GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", +                                            &reserve_sig), +      GNUNET_PQ_result_spec_uint64 ("history_request_serial_id", +                                    &rowid), +      GNUNET_PQ_result_spec_timestamp ("request_timestamp", +                                       &ts), +      GNUNET_PQ_result_spec_end +    }; +    enum GNUNET_GenericReturnValue ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      dsc->status = 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 00000000..b16efdce --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..965b27ba --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..2a766713 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..2368f2d3 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_PurseContractPublicKeyP purse_pub; +    struct TALER_ReservePublicKeyP reserve_pub; +    bool no_reserve = true; +    uint64_t rowid; +    struct TALER_Amount val; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("purse_pub", +                                            &purse_pub), +      GNUNET_PQ_result_spec_allow_null ( +        GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", +                                              &reserve_pub), +        &no_reserve), +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", +                                   &val), +      GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id", +                                    &rowid), +      GNUNET_PQ_result_spec_end +    }; +    enum GNUNET_GenericReturnValue ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      dsc->status = 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 00000000..53ab31c8 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..5fe7e014 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_Amount amount_with_fee; +    struct TALER_CoinSpendPublicKeyP coin_pub; +    struct TALER_DenominationPublicKey denom_pub; +    uint64_t rowid; +    struct GNUNET_PQ_ResultSpec rs[] = { +      TALER_PQ_result_spec_denom_pub ("denom_pub", +                                      &denom_pub), +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", +                                   &amount_with_fee), +      GNUNET_PQ_result_spec_auto_from_type ("coin_pub", +                                            &coin_pub), +      GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id", +                                    &rowid), +      GNUNET_PQ_result_spec_end +    }; +    enum GNUNET_GenericReturnValue ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      dsc->status = 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 00000000..203f9a15 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..9047a86f --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    uint64_t rowid; +    struct TALER_ReservePublicKeyP reserve_pub; +    struct TALER_CoinPublicInfo coin; +    struct TALER_CoinSpendSignatureP coin_sig; +    union TALER_DenominationBlindingKeyP coin_blind; +    struct TALER_Amount amount; +    struct TALER_DenominationPublicKey denom_pub; +    struct TALER_BlindedCoinHashP h_blind_ev; +    struct GNUNET_TIME_Timestamp timestamp; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_uint64 ("recoup_uuid", +                                    &rowid), +      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", +                                       ×tamp), +      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", +                                            &reserve_pub), +      GNUNET_PQ_result_spec_auto_from_type ("coin_pub", +                                            &coin.coin_pub), +      TALER_PQ_result_spec_denom_pub ("denom_pub", +                                      &denom_pub), +      GNUNET_PQ_result_spec_auto_from_type ("coin_sig", +                                            &coin_sig), +      GNUNET_PQ_result_spec_auto_from_type ("coin_blind", +                                            &coin_blind), +      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", +                                            &h_blind_ev), +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", +                                            &coin.denom_pub_hash), +      GNUNET_PQ_result_spec_allow_null ( +        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", +                                              &coin.h_age_commitment), +        &coin.no_age_commitment), +      TALER_PQ_result_spec_denom_sig ("denom_sig", +                                      &coin.denom_sig), +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount", +                                   &amount), +      GNUNET_PQ_result_spec_end +    }; +    int ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      psc->status = 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 00000000..9be0b5c3 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..a3f6bc93 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    uint64_t rowid; +    struct TALER_CoinSpendPublicKeyP old_coin_pub; +    struct TALER_CoinPublicInfo coin; +    struct TALER_CoinSpendSignatureP coin_sig; +    union TALER_DenominationBlindingKeyP coin_blind; +    struct TALER_DenominationPublicKey denom_pub; +    struct TALER_DenominationHashP old_denom_pub_hash; +    struct TALER_Amount amount; +    struct TALER_BlindedCoinHashP h_blind_ev; +    struct GNUNET_TIME_Timestamp timestamp; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid", +                                    &rowid), +      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", +                                       ×tamp), +      GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", +                                            &old_coin_pub), +      GNUNET_PQ_result_spec_auto_from_type ("old_denom_pub_hash", +                                            &old_denom_pub_hash), +      GNUNET_PQ_result_spec_auto_from_type ("coin_pub", +                                            &coin.coin_pub), +      GNUNET_PQ_result_spec_auto_from_type ("coin_sig", +                                            &coin_sig), +      GNUNET_PQ_result_spec_auto_from_type ("coin_blind", +                                            &coin_blind), +      TALER_PQ_result_spec_denom_pub ("denom_pub", +                                      &denom_pub), +      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", +                                            &h_blind_ev), +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", +                                            &coin.denom_pub_hash), +      GNUNET_PQ_result_spec_allow_null ( +        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", +                                              &coin.h_age_commitment), +        &coin.no_age_commitment), +      TALER_PQ_result_spec_denom_sig ("denom_sig", +                                      &coin.denom_sig), +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount", +                                   &amount), +      GNUNET_PQ_result_spec_end +    }; +    enum GNUNET_GenericReturnValue ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      psc->status = 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 00000000..0d7b72fc --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..d2b4a7fa --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_DenominationPublicKey denom_pub; +    struct TALER_CoinSpendPublicKeyP coin_pub; +    struct TALER_CoinSpendSignatureP coin_sig; +    struct TALER_AgeCommitmentHash h_age_commitment; +    bool ac_isnull; +    struct TALER_Amount amount_with_fee; +    uint32_t noreveal_index; +    uint64_t rowid; +    struct TALER_RefreshCommitmentP rc; +    struct GNUNET_PQ_ResultSpec rs[] = { +      TALER_PQ_result_spec_denom_pub ("denom_pub", +                                      &denom_pub), +      GNUNET_PQ_result_spec_allow_null ( +        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", +                                              &h_age_commitment), +        &ac_isnull), +      GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", +                                            &coin_pub), +      GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", +                                            &coin_sig), +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", +                                   &amount_with_fee), +      GNUNET_PQ_result_spec_uint32 ("noreveal_index", +                                    &noreveal_index), +      GNUNET_PQ_result_spec_uint64 ("melt_serial_id", +                                    &rowid), +      GNUNET_PQ_result_spec_auto_from_type ("rc", +                                            &rc), +      GNUNET_PQ_result_spec_end +    }; +    enum GNUNET_GenericReturnValue ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      rsc->status = 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 00000000..2d1db275 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..a5f7d3df --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_EXCHANGEDB_Refund refund; +    struct TALER_DenominationPublicKey denom_pub; +    uint64_t rowid; +    bool full_refund; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", +                                            &refund.details.merchant_pub), +      GNUNET_PQ_result_spec_auto_from_type ("merchant_sig", +                                            &refund.details.merchant_sig), +      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", +                                            &refund.details.h_contract_terms), +      GNUNET_PQ_result_spec_uint64 ("rtransaction_id", +                                    &refund.details.rtransaction_id), +      TALER_PQ_result_spec_denom_pub ("denom_pub", +                                      &denom_pub), +      GNUNET_PQ_result_spec_auto_from_type ("coin_pub", +                                            &refund.coin.coin_pub), +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", +                                   &refund.details.refund_amount), +      GNUNET_PQ_result_spec_uint64 ("refund_serial_id", +                                    &rowid), +      GNUNET_PQ_result_spec_end +    }; +    enum GNUNET_GenericReturnValue ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      rsc->status = 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 00000000..b33816a9 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..17885a47 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_Amount amount_with_fee; +    struct GNUNET_PQ_ResultSpec rs[] = { +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", +                                   &amount_with_fee), +      GNUNET_PQ_result_spec_end +    }; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      srctx->status = 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 00000000..e1838b23 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..1a6efc66 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_ReservePublicKeyP reserve_pub; +    struct TALER_Amount credit; +    char *sender_account_details; +    struct GNUNET_TIME_Timestamp execution_date; +    uint64_t rowid; +    uint64_t wire_reference; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", +                                            &reserve_pub), +      GNUNET_PQ_result_spec_uint64 ("wire_reference", +                                    &wire_reference), +      TALER_PQ_RESULT_SPEC_AMOUNT ("credit", +                                   &credit), +      GNUNET_PQ_result_spec_timestamp ("execution_date", +                                       &execution_date), +      GNUNET_PQ_result_spec_string ("sender_account_details", +                                    &sender_account_details), +      GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id", +                                    &rowid), +      GNUNET_PQ_result_spec_end +    }; +    enum GNUNET_GenericReturnValue ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      risc->status = 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 00000000..5f5dd2ec --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..ba73994f --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_ReservePublicKeyP reserve_pub; +    struct TALER_Amount credit; +    char *sender_account_details; +    struct GNUNET_TIME_Timestamp execution_date; +    uint64_t rowid; +    uint64_t wire_reference; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", +                                            &reserve_pub), +      GNUNET_PQ_result_spec_uint64 ("wire_reference", +                                    &wire_reference), +      TALER_PQ_RESULT_SPEC_AMOUNT ("credit", +                                   &credit), +      GNUNET_PQ_result_spec_timestamp ("execution_date", +                                       &execution_date), +      GNUNET_PQ_result_spec_string ("sender_account_details", +                                    &sender_account_details), +      GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id", +                                    &rowid), +      GNUNET_PQ_result_spec_end +    }; +    enum GNUNET_GenericReturnValue ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      risc->status = 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 00000000..81855ede --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..e219f5d4 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    uint64_t rowid; +    struct GNUNET_TIME_Timestamp date; +    struct TALER_WireTransferIdentifierRawP wtid; +    char *payto_uri; +    struct TALER_Amount amount; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_uint64 ("wireout_uuid", +                                    &rowid), +      GNUNET_PQ_result_spec_timestamp ("execution_date", +                                       &date), +      GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", +                                            &wtid), +      GNUNET_PQ_result_spec_string ("payto_uri", +                                    &payto_uri), +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount", +                                   &amount), +      GNUNET_PQ_result_spec_end +    }; +    int ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      wosc->status = 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 00000000..e42cb9b0 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..08883c9a --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    uint64_t rowid; +    struct GNUNET_TIME_Timestamp date; +    struct TALER_WireTransferIdentifierRawP wtid; +    char *payto_uri; +    struct TALER_Amount amount; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_uint64 ("wireout_uuid", +                                    &rowid), +      GNUNET_PQ_result_spec_timestamp ("execution_date", +                                       &date), +      GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", +                                            &wtid), +      GNUNET_PQ_result_spec_string ("payto_uri", +                                    &payto_uri), +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount", +                                   &amount), +      GNUNET_PQ_result_spec_end +    }; +    int ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      wosc->status = 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 00000000..98315cac --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..4718a62a --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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; i<num_results; i++) +  { +    struct TALER_BlindedCoinHashP h_blind_ev; +    struct TALER_DenominationPublicKey denom_pub; +    struct TALER_ReservePublicKeyP reserve_pub; +    struct TALER_ReserveSignatureP reserve_sig; +    struct GNUNET_TIME_Timestamp execution_date; +    struct TALER_Amount amount_with_fee; +    uint64_t rowid; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", +                                            &h_blind_ev), +      TALER_PQ_result_spec_denom_pub ("denom_pub", +                                      &denom_pub), +      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", +                                            &reserve_pub), +      GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", +                                            &reserve_sig), +      GNUNET_PQ_result_spec_timestamp ("execution_date", +                                       &execution_date), +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", +                                   &amount_with_fee), +      GNUNET_PQ_result_spec_uint64 ("reserve_out_serial_id", +                                    &rowid), +      GNUNET_PQ_result_spec_end +    }; +    enum GNUNET_GenericReturnValue ret; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      rosc->status = 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 00000000..adc23fb3 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..86e9d3f0 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..ead3abd2 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..a996104b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..44b76556 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..490ae4c2 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..65ba0343 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..a2d890c5 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..12c0e59b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..abdc1602 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..ed444ef7 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..8bc0147d --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..79950e65 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..1d91301c --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..c444e85b --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..f5f5672c --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..c01d68a4 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..d4541301 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..91e21d27 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..903f22a5 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..2b6050d0 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..fe2236b8 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..cae1523d --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..de8738e4 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 00000000..19db2ca9 --- /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 <http://www.gnu.org/licenses/> + */ +/** + * @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 aa16e7ff..6a2a473c 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 @@ -131,130 +235,6 @@  /** - * 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.   *   * @param[in,out] pg connection to initialize @@ -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,278 +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. - */ -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 -{ -  /** -   * 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; i<num_results; i++) -  { -    struct TALER_EXCHANGEDB_DenominationKeyInformation issue; -    struct TALER_DenominationPublicKey denom_pub; -    struct TALER_DenominationHashP denom_hash; -    struct GNUNET_PQ_ResultSpec rs[] = { -      GNUNET_PQ_result_spec_auto_from_type ("master_sig", -                                            &issue.signature), -      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", -                                            &denom_hash), -      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), -      TALER_PQ_result_spec_denom_pub ("denom_pub", -                                      &denom_pub), -      GNUNET_PQ_result_spec_uint32 ("age_mask", -                                    &issue.age_mask.bits), -      GNUNET_PQ_result_spec_end -    }; - -    if (GNUNET_OK != -        GNUNET_PQ_extract_result (result, -                                  rs, -                                  i)) -    { -      GNUNET_break (0); -      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() + * Closure for #get_refunds_cb().   */ -struct DenomsIteratorContext +struct SelectRefundContext  {    /** -   * Function to call with the results. +   * Function to call on each result.     */ -  TALER_EXCHANGEDB_DenominationsCallback cb; +  TALER_EXCHANGEDB_RefundCoinCallback cb;    /** -   * Closure to pass to @e cb +   * Closure for @a cb.     */    void *cb_cls; @@ -2202,166 +406,36 @@ struct DenomsIteratorContext     * 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; i<num_results; i++) -  { -    struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0}; -    struct TALER_DenominationPublicKey denom_pub = {0}; -    struct TALER_MasterSignatureP master_sig = {0}; -    struct TALER_DenominationHashP h_denom_pub = {0}; -    bool revoked; -    struct GNUNET_PQ_ResultSpec rs[] = { -      GNUNET_PQ_result_spec_auto_from_type ("master_sig", -                                            &master_sig), -      GNUNET_PQ_result_spec_bool ("revoked", -                                  &revoked), -      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), -      TALER_PQ_result_spec_denom_pub ("denom_pub", -                                      &denom_pub), -      GNUNET_PQ_result_spec_uint32 ("age_mask", -                                    &meta.age_mask.bits), -      GNUNET_PQ_result_spec_end -    }; - -    if (GNUNET_OK != -        GNUNET_PQ_extract_result (result, -                                  rs, -                                  i)) -    { -      GNUNET_break (0); -      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 +   * Set to #GNUNET_SYSERR on error.     */ -  void *cb_cls; - +  int status;  };  /** - * Helper function for #postgres_iterate_active_auditors(). - * Calls the callback with each auditor. + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results.   * - * @param cls a `struct SignkeysIteratorContext` - * @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 -auditors_cb_helper (void *cls, -                    PGresult *result, -                    unsigned int num_results) +get_refunds_cb (void *cls, +                PGresult *result, +                unsigned int num_results)  { -  struct AuditorsIteratorContext *dic = cls; +  struct SelectRefundContext *srctx = cls; +  struct PostgresClosure *pg = srctx->pg;    for (unsigned int i = 0; i<num_results; i++)    { -    struct TALER_AuditorPublicKeyP auditor_pub; -    char *auditor_url; -    char *auditor_name; +    struct TALER_Amount amount_with_fee;      struct GNUNET_PQ_ResultSpec rs[] = { -      GNUNET_PQ_result_spec_auto_from_type ("auditor_pub", -                                            &auditor_pub), -      GNUNET_PQ_result_spec_string ("auditor_url", -                                    &auditor_url), -      GNUNET_PQ_result_spec_string ("auditor_name", -                                    &auditor_name), +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", +                                   &amount_with_fee),        GNUNET_PQ_result_spec_end      }; @@ -2371,741 +445,19 @@ auditors_cb_helper (void *cls,                                    i))      {        GNUNET_break (0); +      srctx->status = GNUNET_SYSERR;        return;      } -    dic->cb (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; i<num_results; i++) -  { -    struct TALER_AuditorPublicKeyP auditor_pub; -    struct TALER_DenominationHashP h_denom_pub; -    struct TALER_AuditorSignatureP auditor_sig; -    struct GNUNET_PQ_ResultSpec rs[] = { -      GNUNET_PQ_result_spec_auto_from_type ("auditor_pub", -                                            &auditor_pub), -      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", -                                            &h_denom_pub), -      GNUNET_PQ_result_spec_auto_from_type ("auditor_sig", -                                            &auditor_sig), -      GNUNET_PQ_result_spec_end -    }; -      if (GNUNET_OK != -        GNUNET_PQ_extract_result (result, -                                  rs, -                                  i)) -    { -      GNUNET_break (0); +        srctx->cb (srctx->cb_cls, +                   &amount_with_fee))        return; -    } -    dic->cb (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), @@ -4368,75 +1746,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; i<num_results; i++) -  { -    struct TALER_Amount amount_with_fee; -    struct GNUNET_PQ_ResultSpec rs[] = { -      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", -                                   &amount_with_fee), -      GNUNET_PQ_result_spec_end -    }; - -    if (GNUNET_OK != -        GNUNET_PQ_extract_result (result, -                                  rs, -                                  i)) -    { -      GNUNET_break (0); -      srctx->status = 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.   *   * @param cls closure of plugin @@ -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);  } @@ -7607,1439 +4916,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.   *   * @param cls a configuration instance @@ -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;  }  | 
