diff options
Diffstat (limited to 'src/exchangedb')
| -rw-r--r-- | src/exchangedb/Makefile.am | 55 | ||||
| -rw-r--r-- | src/exchangedb/pg_get_link_data.c | 11 | ||||
| -rw-r--r-- | src/exchangedb/pg_select_refunds_by_coin.c | 27 | ||||
| -rw-r--r-- | src/exchangedb/test_exchangedb_populate_link_data.c | 548 | ||||
| -rw-r--r-- | src/exchangedb/test_exchangedb_populate_ready_deposit.c | 546 | ||||
| -rw-r--r-- | src/exchangedb/test_exchangedb_populate_table.c | 542 | 
6 files changed, 1416 insertions, 313 deletions
| diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am index ddb899a0..40607af6 100644 --- a/src/exchangedb/Makefile.am +++ b/src/exchangedb/Makefile.am @@ -296,7 +296,9 @@ check_PROGRAMS = \    perf-exchangedb-reserves-in-insert-postgres\    test-exchangedb-by-j-postgres\    test-exchangedb-batch-reserves-in-insert-postgres\ -  test-exchangedb-populate-table-postgres +  test-exchangedb-populate-table-postgres\ +  test-exchangedb-populate-link-data-postgres\ +  test-exchangedb-populate-ready-deposit-postgres  AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;  TESTS = \ @@ -304,7 +306,9 @@ TESTS = \    test-exchangedb-by-j-postgres\    perf-exchangedb-reserves-in-insert-postgres\    test-exchangedb-batch-reserves-in-insert-postgres\ -  test-exchangedb-populate-table-postgres +  test-exchangedb-populate-table-postgres\ +  test-exchangedb-populate-link-data-postgres\ +  test-exchangedb-populate-ready-deposit-postgres  test_exchangedb_postgres_SOURCES = \    test_exchangedb.c  test_exchangedb_postgres_LDADD = \ @@ -375,6 +379,53 @@ test_exchangedb_populate_table_postgres_LDADD = \    -ljansson \    -lgnunetjson \    -lgnunetutil \ +  -lm \ +  $(XLIB) + +bench_db_postgres_SOURCES = \ +  bench_db.c +bench_db_postgres_LDADD = \ +  libtalerexchangedb.la \ +  $(top_builddir)/src/util/libtalerutil.la \ +  $(top_builddir)/src/pq/libtalerpq.la \ +  -lgnunetpq \ +  -lgnunetutil \ +  $(XLIB) + +test_exchangedb_populate_link_data_postgres_SOURCES = \ +  test_exchangedb_populate_link_data.c +test_exchangedb_populate_link_data_postgres_LDADD = \ +  libtalerexchangedb.la \ +  $(top_builddir)/src/json/libtalerjson.la \ +  $(top_builddir)/src/util/libtalerutil.la \ +  $(top_builddir)/src/pq/libtalerpq.la \ +  -ljansson \ +  -lgnunetjson \ +  -lgnunetutil \ +  -lm \ +  $(XLIB) + +bench_db_postgres_SOURCES = \ +  bench_db.c +bench_db_postgres_LDADD = \ +  libtalerexchangedb.la \ +  $(top_builddir)/src/util/libtalerutil.la \ +  $(top_builddir)/src/pq/libtalerpq.la \ +  -lgnunetpq \ +  -lgnunetutil \ +  $(XLIB) + +test_exchangedb_populate_ready_deposit_postgres_SOURCES = \ +  test_exchangedb_populate_ready_deposit.c +test_exchangedb_populate_ready_deposit_postgres_LDADD = \ +  libtalerexchangedb.la \ +  $(top_builddir)/src/json/libtalerjson.la \ +  $(top_builddir)/src/util/libtalerutil.la \ +  $(top_builddir)/src/pq/libtalerpq.la \ +  -ljansson \ +  -lgnunetjson \ +  -lgnunetutil \ +  -lm \    $(XLIB)  EXTRA_test_exchangedb_postgres_DEPENDENCIES = \ diff --git a/src/exchangedb/pg_get_link_data.c b/src/exchangedb/pg_get_link_data.c index f15bf35a..9bc4c9b0 100644 --- a/src/exchangedb/pg_get_link_data.c +++ b/src/exchangedb/pg_get_link_data.c @@ -208,7 +208,7 @@ TEH_PG_get_link_data (void *cls,               "WITH rc AS MATERIALIZED ("               "SELECT"               "* FROM refresh_commitments" -             "WHERE old_coin_pub=$1" +             " WHERE old_coin_pub=$1"               ")"               "SELECT "               " tp.transfer_pub" @@ -219,11 +219,10 @@ TEH_PG_get_link_data (void *cls,               ",rrc.freshcoin_index"               ",rrc.coin_ev"               " FROM refresh_revealed_coins rrc" -             "       USING (melt_serial_id)" -             "     JOIN refresh_transfer_keys tp" -             "       USING (melt_serial_id)" -             "     JOIN denominations denoms" -             "       USING (denominations_serial)" +             "  JOIN refresh_transfer_keys tp" +             "   USING (melt_serial_id)" +             "  JOIN denominations denoms" +             "   USING (denominations_serial)"               " ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");    } diff --git a/src/exchangedb/pg_select_refunds_by_coin.c b/src/exchangedb/pg_select_refunds_by_coin.c index 84b63a71..b9db2b70 100644 --- a/src/exchangedb/pg_select_refunds_by_coin.c +++ b/src/exchangedb/pg_select_refunds_by_coin.c @@ -140,16 +140,25 @@ TEH_PG_select_refunds_by_coin (               "get_refunds_by_coin_and_contract",               "WITH rc AS MATERIALIZED("               "SELECT" -             " * FROM refunds ref" -             "WHERE ref.coin_pub=$1" -                "AND dep.merchant_pub=$2" -                "AND dep.h_contract_terms=$3" -             ")" +             " amount_with_fee_val" +             ",amount_with_fee_frac" +             ",coin_pub" +             ",deposit_serial_id" +             " FROM refunds ref" +             " WHERE ref.coin_pub=$1)"               "SELECT" -             "   ref.amount_with_fee_val" -             "  ,ref.amount_with_fee_frac" -             "FROM deposits dep" -             "JOIN rc" +             "   rc.amount_with_fee_val" +             "  ,rc.amount_with_fee_frac" +             " FROM " +             "(SELECT" +             "   rc.amount_with_fee_val" +             "  ,rc.amount_with_fee_frac" +             "  FROM deposits dep" +             "  WHERE" +             "  dep.coin_pub = $1" // optional... +             "  AND dep.merchant_pub = $2" +             "  AND dep.h_contract_terms = $3) dep" +             " JOIN rc"               "   USING (coin_pub,deposit_serial_id)");    }    qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, diff --git a/src/exchangedb/test_exchangedb_populate_link_data.c b/src/exchangedb/test_exchangedb_populate_link_data.c new file mode 100644 index 00000000..ff294874 --- /dev/null +++ b/src/exchangedb/test_exchangedb_populate_link_data.c @@ -0,0 +1,548 @@ +/* +  This file is part of TALER +  Copyright (C) 2014-2022 Taler Systems SA + +  TALER is free software; you can redistribute it and/or modify it under the +  terms of the GNU General Public License as published by the Free Software +  Foundation; either version 3, or (at your option) any later version. + +  TALER is distributed in the hope that it will be useful, but WITHOUT ANY +  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +  A PARTICULAR PURPOSE.  See the GNU General Public License for 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/test_exchangedb_populate_link_data.c + * @brief test cases for DB interaction functions + * @author Joseph Xu + */ +#include "platform.h" +#include "taler_exchangedb_lib.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +#include "math.h" + + +#define NUM_ROWS 1000 + +/** + * Global result from the testcase. + */ +static int result; + +/** + * Report line of error if @a cond is true, and jump to label "drop". + */ +#define FAILIF(cond)                            \ +  do {                                          \ +      if (! (cond)) {break;}                    \ +    GNUNET_break (0);                           \ +    goto drop;                                  \ +  } while (0) + + +/** + * Initializes @a ptr with random data. + */ +#define RND_BLK(ptr)                                                    \ +  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr)) + +/** + * Initializes @a ptr with zeros. + */ +#define ZR_BLK(ptr) \ +  memset (ptr, 0, sizeof (*ptr)) + + +/** + * Currency we use.  Must match test-exchange-db-*.conf. + */ +#define CURRENCY "EUR" + +/** + * How big do we make the RSA keys? + */ +#define RSA_KEY_SIZE 1024 +static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins; + +static struct TALER_TransferPrivateKeyP tprivs[TALER_CNC_KAPPA]; + +static struct TALER_TransferPublicKeyP tpub; +#define ROUNDS 10 +#define MELT_NEW_COINS 5 +#define MELT_NOREVEAL_INDEX 1 +/** + * Database plugin under test. + */ +static struct TALER_EXCHANGEDB_Plugin *plugin; +static struct TALER_DenomFeeSet fees; +/** + * Denomination keys used for fresh coins in melt test. + */ +static struct DenomKeyPair **new_dkp; + +struct DenomKeyPair +{ +  struct TALER_DenominationPrivateKey priv; +  struct TALER_DenominationPublicKey pub; +}; + + +/** + * Destroy a denomination key pair.  The key is not necessarily removed from the DB. + * + * @param dkp the key pair to destroy + */ +static void +destroy_denom_key_pair (struct DenomKeyPair *dkp) +{ +  TALER_denom_pub_free (&dkp->pub); +  TALER_denom_priv_free (&dkp->priv); +  GNUNET_free (dkp); +} + + +/** + * Create a denomination key pair by registering the denomination in the DB. + * + * @param size the size of the denomination key + * @param now time to use for key generation, legal expiration will be 3h later. + * @param fees fees to use + * @return the denominaiton key pair; NULL upon error + */ +static struct DenomKeyPair * +create_denom_key_pair (unsigned int size, +                       struct GNUNET_TIME_Timestamp now, +                       const struct TALER_Amount *value, +                       const struct TALER_DenomFeeSet *fees) +{ +  struct DenomKeyPair *dkp; +  struct TALER_EXCHANGEDB_DenominationKey dki; +  struct TALER_EXCHANGEDB_DenominationKeyInformation issue2; + +  dkp = GNUNET_new (struct DenomKeyPair); +  GNUNET_assert (GNUNET_OK == +                 TALER_denom_priv_create (&dkp->priv, +                                          &dkp->pub, +                                          TALER_DENOMINATION_RSA, +                                          size)); +  memset (&dki, +          0, +          sizeof (struct TALER_EXCHANGEDB_DenominationKey)); +  dki.denom_pub = dkp->pub; +  dki.issue.start = now; +  dki.issue.expire_withdraw +    = GNUNET_TIME_absolute_to_timestamp ( +        GNUNET_TIME_absolute_add ( +          now.abs_time, +          GNUNET_TIME_UNIT_HOURS)); +  dki.issue.expire_deposit +    = GNUNET_TIME_absolute_to_timestamp ( +        GNUNET_TIME_absolute_add ( +          now.abs_time, +          GNUNET_TIME_relative_multiply ( +            GNUNET_TIME_UNIT_HOURS, 2))); +  dki.issue.expire_legal +    = GNUNET_TIME_absolute_to_timestamp ( +        GNUNET_TIME_absolute_add ( +          now.abs_time, +          GNUNET_TIME_relative_multiply ( +            GNUNET_TIME_UNIT_HOURS, 3))); +  dki.issue.value = *value; +  dki.issue.fees = *fees; +  TALER_denom_pub_hash (&dkp->pub, +                        &dki.issue.denom_hash); +  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +      plugin->insert_denomination_info (plugin->cls, +                                        &dki.denom_pub, +                                        &dki.issue)) +  { +    GNUNET_break (0); +    destroy_denom_key_pair (dkp); +    return NULL; +  } +  memset (&issue2, 0, sizeof (issue2)); +  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +      plugin->get_denomination_info (plugin->cls, +                                     &dki.issue.denom_hash, +                                     &issue2)) +  { +    GNUNET_break (0); +    destroy_denom_key_pair (dkp); +    return NULL; +  } +  if (0 != GNUNET_memcmp (&dki.issue, +                          &issue2)) +  { +    GNUNET_break (0); +    destroy_denom_key_pair (dkp); +    return NULL; +  } +  return dkp; +} + +/** + * Function called with the session hashes and transfer secret + * information for a given coin. + * + * @param cls closure + * @param transfer_pub public transfer key for the session + * @param ldl link data for @a transfer_pub + */ +static void +handle_link_data_cb (void *cls, +                     const struct TALER_TransferPublicKeyP *transfer_pub, +                     const struct TALER_EXCHANGEDB_LinkList *ldl) +{ +  (void) cls; +  (void) transfer_pub; +  for (const struct TALER_EXCHANGEDB_LinkList *ldlp = ldl; +       NULL != ldlp; +       ldlp = ldlp->next) +  { +    bool found; + +    found = false; +    for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) +    { +      if ( (0 == +            TALER_denom_pub_cmp (&ldlp->denom_pub, +                                 &new_dkp[cnt]->pub)) && +           (0 == +            TALER_blinded_denom_sig_cmp (&ldlp->ev_sig, +                                         &revealed_coins[cnt].coin_sig)) ) +      { +        found = true; +        break; +      } +    } +    GNUNET_assert (GNUNET_NO != found); +  } +} + + + +/** + * Main function that will be run by the scheduler. + * + * @param cls closure with config + */ + +static void +run (void *cls) +{ +  struct TALER_EXCHANGEDB_Refresh *refresh; +  uint64_t melt_serial_id; +  struct GNUNET_CONFIGURATION_Handle *cfg = cls; +  const uint32_t num_partitions = 10; +  struct DenomKeyPair *dkp = NULL; +  struct TALER_EXCHANGEDB_Deposit *depos=NULL; +  struct TALER_Amount value; +  struct TALER_DenominationPublicKey *new_denom_pubs = NULL; +  struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO; +  unsigned long long sqrs=0; +  struct TALER_EXCHANGEDB_Refund *ref=NULL; +  unsigned int *perm; +  unsigned long long duration_sq; +  struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin; +  struct TALER_ExchangeWithdrawValues alg_values = { +    .cipher = TALER_DENOMINATION_RSA +    }; + +  ref = GNUNET_new_array (ROUNDS +1, +                          struct TALER_EXCHANGEDB_Refund); +  depos = GNUNET_new_array (ROUNDS +1, +                            struct TALER_EXCHANGEDB_Deposit); +  refresh = GNUNET_new_array (ROUNDS +1, +                            struct TALER_EXCHANGEDB_Refresh); + +  if (NULL == +      (plugin = TALER_EXCHANGEDB_plugin_load (cfg))) +  { +    GNUNET_break (0); +    result = 77; +    return; +  } +  (void) plugin->drop_tables (plugin->cls); +  if (GNUNET_OK != +      plugin->create_tables (plugin->cls, +                             true, +                             num_partitions)) +  { +    GNUNET_break (0); +    result = 77; +    goto cleanup; +  } +  if (GNUNET_OK != +      plugin->preflight (plugin->cls)) +  { +    GNUNET_break (0); +    goto cleanup; +  } + +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":1.000010", +                                         &value)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000010", +                                         &fees.withdraw)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000010", +                                         &fees.deposit)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000010", +                                         &fees.refresh)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000010", +                                         &fees.refund)); +  //DENOMINATION +  { +    //PAIR KEY LIST +    new_dkp = GNUNET_new_array (MELT_NEW_COINS, +                              struct DenomKeyPair *); +    //PUBLIC KEY LIST +    new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS, +                                       struct TALER_DenominationPublicKey); +    //REFRESH REVEAL COIN LIST +    revealed_coins +      = GNUNET_new_array (MELT_NEW_COINS, +                          struct TALER_EXCHANGEDB_RefreshRevealedCoin); +    for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) +      { +        struct GNUNET_TIME_Timestamp now; +        struct TALER_BlindedRsaPlanchet *rp; +        struct TALER_BlindedPlanchet *bp; + +        now = GNUNET_TIME_timestamp_get (); +        //5 KEY PAIR +        new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE, +                                              now, +                                              &value, +                                              &fees); +        GNUNET_assert (NULL != new_dkp[cnt]); +        new_denom_pubs[cnt] = new_dkp[cnt]->pub; +        ccoin = &revealed_coins[cnt]; +        bp = &ccoin->blinded_planchet; +        bp->cipher = TALER_DENOMINATION_RSA; +        rp = &bp->details.rsa_blinded_planchet; +        rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 ( +                                                                      GNUNET_CRYPTO_QUALITY_WEAK, +                                                                      (RSA_KEY_SIZE / 8) - 1); +        rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size); +        GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, +                                    rp->blinded_msg, +                                    rp->blinded_msg_size); +        TALER_denom_pub_hash (&new_dkp[cnt]->pub, +                              &ccoin->h_denom_pub); +        ccoin->exchange_vals = alg_values; +        TALER_coin_ev_hash (bp, +                            &ccoin->h_denom_pub, +                            &ccoin->coin_envelope_hash); +        GNUNET_assert (GNUNET_OK == +                     TALER_denom_sign_blinded (&ccoin->coin_sig, +                                               &new_dkp[cnt]->priv, +                                               true, +                                               bp)); +      } +  } +  perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE, +                                       NUM_ROWS); +  //BEGIN +  FAILIF (GNUNET_OK != +          plugin->start (plugin->cls, +                         "Transaction")); +  for (unsigned int j = 0; j < NUM_ROWS; j++) +    { +      union TALER_DenominationBlindingKeyP bks; +      struct TALER_CoinSpendPublicKeyP coin_pub; +      struct TALER_CoinPubHashP c_hash; +      unsigned int k = (unsigned int)rand()%5; +      unsigned int i = perm[j]; +      if (i >= ROUNDS) +        i = ROUNDS; /* throw-away slot, do not keep around */ +      RND_BLK (&coin_pub); +      RND_BLK (&c_hash); + +      RND_BLK (&depos[i].coin.coin_pub); +      TALER_denom_pub_hash (&new_dkp[k]->pub, +                            &depos[i].coin.denom_pub_hash); +      GNUNET_assert (GNUNET_OK == +                     TALER_denom_sig_unblind (&depos[i].coin.denom_sig, +                                              &ccoin->coin_sig, +                                              &bks, +                                              &c_hash, +                                              &alg_values, +                                              &new_dkp[k]->pub)); +      { +        /* ENSURE_COIN_KNOWN */ +        uint64_t known_coin_id; +        struct TALER_DenominationHashP dph; +        struct TALER_AgeCommitmentHash agh; +        bool zombie_required = false; +        bool balance_ok; +        FAILIF (TALER_EXCHANGEDB_CKS_ADDED != +                plugin->ensure_coin_known (plugin->cls, +                                           &depos[i].coin, +                                           &known_coin_id, +                                           &dph, +                                           &agh)); +        /**** INSERT REFRESH COMMITMENTS ****/ +        refresh[i].coin = depos[i].coin; +        RND_BLK (&refresh[i].coin_sig); +        RND_BLK (&refresh[i].rc); +        refresh[i].amount_with_fee = value; +        refresh[i].noreveal_index = MELT_NOREVEAL_INDEX; +        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +                plugin->do_melt (plugin->cls, +                                 NULL, +                                 &refresh[i], +                                 known_coin_id, +                                 &zombie_required, +                                 &balance_ok)); +        FAILIF (! balance_ok); +        FAILIF (zombie_required); +      } +      /**** INSERT REFRESH_REVEAL + TRANSFER_KEYS *****/ +        RND_BLK (&tprivs); +        RND_BLK (&tpub); +        RND_BLK(&melt_serial_id); +        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +                plugin->insert_refresh_reveal (plugin->cls, +                                               melt_serial_id, +                                               MELT_NEW_COINS, +                                               revealed_coins, +                                               TALER_CNC_KAPPA - 1, +                                               tprivs, +                                               &tpub)); +        if (ROUNDS == i) +          TALER_denom_sig_free (&depos[i].coin.denom_sig); +    } +  /* End of benchmark setup */ +  GNUNET_free(perm); +  // commit +  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != +          plugin->commit (plugin->cls)); +  /**** CALL GET LINK DATA ****/ +  for (unsigned int r=0; r< ROUNDS; r++) +  { +    struct GNUNET_TIME_Absolute time; +    struct GNUNET_TIME_Relative duration; +    enum GNUNET_DB_QueryStatus qs; +    time = GNUNET_TIME_absolute_get(); +    qs = plugin->get_link_data (plugin->cls, +                                &refresh[r].coin.coin_pub, +                                &handle_link_data_cb, +                                NULL); +    FAILIF (qs < 0); + +    duration = GNUNET_TIME_absolute_get_duration (time); +    times = GNUNET_TIME_relative_add (times, +                                      duration); +    duration_sq = duration.rel_value_us * duration.rel_value_us; +    GNUNET_assert (duration_sq / duration.rel_value_us == duration.rel_value_us); +    GNUNET_assert (sqrs + duration_sq >= sqrs); +    sqrs += duration_sq; +  } + +  /* evaluation of performance */ +  { +    struct GNUNET_TIME_Relative avg; +    double avg_dbl; +    double variance; + +    avg = GNUNET_TIME_relative_divide (times, +                                       ROUNDS); +    avg_dbl = avg.rel_value_us; +    variance = sqrs - (avg_dbl * avg_dbl * ROUNDS); +    fprintf(stdout, +            "%8llu ± %6.0f\n", +            (unsigned long long) avg.rel_value_us, +            sqrt (variance / (ROUNDS-1))); +  } +  result = 0; +drop: +  GNUNET_break (GNUNET_OK == +  plugin->drop_tables (plugin->cls)); +cleanup: +  if (NULL != dkp) +    destroy_denom_key_pair (dkp); +  if (NULL != revealed_coins) +  { +    for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) +    { +      TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig); +      TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet); +    } +    GNUNET_free (revealed_coins); +    revealed_coins = NULL; +  } +  GNUNET_free (new_denom_pubs); +  for (unsigned int cnt = 0; +       (NULL != new_dkp) && (cnt < MELT_NEW_COINS) && (NULL != new_dkp[cnt]); +       cnt++) +    destroy_denom_key_pair (new_dkp[cnt]); +  GNUNET_free (new_dkp); +  for (unsigned int i=0; i< ROUNDS; i++) +    { +      TALER_denom_sig_free (&depos[i].coin.denom_sig); +    } +  GNUNET_free(depos); +  GNUNET_free(ref); +  GNUNET_free(refresh); +  dkp = NULL; +  TALER_EXCHANGEDB_plugin_unload (plugin); +  plugin = NULL; +} + + +int +main (int argc, +      char *const argv[]) +{ +  const char *plugin_name; +  char *config_filename; +  char *testname; +  struct GNUNET_CONFIGURATION_Handle *cfg; + +  (void) argc; +  result = -1; +  if (NULL == (plugin_name = strrchr (argv[0], (int) '-'))) +  { +    GNUNET_break (0); +    return -1; +  } +  GNUNET_log_setup (argv[0], +                    "WARNING", +                    NULL); +  plugin_name++; +  (void) GNUNET_asprintf (&testname, +                          "test-exchange-db-%s", +                          plugin_name); +  (void) GNUNET_asprintf (&config_filename, +                          "%s.conf", +                          testname); +  fprintf (stdout, +           "Using config: %s\n", +           config_filename); +  cfg = GNUNET_CONFIGURATION_create (); +  if (GNUNET_OK != +      GNUNET_CONFIGURATION_parse (cfg, +                                  config_filename)) +  { +    GNUNET_break (0); +    GNUNET_free (config_filename); +    GNUNET_free (testname); +    return 2; +  } +  GNUNET_SCHEDULER_run (&run, +                        cfg); +  GNUNET_CONFIGURATION_destroy (cfg); +  GNUNET_free (config_filename); +  GNUNET_free (testname); +  return result; +} + + +/* end of test_exchangedb_by_j.c */ diff --git a/src/exchangedb/test_exchangedb_populate_ready_deposit.c b/src/exchangedb/test_exchangedb_populate_ready_deposit.c new file mode 100644 index 00000000..49b1bf5d --- /dev/null +++ b/src/exchangedb/test_exchangedb_populate_ready_deposit.c @@ -0,0 +1,546 @@ +/* +  This file is part of TALER +  Copyright (C) 2014-2022 Taler Systems SA + +  TALER is free software; you can redistribute it and/or modify it under the +  terms of the GNU General Public License as published by the Free Software +  Foundation; either version 3, or (at your option) any later version. + +  TALER is distributed in the hope that it will be useful, but WITHOUT ANY +  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +  A PARTICULAR PURPOSE.  See the GNU General Public License for 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/test_exchangedb_populate_ready_deposit.c + * @brief test cases for DB interaction functions + * @author Joseph Xu + */ +#include "platform.h" +#include "taler_exchangedb_lib.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +#include "math.h" + + +#define NUM_ROWS 1000 + +/** + * Global result from the testcase. + */ +static int result; + +/** + * Report line of error if @a cond is true, and jump to label "drop". + */ +#define FAILIF(cond)                            \ +  do {                                          \ +      if (! (cond)) {break;}                    \ +    GNUNET_break (0);                           \ +    goto drop;                                  \ +  } while (0) + + +/** + * Initializes @a ptr with random data. + */ +#define RND_BLK(ptr)                                                    \ +  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr)) + +/** + * Initializes @a ptr with zeros. + */ +#define ZR_BLK(ptr) \ +  memset (ptr, 0, sizeof (*ptr)) + + +/** + * Currency we use.  Must match test-exchange-db-*.conf. + */ +#define CURRENCY "EUR" + +/** + * How big do we make the RSA keys? + */ +#define RSA_KEY_SIZE 1024 +static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins; + + +#define ROUNDS 100 +#define MELT_NEW_COINS 5 +#define MELT_NOREVEAL_INDEX 1 +/** + * Database plugin under test. + */ +static struct TALER_EXCHANGEDB_Plugin *plugin; +static struct TALER_DenomFeeSet fees; +static struct TALER_MerchantWireHashP h_wire_wt; +/** + * Denomination keys used for fresh coins in melt test. + */ +static struct DenomKeyPair **new_dkp; + +struct DenomKeyPair +{ +  struct TALER_DenominationPrivateKey priv; +  struct TALER_DenominationPublicKey pub; +}; + + +/** + * Destroy a denomination key pair.  The key is not necessarily removed from the DB. + * + * @param dkp the key pair to destroy + */ +static void +destroy_denom_key_pair (struct DenomKeyPair *dkp) +{ +  TALER_denom_pub_free (&dkp->pub); +  TALER_denom_priv_free (&dkp->priv); +  GNUNET_free (dkp); +} + + +/** + * Create a denomination key pair by registering the denomination in the DB. + * + * @param size the size of the denomination key + * @param now time to use for key generation, legal expiration will be 3h later. + * @param fees fees to use + * @return the denominaiton key pair; NULL upon error + */ +static struct DenomKeyPair * +create_denom_key_pair (unsigned int size, +                       struct GNUNET_TIME_Timestamp now, +                       const struct TALER_Amount *value, +                       const struct TALER_DenomFeeSet *fees) +{ +  struct DenomKeyPair *dkp; +  struct TALER_EXCHANGEDB_DenominationKey dki; +  struct TALER_EXCHANGEDB_DenominationKeyInformation issue2; + +  dkp = GNUNET_new (struct DenomKeyPair); +  GNUNET_assert (GNUNET_OK == +                 TALER_denom_priv_create (&dkp->priv, +                                          &dkp->pub, +                                          TALER_DENOMINATION_RSA, +                                          size)); +  memset (&dki, +          0, +          sizeof (struct TALER_EXCHANGEDB_DenominationKey)); +  dki.denom_pub = dkp->pub; +  dki.issue.start = now; +  dki.issue.expire_withdraw +    = GNUNET_TIME_absolute_to_timestamp ( +        GNUNET_TIME_absolute_add ( +          now.abs_time, +          GNUNET_TIME_UNIT_HOURS)); +  dki.issue.expire_deposit +    = GNUNET_TIME_absolute_to_timestamp ( +        GNUNET_TIME_absolute_add ( +          now.abs_time, +          GNUNET_TIME_relative_multiply ( +            GNUNET_TIME_UNIT_HOURS, 2))); +  dki.issue.expire_legal +    = GNUNET_TIME_absolute_to_timestamp ( +        GNUNET_TIME_absolute_add ( +          now.abs_time, +          GNUNET_TIME_relative_multiply ( +            GNUNET_TIME_UNIT_HOURS, 3))); +  dki.issue.value = *value; +  dki.issue.fees = *fees; +  TALER_denom_pub_hash (&dkp->pub, +                        &dki.issue.denom_hash); +  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +      plugin->insert_denomination_info (plugin->cls, +                                        &dki.denom_pub, +                                        &dki.issue)) +  { +    GNUNET_break (0); +    destroy_denom_key_pair (dkp); +    return NULL; +  } +  memset (&issue2, 0, sizeof (issue2)); +  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +      plugin->get_denomination_info (plugin->cls, +                                     &dki.issue.denom_hash, +                                     &issue2)) +  { +    GNUNET_break (0); +    destroy_denom_key_pair (dkp); +    return NULL; +  } +  if (0 != GNUNET_memcmp (&dki.issue, +                          &issue2)) +  { +    GNUNET_break (0); +    destroy_denom_key_pair (dkp); +    return NULL; +  } +  return dkp; +} + + + + +/** + * Main function that will be run by the scheduler. + * + * @param cls closure with config + */ + +static void +run (void *cls) +{ +  struct TALER_EXCHANGEDB_Refresh refresh; +  struct GNUNET_CONFIGURATION_Handle *cfg = cls; +  const uint32_t num_partitions = 10; +  struct TALER_Amount value; +  struct TALER_EXCHANGEDB_CollectableBlindcoin cbc; +  struct TALER_DenominationPublicKey *new_denom_pubs = NULL; +  struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO; +  unsigned long long sqrs=0; +  struct TALER_EXCHANGEDB_Deposit *depos=NULL; +  struct TALER_EXCHANGEDB_Refund *ref=NULL; +  unsigned int *perm; +  unsigned long long duration_sq; +  struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin; +  struct TALER_ExchangeWithdrawValues alg_values = { +    .cipher = TALER_DENOMINATION_RSA +    }; + +  ref = GNUNET_new_array (ROUNDS +1, +                          struct TALER_EXCHANGEDB_Refund); +  depos = GNUNET_new_array (ROUNDS +1, +                            struct TALER_EXCHANGEDB_Deposit); + +  if (NULL == +      (plugin = TALER_EXCHANGEDB_plugin_load (cfg))) +  { +    GNUNET_break (0); +    result = 77; +    return; +  } +  (void) plugin->drop_tables (plugin->cls); +  if (GNUNET_OK != +      plugin->create_tables (plugin->cls, +                             true, +                             num_partitions)) +  { +    GNUNET_break (0); +    result = 77; +    goto cleanup; +  } +  if (GNUNET_OK != +      plugin->preflight (plugin->cls)) +  { +    GNUNET_break (0); +    goto cleanup; +  } + +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":1.000010", +                                         &value)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000010", +                                         &fees.withdraw)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000010", +                                         &fees.deposit)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000010", +                                         &fees.refresh)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000010", +                                         &fees.refund)); +  //DENOMINATION +  { +    ZR_BLK (&cbc); +    //PAIR KEY LIST +    new_dkp = GNUNET_new_array (MELT_NEW_COINS, +                              struct DenomKeyPair *); +    //PUBLIC KEY LIST +    new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS, +                                       struct TALER_DenominationPublicKey); +    //REFRESH REVEAL COIN LIST +    revealed_coins +      = GNUNET_new_array (MELT_NEW_COINS, +                          struct TALER_EXCHANGEDB_RefreshRevealedCoin); +    for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) +      { +        struct GNUNET_TIME_Timestamp now; +        struct TALER_BlindedRsaPlanchet *rp; +        struct TALER_BlindedPlanchet *bp; + +        now = GNUNET_TIME_timestamp_get (); +        //5 KEY PAIR +        new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE, +                                              now, +                                              &value, +                                              &fees); +        GNUNET_assert (NULL != new_dkp[cnt]); +        new_denom_pubs[cnt] = new_dkp[cnt]->pub; +        ccoin = &revealed_coins[cnt]; +        bp = &ccoin->blinded_planchet; +        bp->cipher = TALER_DENOMINATION_RSA; +        rp = &bp->details.rsa_blinded_planchet; +        rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 ( +                                                                      GNUNET_CRYPTO_QUALITY_WEAK, +                                                                      (RSA_KEY_SIZE / 8) - 1); +        rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size); +        GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, +                                    rp->blinded_msg, +                                    rp->blinded_msg_size); +        TALER_denom_pub_hash (&new_dkp[cnt]->pub, +                              &ccoin->h_denom_pub); +        ccoin->exchange_vals = alg_values; +        TALER_coin_ev_hash (bp, +                            &ccoin->h_denom_pub, +                            &ccoin->coin_envelope_hash); +        GNUNET_assert (GNUNET_OK == +                     TALER_denom_sign_blinded (&ccoin->coin_sig, +                                               &new_dkp[cnt]->priv, +                                               true, +                                               bp)); +        GNUNET_assert (GNUNET_OK == +                       TALER_coin_ev_hash (bp, +                                           &cbc.denom_pub_hash, +                                           &cbc.h_coin_envelope)); +        GNUNET_assert ( +                       GNUNET_OK == +                       TALER_denom_sign_blinded ( +                                                 &cbc.sig, +                                                 &new_dkp[cnt]->priv, +                                                 false, +                                                 bp)); +      } +  } +  perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE, +                                       NUM_ROWS); +  //BEGIN +  FAILIF (GNUNET_OK != +          plugin->start (plugin->cls, +                         "Transaction")); +  for (unsigned int j = 0; j < NUM_ROWS; j++) +    { +      /*** NEED TO INSERT REFRESH COMMITMENTS + ENSURECOIN ***/ +      union TALER_DenominationBlindingKeyP bks; +      struct GNUNET_TIME_Timestamp deadline; +      struct TALER_CoinSpendPublicKeyP coin_pub; +      struct TALER_ReservePublicKeyP reserve_pub; +      struct TALER_CoinPubHashP c_hash; +      unsigned int k = (unsigned int)rand()%5; +      unsigned int i = perm[j]; +      if (i >= ROUNDS) +        i = ROUNDS; /* throw-away slot, do not keep around */ +      depos[i].deposit_fee = fees.deposit; +      RND_BLK (&coin_pub); +      RND_BLK (&c_hash); +      RND_BLK (&reserve_pub); +      RND_BLK (&cbc.reserve_sig); +      TALER_denom_pub_hash (&new_dkp[k]->pub, +                            &cbc.denom_pub_hash); +      deadline = GNUNET_TIME_timestamp_get (); +      RND_BLK (&depos[i].coin.coin_pub); +      TALER_denom_pub_hash (&new_dkp[k]->pub, +                            &depos[i].coin.denom_pub_hash); +      GNUNET_assert (GNUNET_OK == +                     TALER_denom_sig_unblind (&depos[i].coin.denom_sig, +                                              &ccoin->coin_sig, +                                              &bks, +                                              &c_hash, +                                              &alg_values, +                                              &new_dkp[k]->pub)); +      RND_BLK (&depos[i].merchant_pub); +      RND_BLK (&depos[i].csig); +      RND_BLK (&depos[i].h_contract_terms); +      RND_BLK (&depos[i].wire_salt); +      depos[i].amount_with_fee = value; +      depos[i].refund_deadline = deadline; +      depos[i].wire_deadline = deadline; +      depos[i].receiver_wire_account = +        "payto://iban/DE67830654080004822650?receiver-name=Test"; +      TALER_merchant_wire_signature_hash ( +                                          "payto://iban/DE67830654080004822650?receiver-name=Test", +                                          &depos[i].wire_salt, +                                          &h_wire_wt); +      cbc.reserve_pub = reserve_pub; +      cbc.amount_with_fee = value; +      GNUNET_assert (GNUNET_OK == +                     TALER_amount_set_zero (CURRENCY, +                                            &cbc.withdraw_fee)); +      { +        /* INSERT WIRE TARGETS */ +        bool found; +        bool nonce_ok; +        bool balance_ok; +        uint64_t ruuid; +        struct GNUNET_TIME_Timestamp now; +        now = GNUNET_TIME_timestamp_get (); +        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +                plugin->do_withdraw (plugin->cls, +                                     NULL, +                                     &cbc, +                                     now, +                                     &found, +                                     &balance_ok, +                                     &nonce_ok, +                                     &ruuid)); +      } + +      { +        /* ENSURE_COIN_KNOWN */ +        uint64_t known_coin_id; +        struct TALER_DenominationHashP dph; +        struct TALER_AgeCommitmentHash agh; +        FAILIF (TALER_EXCHANGEDB_CKS_ADDED != +                plugin->ensure_coin_known (plugin->cls, +                                           &depos[i].coin, +                                           &known_coin_id, +                                           &dph, +                                           &agh)); +        refresh.coin = depos[i].coin; +        RND_BLK (&refresh.coin_sig); +        RND_BLK (&refresh.rc); +        refresh.amount_with_fee = value; +        refresh.noreveal_index = MELT_NOREVEAL_INDEX; +      } +        /*STORE INTO DEPOSIT*/ +        { +          struct GNUNET_TIME_Timestamp now; +          now = GNUNET_TIME_timestamp_get (); +          FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +                  plugin->insert_deposit (plugin->cls, +                                          now, +                                          &depos[i])); +        } +        if (ROUNDS == i) +          TALER_denom_sig_free (&depos[i].coin.denom_sig); +    } +  /* End of benchmark setup */ +  GNUNET_free(perm); +  // commit +  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != +          plugin->commit (plugin->cls)); +  /**** CALL GET LINK DATA ****/ +  for (unsigned int r=0; r< ROUNDS; r++) +  { +    struct GNUNET_TIME_Absolute time; +    struct GNUNET_TIME_Relative duration; +    struct TALER_MerchantPublicKeyP merchant_pub; +    char *payto_uri; +    time = GNUNET_TIME_absolute_get(); +    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +            plugin->get_ready_deposit (plugin->cls, +                                       0, +                                       INT32_MAX, +                                       &merchant_pub, +                                       &payto_uri)); + +    duration = GNUNET_TIME_absolute_get_duration (time); +    times = GNUNET_TIME_relative_add (times, +                                      duration); +    duration_sq = duration.rel_value_us * duration.rel_value_us; +    GNUNET_assert (duration_sq / duration.rel_value_us == duration.rel_value_us); +    GNUNET_assert (sqrs + duration_sq >= sqrs); +    sqrs += duration_sq; +  } + +  /* evaluation of performance */ +  { +    struct GNUNET_TIME_Relative avg; +    double avg_dbl; +    double variance; + +    avg = GNUNET_TIME_relative_divide (times, +                                       ROUNDS); +    avg_dbl = avg.rel_value_us; +    variance = sqrs - (avg_dbl * avg_dbl * ROUNDS); +    fprintf(stdout, +            "%8llu ± %6.0f\n", +            (unsigned long long) avg.rel_value_us, +            sqrt (variance / (ROUNDS-1))); +  } +  result = 0; +drop: +  GNUNET_break (GNUNET_OK == +  plugin->drop_tables (plugin->cls)); +cleanup: +  if (NULL != revealed_coins) +  { +    for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) +    { +      TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig); +      TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet); +    } +    GNUNET_free (revealed_coins); +    revealed_coins = NULL; +  } +  GNUNET_free (new_denom_pubs); +  for (unsigned int cnt = 0; +       (NULL != new_dkp) && (cnt < MELT_NEW_COINS) && (NULL != new_dkp[cnt]); +       cnt++) +    destroy_denom_key_pair (new_dkp[cnt]); +  GNUNET_free (new_dkp); +  for (unsigned int i=0; i< ROUNDS ; i++) +    { +      TALER_denom_sig_free (&depos[i].coin.denom_sig); +    } +  GNUNET_free(depos); +  GNUNET_free(ref); +  TALER_EXCHANGEDB_plugin_unload (plugin); +  plugin = NULL; +} + + +int +main (int argc, +      char *const argv[]) +{ +  const char *plugin_name; +  char *config_filename; +  char *testname; +  struct GNUNET_CONFIGURATION_Handle *cfg; + +  (void) argc; +  result = -1; +  if (NULL == (plugin_name = strrchr (argv[0], (int) '-'))) +  { +    GNUNET_break (0); +    return -1; +  } +  GNUNET_log_setup (argv[0], +                    "WARNING", +                    NULL); +  plugin_name++; +  (void) GNUNET_asprintf (&testname, +                          "test-exchange-db-%s", +                          plugin_name); +  (void) GNUNET_asprintf (&config_filename, +                          "%s.conf", +                          testname); +  fprintf (stdout, +           "Using config: %s\n", +           config_filename); +  cfg = GNUNET_CONFIGURATION_create (); +  if (GNUNET_OK != +      GNUNET_CONFIGURATION_parse (cfg, +                                  config_filename)) +  { +    GNUNET_break (0); +    GNUNET_free (config_filename); +    GNUNET_free (testname); +    return 2; +  } +  GNUNET_SCHEDULER_run (&run, +                        cfg); +  GNUNET_CONFIGURATION_destroy (cfg); +  GNUNET_free (config_filename); +  GNUNET_free (testname); +  return result; +} + + +/* end of test_exchangedb_by_j.c */ diff --git a/src/exchangedb/test_exchangedb_populate_table.c b/src/exchangedb/test_exchangedb_populate_table.c index d67d1307..face454f 100644 --- a/src/exchangedb/test_exchangedb_populate_table.c +++ b/src/exchangedb/test_exchangedb_populate_table.c @@ -22,8 +22,11 @@  #include "taler_exchangedb_lib.h"  #include "taler_json_lib.h"  #include "taler_exchangedb_plugin.h" +#include "math.h" -/**o +#define NUM_ROWS 10000 + +/**   * Global result from the testcase.   */  static int result; @@ -56,20 +59,13 @@ static int result;   * Currency we use.  Must match test-exchange-db-*.conf.   */  #define CURRENCY "EUR" - - -/** - * Number of newly minted coins to use in the test. - */ -#define MELT_NEW_COINS 5 -#define i 0 -#define NUMBER_DEPOSIT 10  /**   * How big do we make the RSA keys?   */  #define RSA_KEY_SIZE 1024 - - +#define ROUNDS 1000 +#define MELT_NEW_COINS 5 +#define MELT_NOREVEAL_INDEX 1  /**   * Database plugin under test.   */ @@ -82,8 +78,8 @@ struct DenomKeyPair    struct TALER_DenominationPrivateKey priv;    struct TALER_DenominationPublicKey pub;  }; - - +static struct DenomKeyPair **new_dkp; +static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;  /**   * Destroy a denomination key pair.  The key is not necessarily removed from the DB.   * @@ -176,92 +172,30 @@ create_denom_key_pair (unsigned int size,    }    return dkp;  } - -/** - * Here we store the hash of the payto URI. - */ -static struct TALER_PaytoHashP wire_target_h_payto;  /** - * Counter used in auditor-related db functions. Used to count - * expected rows. - */ -static unsigned int auditor_row_cnt; -/** - * Callback for #select_deposits_above_serial_id () + * Callback invoked with information about refunds applicable + * to a particular coin.   * - * @param cls closure - * @param rowid unique serial ID for the deposit in our DB - * @param exchange_timestamp when did the deposit happen - * @param deposit deposit details - * @param denom_pub denomination of the @a coin_pub - * @param done flag set if the deposit was already executed (or not) + * @param cls closure with the `struct TALER_EXCHANGEDB_Refund *` we expect to get + * @param amount_with_fee amount being refunded   * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop   */  static enum GNUNET_GenericReturnValue -audit_deposit_cb (void *cls, -                  uint64_t rowid, -                  struct GNUNET_TIME_Timestamp exchange_timestamp, -                  const struct TALER_EXCHANGEDB_Deposit *deposit, -                  const struct TALER_DenominationPublicKey *denom_pub, -                  bool done) +check_refund_cb (void *cls, +                 const struct TALER_Amount *amount_with_fee)  { -  (void) cls; -  (void) rowid; -  (void) exchange_timestamp; -  (void) deposit; -  (void) denom_pub; -  (void) done; -  auditor_row_cnt++; -  return GNUNET_OK; -} -/** - * Function called on deposits that are past their due date - * and have not yet seen a wire transfer. - * - * @param cls closure a `struct TALER_EXCHANGEDB_Deposit *` - * @param rowid deposit table row of the coin's deposit - * @param coin_pub public key of the coin - * @param amount value of the deposit, including fee - * @param payto_uri where should the funds be wired - * @param deadline what was the requested wire transfer deadline - * @param done did the exchange claim that it made a transfer? - */ -static void -wire_missing_cb (void *cls, -                 uint64_t rowid, -                 const struct TALER_CoinSpendPublicKeyP *coin_pub, -                 const struct TALER_Amount *amount, -                 const char *payto_uri, -                 struct GNUNET_TIME_Timestamp deadline, -                 bool done) -{ -  const struct TALER_EXCHANGEDB_Deposit *deposit = cls; +  const struct TALER_EXCHANGEDB_Refund *refund = cls; -  (void) payto_uri; -  (void) deadline; -  (void) rowid; -  if (done) -  { -    GNUNET_break (0); -    result = 66; -  } -  if (0 != TALER_amount_cmp (amount, -                             &deposit->amount_with_fee)) -  { -    GNUNET_break (0); -    result = 66; -  } -  if (0 != GNUNET_memcmp (coin_pub, -                          &deposit->coin.coin_pub)) +  if (0 != TALER_amount_cmp (amount_with_fee, +                             &refund->details.refund_amount))    {      GNUNET_break (0);      result = 66;    } +  return GNUNET_OK;  } - -  /**   * Main function that will be run by the scheduler.   * @@ -275,27 +209,28 @@ run (void *cls)    const uint32_t num_partitions = 10;    struct DenomKeyPair *dkp = NULL;    struct GNUNET_TIME_Timestamp ts; -  struct TALER_EXCHANGEDB_Deposit depos[NUMBER_DEPOSIT]; +  struct TALER_EXCHANGEDB_Deposit *depos=NULL;    struct GNUNET_TIME_Timestamp deadline;    struct TALER_Amount value;    union TALER_DenominationBlindingKeyP bks;    struct TALER_CoinPubHashP c_hash;    struct TALER_EXCHANGEDB_CollectableBlindcoin cbc; -  struct TALER_EXCHANGEDB_CollectableBlindcoin cbc2;    struct TALER_ExchangeWithdrawValues alg_values = {      .cipher = TALER_DENOMINATION_RSA      }; -  struct TALER_PlanchetMasterSecretP ps; -  struct TALER_ReservePublicKeyP reserve_pub; -  struct TALER_EXCHANGEDB_Refund ref; - +  struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO; +  unsigned long long sqrs = 0; +  struct TALER_EXCHANGEDB_Refund *ref=NULL; +  unsigned int *perm; +  unsigned long long duration_sq; +  struct TALER_CoinSpendPublicKeyP coin_pub; +  struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin; +  struct TALER_DenominationPublicKey *new_denom_pubs = NULL; +  ref = GNUNET_new_array (ROUNDS +1, +                          struct TALER_EXCHANGEDB_Refund); +  depos = GNUNET_new_array (ROUNDS +1, +                            struct TALER_EXCHANGEDB_Deposit);    ZR_BLK (&cbc); -  ZR_BLK (&cbc2); -  RND_BLK (&reserve_pub); - -  memset (&ref, -          0, -          sizeof (ref));    if (NULL ==        (plugin = TALER_EXCHANGEDB_plugin_load (cfg))) @@ -337,209 +272,207 @@ run (void *cls)    GNUNET_assert (GNUNET_OK ==                   TALER_string_to_amount (CURRENCY ":0.000010",                                           &fees.refund)); +  GNUNET_assert (NUM_ROWS >= ROUNDS); +    ts = GNUNET_TIME_timestamp_get ();    deadline = GNUNET_TIME_timestamp_get (); -  dkp = create_denom_key_pair (RSA_KEY_SIZE, -                               ts, -                               &value, -                               &fees); - -  GNUNET_assert (NULL != dkp); -  TALER_denom_pub_hash (&dkp->pub, -                        &cbc.denom_pub_hash); -  RND_BLK (&cbc.reserve_sig); -  RND_BLK (&ps); -  TALER_planchet_blinding_secret_create (&ps, -                                         &alg_values, -                                         &bks); - - -  cbc.reserve_pub = reserve_pub; -  cbc.amount_with_fee = value; -  GNUNET_assert (GNUNET_OK == -                 TALER_amount_set_zero (CURRENCY, -                                        &cbc.withdraw_fee)); -  /* for (unsigned int i=0; i< NUMBER_DEPOSIT; i++) -     {*/ -            fprintf(stdout, "%d\n", i); -      struct TALER_CoinSpendPublicKeyP coin_pub; -      RND_BLK (&coin_pub); -      { -        struct TALER_PlanchetDetail pd; - -        struct TALER_AgeCommitmentHash age_hash; -        struct TALER_AgeCommitmentHash *p_ah[2] = { -          NULL, -          &age_hash -        }; - -        RND_BLK (&age_hash); - -        for (size_t k = 0; k < sizeof(p_ah) / sizeof(p_ah[0]); k++) -          { -            fprintf(stdout, "OPEN\n"); - -            GNUNET_assert (GNUNET_OK == -                           TALER_denom_blind (&dkp->pub, -                                              &bks, -                                              p_ah[k], -                                              &coin_pub, -                                              &alg_values, -                                              &c_hash, -                                              &pd.blinded_planchet)); -            GNUNET_assert (GNUNET_OK == -                           TALER_coin_ev_hash (&pd.blinded_planchet, -                                               &cbc.denom_pub_hash, -                                               &cbc.h_coin_envelope)); -            if (k != 0) -              TALER_blinded_denom_sig_free (&cbc.sig); -            GNUNET_assert ( -                           GNUNET_OK == -                           TALER_denom_sign_blinded ( -                                                     &cbc.sig, -                                                     &dkp->priv, -                                                     false, -                                                     &pd.blinded_planchet)); -            TALER_blinded_planchet_free (&pd.blinded_planchet); -          } -      } - - -      depos[i].deposit_fee = fees.deposit; - -      RND_BLK (&depos[i].coin.coin_pub); - -      TALER_denom_pub_hash (&dkp->pub, -                            &depos[i].coin.denom_pub_hash); -      // TALER_denom_pub_hash (&dkp->pub, -      //                    &ref.coin.denom_pub_hash); -      GNUNET_assert (GNUNET_OK == -                     TALER_denom_sig_unblind (&depos[i].coin.denom_sig, -                                              &cbc.sig, -                                              &bks, -                                              &c_hash, -                                              &alg_values, -                                              &dkp->pub)); - -      RND_BLK (&depos[i].merchant_pub); -      RND_BLK (&depos[i].csig); -      RND_BLK (&depos[i].h_contract_terms); -      RND_BLK (&depos[i].wire_salt); -      depos[i].amount_with_fee = value; -      depos[i].refund_deadline = deadline; -      depos[i].wire_deadline = deadline; -      depos[i].receiver_wire_account = -        "payto://iban/DE67830654080004822650?receiver-name=Test"; -      TALER_merchant_wire_signature_hash ( -                                          "payto://iban/DE67830654080004822650?receiver-name=Test", -                                          &depos[i].wire_salt, -                                          &h_wire_wt); -      depos[i].timestamp = ts; -      result = 8; -      { -        uint64_t known_coin_id; -        struct TALER_DenominationHashP dph; -        struct TALER_AgeCommitmentHash agh; -        FAILIF (TALER_EXCHANGEDB_CKS_ADDED != -                plugin->ensure_coin_known (plugin->cls, -                                           &depos[i].coin, -                                           &known_coin_id, -                                           &dph, -                                           &agh)); -      } - -      /*wire + deposit for get_ready_deposit*/ - -      /*STORE INTO DEPOSIT*/ +  //DENOMINATION +  { +    //PAIR KEY LIST +    new_dkp = GNUNET_new_array (MELT_NEW_COINS, +                              struct DenomKeyPair *); +    //PUBLIC KEY LIST +    new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS, +                                       struct TALER_DenominationPublicKey); +    //REFRESH REVEAL COIN LIST +    revealed_coins +      = GNUNET_new_array (MELT_NEW_COINS, +                          struct TALER_EXCHANGEDB_RefreshRevealedCoin); +    for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)        {          struct GNUNET_TIME_Timestamp now; -        struct GNUNET_TIME_Timestamp r; -        struct TALER_Amount deposit_fee; -        struct TALER_MerchantWireHashP h_wire; +        struct TALER_BlindedRsaPlanchet *rp; +        struct TALER_BlindedPlanchet *bp;          now = GNUNET_TIME_timestamp_get (); -        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != -                plugin->insert_deposit (plugin->cls, -                                        now, -                                        &depos[i])); -        TALER_merchant_wire_signature_hash (depos[i].receiver_wire_account, -                                            &depos[i].wire_salt, -                                            &h_wire); -        FAILIF (1 != -                plugin->have_deposit2 (plugin->cls, -                                       &depos[i].h_contract_terms, -                                       &h_wire, -                                       &depos[i].coin.coin_pub, -                                       &depos[i].merchant_pub, -                                       depos[i].refund_deadline, -                                       &deposit_fee, -                                       &r)); -        FAILIF (GNUNET_TIME_timestamp_cmp (now, -                                           !=, -                                           r)); -      } -      { -        struct GNUNET_TIME_Timestamp start_range; -        struct GNUNET_TIME_Timestamp end_range; - -        start_range = GNUNET_TIME_absolute_to_timestamp ( -                                                         GNUNET_TIME_absolute_subtract (deadline.abs_time, -                                                                                        GNUNET_TIME_UNIT_SECONDS)); -        end_range = GNUNET_TIME_absolute_to_timestamp ( -                                                       GNUNET_TIME_absolute_add (deadline.abs_time, -                                                                                 GNUNET_TIME_UNIT_SECONDS)); -        /*Aborted*/ -        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != -                plugin->select_deposits_missing_wire (plugin->cls, -                                                      start_range, -                                                      end_range, -                                                      &wire_missing_cb, -                                                      &depos[i])); - -          FAILIF (8 != result); +        //5 KEY PAIR +        new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE, +                                              now, +                                              &value, +                                              &fees); +        GNUNET_assert (NULL != new_dkp[cnt]); +        new_denom_pubs[cnt] = new_dkp[cnt]->pub; +        ccoin = &revealed_coins[cnt]; +        bp = &ccoin->blinded_planchet; +        bp->cipher = TALER_DENOMINATION_RSA; +        rp = &bp->details.rsa_blinded_planchet; +        rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 ( +                                                                      GNUNET_CRYPTO_QUALITY_WEAK, +                                                                      (RSA_KEY_SIZE / 8) - 1); +        rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size); +        GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, +                                    rp->blinded_msg, +                                    rp->blinded_msg_size); +        TALER_denom_pub_hash (&new_dkp[cnt]->pub, +                              &ccoin->h_denom_pub); +        ccoin->exchange_vals = alg_values; +        TALER_coin_ev_hash (bp, +                            &ccoin->h_denom_pub, +                            &ccoin->coin_envelope_hash); +        GNUNET_assert (GNUNET_OK == +                     TALER_denom_sign_blinded (&ccoin->coin_sig, +                                               &new_dkp[cnt]->priv, +                                               true, +                                               bp)); +        GNUNET_assert (GNUNET_OK == +                       TALER_coin_ev_hash (bp, +                                           &cbc.denom_pub_hash, +                                           &cbc.h_coin_envelope)); +        GNUNET_assert ( +                       GNUNET_OK == +                       TALER_denom_sign_blinded ( +                                                 &cbc.sig, +                                                 &new_dkp[cnt]->priv, +                                                 false, +                                                 bp));        } -      auditor_row_cnt = 0; -      FAILIF (0 >= -              plugin->select_deposits_above_serial_id (plugin->cls, -                                                       0, -                                                       &audit_deposit_cb, -                                                       NULL)); -      FAILIF (0 == auditor_row_cnt); -      result = 8; -      sleep (2); -      /*CREATE DEPOSIT*/ -      { -        struct TALER_MerchantPublicKeyP merchant_pub2; -        char *payto_uri2; - -        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != -                plugin->get_ready_deposit (plugin->cls, -                                           0, -                                           INT32_MAX, -                                           &merchant_pub2, -                                           &payto_uri2)); -        FAILIF (0 != GNUNET_memcmp (&merchant_pub2, -                                    &depos[i].merchant_pub)); -        FAILIF (0 != strcmp (payto_uri2, -                             depos[i].receiver_wire_account)); -        TALER_payto_hash (payto_uri2, -                          &wire_target_h_payto); -        GNUNET_free (payto_uri2); -        //  } -      /* { -    RND_BLK (&ref.details.merchant_pub); -    RND_BLK(&ref.details.merchant_sig); -    ref.details.h_contract_terms = depos.h_contract_terms; -    ref.coin.coin_pub = depos.coin.coin_pub; -    ref.details.rtransaction_id = 1; -    ref.details.refund_amount = value; -    ref.details.refund_fee = fees.refund; -    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != -            plugin->insert_refund (plugin->cls, -                                   &ref)); -                                   }*/ +  } + +  perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE, +                                       NUM_ROWS); +  // begin +  FAILIF (GNUNET_OK != +          plugin->start (plugin->cls, +                         "Transaction")); +  for (unsigned int j=0; j< NUM_ROWS; j++) +  { +    unsigned int i = perm[j]; +    unsigned int k = (unsigned int)rand()%5; +    if (i >= ROUNDS) +      i = ROUNDS; /* throw-away slot, do not keep around */ +    RND_BLK (&coin_pub); +    RND_BLK (&c_hash); +    depos[i].deposit_fee = fees.deposit; +    RND_BLK (&depos[i].coin.coin_pub); +    TALER_denom_pub_hash (&new_dkp[k]->pub, +                          &depos[i].coin.denom_pub_hash); +    // TALER_denom_pub_hash (&dkp->pub, +    //                    &ref.coin.denom_pub_hash); +    GNUNET_assert (GNUNET_OK == +                   TALER_denom_sig_unblind (&depos[i].coin.denom_sig, +                                            &cbc.sig, +                                            &bks, +                                            &c_hash, +                                            &alg_values, +                                            &new_dkp[k]->pub)); +    RND_BLK (&depos[i].merchant_pub); +    RND_BLK (&depos[i].csig); +    RND_BLK (&depos[i].h_contract_terms); +    RND_BLK (&depos[i].wire_salt); +    depos[i].amount_with_fee = value; +    depos[i].refund_deadline = deadline; +    depos[i].wire_deadline = deadline; +    depos[i].receiver_wire_account = +      "payto://iban/DE67830654080004822650?receiver-name=Test"; +    TALER_merchant_wire_signature_hash ( +                                        "payto://iban/DE67830654080004822650?receiver-name=Test", +                                        &depos[i].wire_salt, +                                        &h_wire_wt); +    depos[i].timestamp = ts; +      uint64_t known_coin_id; +    {//ENSURE_COIN_KNOWN + +      struct TALER_DenominationHashP dph; +      struct TALER_AgeCommitmentHash agh; +      FAILIF (TALER_EXCHANGEDB_CKS_ADDED != +              plugin->ensure_coin_known (plugin->cls, +                                         &depos[i].coin, +                                         &known_coin_id, +                                         &dph, +                                         &agh)); +    } +    /*STORE INTO DEPOSIT*/ +    { +      struct GNUNET_TIME_Timestamp now; +      now = GNUNET_TIME_timestamp_get (); +      FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +              plugin->insert_deposit (plugin->cls, +                                      now, +                                      &depos[i]));      } +    /* 100% Refund */ +    { +      bool not_found; +      bool refund_ok; +      bool gone; +      bool conflict; +      ref[i].coin = depos[i].coin; +      ref[i].details.merchant_pub = depos[i].merchant_pub; +      RND_BLK(&ref[i].details.merchant_sig); +      ref[i].details.h_contract_terms = depos[i].h_contract_terms; +      ref[i].coin.coin_pub = depos[i].coin.coin_pub; +      ref[i].details.rtransaction_id = i; +      ref[i].details.refund_amount = value; +      ref[i].details.refund_fee = fees.refund; +      FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +              plugin->do_refund (plugin->cls, +                                 &ref[i], +                                 &fees.deposit, +                                 known_coin_id, +                                 ¬_found, +                                 &refund_ok, +                                 &gone, +                                 &conflict)); + +      /*      FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +              plugin->insert_refund (plugin->cls, +              &ref[i]));*/ +    } +    if (ROUNDS == i) +      TALER_denom_sig_free (&depos[i].coin.denom_sig); +  } +  /* End of benchmark setup */ +  GNUNET_free (perm); +  // commit +  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != +          plugin->commit (plugin->cls)); +  for (unsigned int r = 0; r < ROUNDS; r++) +  { +    struct GNUNET_TIME_Absolute time; +    struct GNUNET_TIME_Relative duration; + +    time = GNUNET_TIME_absolute_get (); +    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +            plugin->select_refunds_by_coin (plugin->cls, +                                            &ref[r].coin.coin_pub, +                                            &ref[r].details.merchant_pub, +                                            &ref[r].details.h_contract_terms, +                                            &check_refund_cb, +                                            &ref[r])); +    duration = GNUNET_TIME_absolute_get_duration (time); +    times = GNUNET_TIME_relative_add (times, +                                      duration); +    duration_sq = duration.rel_value_us * duration.rel_value_us; +    GNUNET_assert (duration_sq / duration.rel_value_us == duration.rel_value_us); +    GNUNET_assert (sqrs + duration_sq >= sqrs); +    sqrs += duration_sq; +  } +  /* evaluation of performance */ +  { +    struct GNUNET_TIME_Relative avg; +    double avg_dbl; +    double variance; + +    avg = GNUNET_TIME_relative_divide (times, +                                       ROUNDS); +    avg_dbl = avg.rel_value_us; +    variance = sqrs - (avg_dbl * avg_dbl * ROUNDS); +    fprintf(stdout, +            "%8llu ± %6.0f\n", +            (unsigned long long) avg.rel_value_us, +            sqrt (variance / (ROUNDS-1))); +  }    result = 0;  drop:    GNUNET_break (GNUNET_OK == @@ -547,11 +480,28 @@ drop:  cleanup:    if (NULL != dkp)      destroy_denom_key_pair (dkp); -  //  for (unsigned int i=0; i<NUMBER_DEPOSIT; i++){ -  TALER_denom_sig_free (&depos[i].coin.denom_sig);//} - -  TALER_denom_sig_free (&ref.coin.denom_sig); -  TALER_blinded_denom_sig_free (&cbc.sig); +  if (NULL != revealed_coins) +  { +    for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) +    { +      TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig); +      TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet); +    } +    GNUNET_free (revealed_coins); +    revealed_coins = NULL; +  } +  GNUNET_free (new_denom_pubs); +  for (unsigned int cnt = 0; +       (NULL != new_dkp) && (cnt < MELT_NEW_COINS) && (NULL != new_dkp[cnt]); +       cnt++) +    destroy_denom_key_pair (new_dkp[cnt]); +  GNUNET_free (new_dkp); +  for (unsigned int i=0; i< ROUNDS +1 ; i++) +    { +      TALER_denom_sig_free (&depos[i].coin.denom_sig); +    } +  GNUNET_free(depos); +  GNUNET_free(ref);    dkp = NULL;    TALER_EXCHANGEDB_plugin_unload (plugin);    plugin = NULL; | 
