diff options
| author | Joseph <Joseph.xu@efrei.net> | 2023-03-29 11:18:20 -0400 | 
|---|---|---|
| committer | Joseph <Joseph.xu@efrei.net> | 2023-03-29 11:18:20 -0400 | 
| commit | 9cce35d27027e1e72e44ac8965ae687d75f1c93d (patch) | |
| tree | a0d2b7b7ffafeca1dcfd04872da022f51ca8391c | |
| parent | 0c2d5bba55d55981f50da3f822a6f45ff5d74cd3 (diff) | |
New sql code for batch ensure coin known
| m--------- | contrib/gana | 0 | ||||
| -rw-r--r-- | src/exchangedb/pg_batch_ensure_coin_known.c | 483 | ||||
| -rw-r--r-- | src/exchangedb/pg_batch_ensure_coin_known.h | 35 | ||||
| -rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 5 | ||||
| -rw-r--r-- | src/include/taler_exchangedb_plugin.h | 36 | 
5 files changed, 557 insertions, 2 deletions
| diff --git a/contrib/gana b/contrib/gana -Subproject 3a616a04f1cd946bf0641b54cd71f1b858174f7 +Subproject 59de2acb7c716c816ed15786b5369e56c325770 diff --git a/src/exchangedb/pg_batch_ensure_coin_known.c b/src/exchangedb/pg_batch_ensure_coin_known.c new file mode 100644 index 00000000..d246e622 --- /dev/null +++ b/src/exchangedb/pg_batch_ensure_coin_known.c @@ -0,0 +1,483 @@ +/* +   This file is part of TALER +   Copyright (C) 2022 Taler Systems SA + +   TALER is free software; you can redistribute it and/or modify it under the +   terms of the GNU General Public License as published by the Free Software +   Foundation; either version 3, or (at your option) any later version. + +   TALER is distributed in the hope that it will be useful, but WITHOUT ANY +   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +   A PARTICULAR PURPOSE.  See the GNU General Public License for 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_batch_ensure_coin_known.c + * @brief Implementation of the batch_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_batch_ensure_coin_known.h" +#include "pg_helper.h" + + + + + + +static enum TALER_EXCHANGEDB_CoinKnownStatus +insert1 (struct PosgresClosure *pg, +         const struct TALER_CoinPublicInfo *coin[1], +         const struct TALER_EXCHANGEDB_CoinInfo *result[1]) +{ +  enum GNUNET_DB_QueryStatus qs; +  bool is_denom_pub_hash_null = false; +  bool is_age_hash_null = false; +  PREPARE (pg, +           "batch1_known_coin", +           "SELECT" +           " existed1 AS existed" +           ",known_coin_id1 AS known_coin_id" +           ",denom_pub_hash1 AS denom_hash" +           ",age_commitment_hash1 AS h_age_commitment" +           " FROM exchange_do_batch1_known_coin" +           "  ($1, $2, $3, $4);" +           ); +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), +    GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), +    GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), +    TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), +    GNUNET_PQ_query_param_end +  }; +  struct GNUNET_PQ_ResultSpec rs[] = { +    GNUNET_PQ_result_spec_bool ("existed", +                                result[0].existed), +    GNUNET_PQ_result_spec_uint64 ("known_coin_id", +                                  result[0].known_coin_id), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", +                                            result[0].denom_hash), +      &is_denom_pub_hash_null), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", +                                            result[0].h_age_commitment), +      &is_age_hash_null), +    GNUNET_PQ_result_spec_end +  }; + +  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, +                                                 "batch1_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; +} + +static enum TALER_EXCHANGEDB_CoinKnownStatus +insert2 (struct PosgresClosure *pg, +         const struct TALER_CoinPublicInfo *coin[2], +         const struct TALER_EXCHANGEDB_CoinInfo *result[2]) +{ +  enum GNUNET_DB_QueryStatus qs; +  bool is_denom_pub_hash_null = false; +  bool is_age_hash_null = false; +  bool is_denom_pub_hash_null2 = false; +  bool is_age_hash_null2 = false; +  PREPARE (pg, +           "batch2_known_coin", +           "SELECT" +           " existed1 AS existed" +           ",known_coin_id1 AS known_coin_id" +           ",denom_pub_hash1 AS denom_hash" +           ",age_commitment_hash1 AS h_age_commitment" +           ",existed2 AS existed2" +           ",known_coin_id2 AS known_coin_id2" +           ",denom_pub_hash2 AS denom_hash2" +           ",age_commitment_hash2 AS h_age_commitment2" +           " FROM exchange_do_batch2_known_coin" +           "  ($1, $2, $3, $4, $5, $6, $7, $8);" +           ); +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), +    GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), +    GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), +    TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + +    GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub), +    GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash), +    GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment), +    TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), +    GNUNET_PQ_query_param_end +  }; +  struct GNUNET_PQ_ResultSpec rs[] = { +    GNUNET_PQ_result_spec_bool ("existed", +                                result[0].existed), +    GNUNET_PQ_result_spec_uint64 ("known_coin_id", +                                  result[0].known_coin_id), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", +                                            result[0].denom_hash), +      &is_denom_pub_hash_null), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", +                                            result[0].h_age_commitment[0]), +      &is_age_hash_null), +    GNUNET_PQ_result_spec_bool ("existed2", +                                result[1].existed), +    GNUNET_PQ_result_spec_uint64 ("known_coin_id2", +                                  result[1].known_coin_id), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2", +                                            &result[1].denom_hash), +      &is_denom_pub_hash_null2), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2", +                                            &result[1].h_age_commitment), +      &is_age_hash_null2), +    GNUNET_PQ_result_spec_end +  }; + +  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, +                                                 "batch2_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[0].hash, +                            &coin[0].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[0], +                            &coin[0].h_age_commitment)) ) +  { +    GNUNET_break (GNUNET_is_zero (h_age_commitment[0])); +    GNUNET_break_op (0); +    return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; +  } +  if ( (! is_denom_pub_hash_null2) && +       (0 != GNUNET_memcmp (&denom_hash[1].hash, +                            &coin[1].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[1], +                            &coin[1].h_age_commitment)) ) +  { +    GNUNET_break (GNUNET_is_zero (h_age_commitment[1])); +    GNUNET_break_op (0); +    return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; +  } +  return TALER_EXCHANGEDB_CKS_PRESENT; +} + +static enum TALER_EXCHANGEDB_CoinKnownStatus +insert4 (struct PosgresClosure *pg, +         const struct TALER_CoinPublicInfo *coin[4], +         const struct TALER_EXCHANGEDB_CoinInfo *result[4]) +{ +  enum GNUNET_DB_QueryStatus qs; +  bool is_denom_pub_hash_null = false; +  bool is_age_hash_null = false; +  bool is_denom_pub_hash_null2 = false; +  bool is_age_hash_null2 = false; +  bool is_denom_pub_hash_null3 = false; +  bool is_age_hash_null3 = false; +  bool is_denom_pub_hash_null4 = false; +  bool is_age_hash_null4 = false; +  PREPARE (pg, +           "batch4_known_coin", +           "SELECT" +           " existed1 AS existed" +           ",known_coin_id1 AS known_coin_id" +           ",denom_pub_hash1 AS denom_hash" +           ",age_commitment_hash1 AS h_age_commitment" +           ",existed2 AS existed2" +           ",known_coin_id2 AS known_coin_id2" +           ",denom_pub_hash2 AS denom_hash2" +           ",age_commitment_hash2 AS h_age_commitment2" +           ",existed3 AS existed3" +           ",known_coin_id3 AS known_coin_id3" +           ",denom_pub_hash3 AS denom_hash3" +           ",age_commitment_hash3 AS h_age_commitment3" +           ",existed4 AS existed4" +           ",known_coin_id4 AS known_coin_id4" +           ",denom_pub_hash4 AS denom_hash4" +           ",age_commitment_hash4 AS h_age_commitment4" +           " FROM exchange_do_batch2_known_coin" +           "  ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16);" +           ); +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), +    GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), +    GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), +    TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + +    GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub), +    GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash), +    GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment), +    TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + +    GNUNET_PQ_query_param_auto_from_type (&coin[2].coin_pub), +    GNUNET_PQ_query_param_auto_from_type (&coin[2].denom_pub_hash), +    GNUNET_PQ_query_param_auto_from_type (&coin[2].h_age_commitment), +    TALER_PQ_query_param_denom_sig (&coin[2].denom_sig), + +    GNUNET_PQ_query_param_auto_from_type (&coin[3].coin_pub), +    GNUNET_PQ_query_param_auto_from_type (&coin[3].denom_pub_hash), +    GNUNET_PQ_query_param_auto_from_type (&coin[3].h_age_commitment), +    TALER_PQ_query_param_denom_sig (&coin[3].denom_sig), +    GNUNET_PQ_query_param_end +  }; +  struct GNUNET_PQ_ResultSpec rs[] = { +    GNUNET_PQ_result_spec_bool ("existed", +                                result[0].existed), +    GNUNET_PQ_result_spec_uint64 ("known_coin_id", +                                  result[0].known_coin_id), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", +                                            result[0].denom_hash), +      &is_denom_pub_hash_null), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", +                                            result[0].h_age_commitment), +      &is_age_hash_null), +    GNUNET_PQ_result_spec_bool ("existed2", +                                result[1].existed), +    GNUNET_PQ_result_spec_uint64 ("known_coin_id2", +                                  result[1].known_coin_id), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2", +                                            result[1].denom_hash), +      &is_denom_pub_hash_null2), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2", +                                            result[1].h_age_commitment), +      &is_age_hash_null2), +    GNUNET_PQ_result_spec_bool ("existed3", +                                result[2].existed), +    GNUNET_PQ_result_spec_uint64 ("known_coin_id3", +                                  result[2].known_coin_id), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash3", +                                            result[2].denom_hash), +      &is_denom_pub_hash_null3), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash3", +                                            result[2].h_age_commitment), +      &is_age_hash_null3), +    GNUNET_PQ_result_spec_bool ("existed4", +                                result[3].existed), +    GNUNET_PQ_result_spec_uint64 ("known_coin_id4", +                                  result[3].known_coin_id), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash4", +                                            result[3].denom_hash), +      &is_denom_pub_hash_null4), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash4", +                                            result[3].h_age_commitment), +      &is_age_hash_null4), +    GNUNET_PQ_result_spec_end +  }; + +  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, +                                                 "batch4_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 (result[0].denom_hash.hash, +                            &coin[0].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[0], +                            &coin[0].h_age_commitment)) ) +  { +    GNUNET_break (GNUNET_is_zero (h_age_commitment[0])); +    GNUNET_break_op (0); +    return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; +  } + +  if ( (! is_denom_pub_hash_null2) && +       (0 != GNUNET_memcmp (&denom_hash[1].hash, +                            &coin[1].denom_pub_hash.hash)) ) +  { +    GNUNET_break_op (0); +    return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; +  } +  if ( (! is_age_hash_null2) && +       (0 != GNUNET_memcmp (h_age_commitment[1], +                            &coin[1].h_age_commitment)) ) +  { +    GNUNET_break (GNUNET_is_zero (h_age_commitment[1])); +    GNUNET_break_op (0); +    return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; +  } + +  if ( (! is_denom_pub_hash_null3) && +       (0 != GNUNET_memcmp (&denom_hash[2].hash, +                            &coin[2].denom_pub_hash.hash)) ) +  { +    GNUNET_break_op (0); +    return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; +  } +  if ( (! is_age_hash_null3) && +       (0 != GNUNET_memcmp (h_age_commitment[2], +                            &coin[2].h_age_commitment)) ) +  { +    GNUNET_break (GNUNET_is_zero (h_age_commitment[2])); +    GNUNET_break_op (0); +    return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; +  } + +  if ( (! is_denom_pub_hash_null4) && +       (0 != GNUNET_memcmp (&denom_hash[3].hash, +                            &coin[3].denom_pub_hash.hash)) ) +  { +    GNUNET_break_op (0); +    return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; +  } +  if ( (! is_age_hash_null4) && +       (0 != GNUNET_memcmp (h_age_commitment[3], +                            &coin[3].h_age_commitment)) ) +  { +    GNUNET_break (GNUNET_is_zero (h_age_commitment[3])); +    GNUNET_break_op (0); +    return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; +  } + +  return TALER_EXCHANGEDB_CKS_PRESENT; +} + + + +enum TALER_EXCHANGEDB_CoinKnownStatus +TEH_PG_batch_ensure_coin_known (void *cls, +                                const struct +                                TALER_CoinPublicInfo *coin, +                                const struct +                                TALER_EXCHANGEDB_CoinInfo *result, +                                unsigned int coin_length, +                                unsigned int batch_size) +{ +  struct PostgresClosure *pg = cls; +  enum TALER_EXCHANGEDB_CoinKnownStatus qs1; +  enum TALER_EXCHANGEDB_CoinKnownStatus qs2; +  enum TALER_EXCHANGEDB_CoinKnownStatus qs4; +  unsigned int i = 0; + +  while (i < coin_length) +  { +    unsigned int bs = GNUNET_MIN (batch_size, +                                  coin_length - i); +    bs = 1; +    if (bs >= 4) +    { +      qs4 = insert4 (pg, +                     &coin[i], +                     &result[i] +                     ); +      i += 4; +      continue; +    } +    switch (bs) +    { +    case 3: +    case 2: +      qs2 = insert2 (pg, +                     &coin[i], +                     &result[i] +                     ); +      i += 2; +      break; +    case 1: +      qs1 = insert1 (pg, +                     &coin[i], +                     &result[i] +                     ); +      i += 1; +      break; +    case 0: +      GNUNET_assert (0); +      break; +    } +  } /* end while */ +  return TALER_EXCHANGEDB_CKS_PRESENT; +} diff --git a/src/exchangedb/pg_batch_ensure_coin_known.h b/src/exchangedb/pg_batch_ensure_coin_known.h new file mode 100644 index 00000000..ce2b2f4c --- /dev/null +++ b/src/exchangedb/pg_batch_ensure_coin_known.h @@ -0,0 +1,35 @@ +/* +   This file is part of TALER +   Copyright (C) 2022 Taler Systems SA + +   TALER is free software; you can redistribute it and/or modify it under the +   terms of the GNU General Public License as published by the Free Software +   Foundation; either version 3, or (at your option) any later version. + +   TALER is distributed in the hope that it will be useful, but WITHOUT ANY +   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +   A PARTICULAR PURPOSE.  See the GNU General Public License for 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_batch_ensure_coin_known.h + * @brief implementation of the batch_ensure_coin_known function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_BATCH_ENSURE_COIN_KNOWN_H +#define PG_BATCH_ENSURE_COIN_KNOWN_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +enum TALER_EXCHANGEDB_CoinKnownStatus +TEH_PG_batch_ensure_coin_known (void *cls, +                                const struct +                                TALER_CoinPublicInfo *coin, +                                const struct +                                TALER_EXCHANGEDB_CoinInfo *result, +                                unsigned int coin_length, +                                unsigned int batch_size); +#endif diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 2f331818..7e3aa2b1 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -216,7 +216,7 @@  #include "pg_select_aml_process.h"  #include "pg_select_aml_history.h"  #include "pg_insert_aml_decision.h" - +#include "pg_batch_ensure_coin_known.h"  /**   * Set to 1 to enable Postgres auto_explain module. This will @@ -774,6 +774,9 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)    plugin->insert_aml_decision      = &TEH_PG_insert_aml_decision; +  plugin->batch_ensure_coin_known +    = &TEH_PG_batch_ensure_coin_known; +    return plugin;  } diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 962bccaa..cee8fb88 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -29,6 +29,19 @@  #include "taler_extensions_policy.h" + + +struct TALER_EXCHANGEDB_CoinInfo +{ +  uint64_t *known_coin_id; +  struct TALER_DenominationHashP *denom_hash; +  struct TALER_AgeCommitmentHash *h_age_commitment; +  bool *existed; +}; + + + +  /**   * Information about a denomination key.   */ @@ -887,6 +900,21 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData  }; + + + + + + + + + + + + + + +  /**   * Signature of a function called with information about the exchange's   * denomination keys. @@ -4027,7 +4055,13 @@ struct TALER_EXCHANGEDB_Plugin                         struct TALER_DenominationHashP *denom_pub_hash,                         struct TALER_AgeCommitmentHash *age_hash); - +  enum TALER_EXCHANGEDB_CoinKnownStatus +  (*batch_ensure_coin_known)(void *cls, +                             const struct TALER_CoinPublicInfo *coin, +                             const struct +                             TALER_EXCHANGEDB_CoinInfo *result, +                             unsigned int coin_length, +                             unsigned int batch_size);    /**     * Retrieve information about the given @a coin from the database.     * | 
