From 4bb96abc975aa6753828731a015b8ea7c00684f1 Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 30 Jan 2023 08:43:38 -0500 Subject: [PATCH] test for link data --- src/exchangedb/exchange_do_get_link_data.sql | 59 ++++ src/exchangedb/pg_get_link_data.c | 70 ++++- src/exchangedb/procedures.sql.in | 1 + .../test_exchangedb_populate_link_data.c | 275 +++++++++--------- 4 files changed, 259 insertions(+), 146 deletions(-) create mode 100644 src/exchangedb/exchange_do_get_link_data.sql diff --git a/src/exchangedb/exchange_do_get_link_data.sql b/src/exchangedb/exchange_do_get_link_data.sql new file mode 100644 index 000000000..a76f4aaaf --- /dev/null +++ b/src/exchangedb/exchange_do_get_link_data.sql @@ -0,0 +1,59 @@ +-- +-- 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 +-- +/*DROP FUNCTION exchange_do_refund_by_coin( + IN in_coin_pub BYTEA, + IN in_merchant_pub BYTEA, + IN in_h_contract BYTEA +);*/ +CREATE OR REPLACE FUNCTION exchange_do_get_link_data( + IN in_coin_pub BYTEA +) +RETURNS SETOF record +LANGUAGE plpgsql +AS $$ +DECLARE + curs CURSOR + FOR + SELECT + melt_serial_id + FROM refresh_commitments + WHERE old_coin_pub=in_coin_pub; + +DECLARE + i RECORD; +BEGIN +OPEN curs; +LOOP + FETCH NEXT FROM curs INTO i; + EXIT WHEN NOT FOUND; + RETURN QUERY + SELECT + tp.transfer_pub + ,denoms.denom_pub + ,rrc.ev_sig + ,rrc.ewv + ,rrc.link_sig + ,rrc.freshcoin_index + ,rrc.coin_ev + FROM refresh_revealed_coins rrc + JOIN refresh_transfer_keys tp + ON (tp.melt_serial_id=rrc.melt_serial_id) + JOIN denominations denoms + ON (rrc.denominations_serial=denoms.denominations_serial) + WHERE rrc.melt_serial_id =i.melt_serial_id; +END LOOP; +CLOSE curs; +END $$; diff --git a/src/exchangedb/pg_get_link_data.c b/src/exchangedb/pg_get_link_data.c index 9bc4c9b04..26225a13d 100644 --- a/src/exchangedb/pg_get_link_data.c +++ b/src/exchangedb/pg_get_link_data.c @@ -177,11 +177,35 @@ TEH_PG_get_link_data (void *cls, }; enum GNUNET_DB_QueryStatus qs; struct LinkDataContext ldctx; + static int percent_refund = -2; + const char *query; - if (NULL == getenv ("NEW_LOGIC")) + if (-2 == percent_refund) { + const char *mode = getenv ("NEW_LOGIC"); + char dummy; + + if ( (NULL==mode) || + (1 != sscanf (mode, + "%d%c", + &percent_refund, + &dummy)) ) + { + if (NULL != mode) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Bad mode `%s' specified\n", + mode); + } + if (NULL==mode) + percent_refund=0; + } + + switch (percent_refund) + { + case 0: + query="get_link"; PREPARE (pg, - "get_link", + query, "SELECT " " tp.transfer_pub" ",denoms.denom_pub" @@ -199,15 +223,15 @@ TEH_PG_get_link_data (void *cls, " ON (rrc.denominations_serial = denoms.denominations_serial)" " WHERE old_coin_pub=$1" " ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC"); - } - - else - { + break; + case 1: + query="get_link_v1"; PREPARE (pg, - "get_link", + query, "WITH rc AS MATERIALIZED (" "SELECT" - "* FROM refresh_commitments" + " melt_serial_id" + " FROM refresh_commitments" " WHERE old_coin_pub=$1" ")" "SELECT " @@ -217,13 +241,37 @@ TEH_PG_get_link_data (void *cls, ",rrc.ewv" ",rrc.link_sig" ",rrc.freshcoin_index" - ",rrc.coin_ev" - " FROM refresh_revealed_coins rrc" + ",rrc.coin_ev " + "FROM " + "refresh_revealed_coins rrc" " JOIN refresh_transfer_keys tp" " USING (melt_serial_id)" " JOIN denominations denoms" " USING (denominations_serial)" + " WHERE rrc.melt_serial_id = (SELECT melt_serial_id FROM rc)" " ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC"); + break; + case 2: + query="get_link_v2"; + PREPARE (pg, + query, + "SELECT" + " *" + " FROM" + " exchange_do_get_link_data" + " ($1) " + " AS " + " (transfer_pub BYTEA" + " ,denom_pub BYTEA" + " ,ev_sig BYTEA" + " ,ewv BYTEA" + " ,link_sig BYTEA" + " ,freshcoin_index INT4" + " ,coin_ev BYTEA);"); + break; + default: + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; } ldctx.ldc = ldc; @@ -231,7 +279,7 @@ TEH_PG_get_link_data (void *cls, ldctx.last = NULL; ldctx.status = GNUNET_OK; qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "get_link", + query, params, &add_ldl, &ldctx); diff --git a/src/exchangedb/procedures.sql.in b/src/exchangedb/procedures.sql.in index ef6341a1b..a53396c36 100644 --- a/src/exchangedb/procedures.sql.in +++ b/src/exchangedb/procedures.sql.in @@ -46,5 +46,6 @@ SET search_path TO exchange; #include "exchange_do_batch8_reserves_in_insert.sql" #include "exchange_do_refund_by_coin.sql" #include "exchange_do_get_ready_deposit.sql" +#include "exchange_do_get_link_data.sql" COMMIT; diff --git a/src/exchangedb/test_exchangedb_populate_link_data.c b/src/exchangedb/test_exchangedb_populate_link_data.c index 1323f3b3e..a4ddce1a2 100644 --- a/src/exchangedb/test_exchangedb_populate_link_data.c +++ b/src/exchangedb/test_exchangedb_populate_link_data.c @@ -49,9 +49,10 @@ #define CURRENCY "EUR" #define RSA_KEY_SIZE 1024 -#define ROUNDS 10 -#define NUM_ROWS 1000 +#define ROUNDS 2 +#define NUM_ROWS 10 #define MELT_NEW_COINS 5 +#define DENOMINATIONS 5 #define MELT_NOREVEAL_INDEX 1 /** * Database plugin under test. @@ -63,7 +64,7 @@ static struct TALER_DenomFeeSet fees; */ static struct DenomKeyPair **new_dkp; static int result; -static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins; + static struct TALER_TransferPrivateKeyP tprivs[TALER_CNC_KAPPA]; static struct TALER_TransferPublicKeyP tpub; struct DenomKeyPair @@ -165,7 +166,6 @@ create_denom_key_pair (unsigned int size, } return dkp; } - /** * Function called with the session hashes and transfer secret * information for a given coin. @@ -181,30 +181,10 @@ handle_link_data_cb (void *cls, { (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); - } + (void) ldl; } + /** * Main function that will be run by the scheduler. * @@ -221,13 +201,11 @@ run (void *cls) 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 }; @@ -237,7 +215,7 @@ run (void *cls) depos = GNUNET_new_array (ROUNDS +1, struct TALER_EXCHANGEDB_Deposit); refresh = GNUNET_new_array (ROUNDS +1, - struct TALER_EXCHANGEDB_Refresh); + struct TALER_EXCHANGEDB_Refresh); if (NULL == (plugin = TALER_EXCHANGEDB_plugin_load (cfg))) @@ -282,51 +260,18 @@ run (void *cls) { //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; + struct DenomKeyPair *); - 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)); - } + for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) + { + struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get (); + + new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE, + now, + &value, + &fees); + GNUNET_assert (NULL != new_dkp[cnt]); + } } perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE, NUM_ROWS); @@ -335,60 +280,111 @@ run (void *cls) 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); + { + union TALER_DenominationBlindingKeyP bks; + struct TALER_CoinPubHashP c_hash; + unsigned int i = perm[j]; + uint64_t known_coin_id; + struct TALER_EXCHANGEDB_CollectableBlindcoin cbc; + if (i >= ROUNDS) + i = ROUNDS; /* throw-away slot, do not keep around */ + RND_BLK (&depos[i].coin.coin_pub); + ZR_BLK (&cbc); + TALER_denom_pub_hash (&new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->pub, + &depos[i].coin.denom_pub_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)); + + + { + struct TALER_EXCHANGEDB_RefreshRevealedCoin revealed_coins[MELT_NEW_COINS]; + + for (unsigned int p=0;pblinded_planchet; + struct TALER_BlindedRsaPlanchet *rp = &bp->details.rsa_blinded_planchet; + + /* h_coin_ev must be unique, but we only have MELT_NEW_COINS created + above for NUM_ROWS iterations; instead of making "all new" coins, + we simply randomize the hash here as nobody is checking for consistency + anyway ;-) */ + bp->cipher = TALER_DENOMINATION_RSA; + 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[(unsigned int)rand()%MELT_NEW_COINS]->pub, + &revealed_coin->h_denom_pub); + revealed_coin->exchange_vals = alg_values; + TALER_coin_ev_hash (bp, + &revealed_coin->h_denom_pub, + &revealed_coin->coin_envelope_hash); + GNUNET_assert (GNUNET_OK == + TALER_denom_sign_blinded (&revealed_coin->coin_sig, + &new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->priv, + true, + bp)); + GNUNET_assert ( + GNUNET_OK == + TALER_denom_sign_blinded ( + &cbc.sig, + &new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->priv, + false, + bp)); + } + GNUNET_assert (GNUNET_OK == + TALER_denom_sig_unblind (&depos[i].coin.denom_sig, + &cbc.sig, + &bks, + &c_hash, + &alg_values, + &new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->pub)); + { + /* ENSURE_COIN_KNOWN */ + 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)); + } + /****GET melt_serial_id generated by default****/ { - /* 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; + struct TALER_EXCHANGEDB_Melt ret_refresh_session; + 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); + plugin->get_melt (plugin->cls, + &refresh[i].rc, + &ret_refresh_session, + &melt_serial_id)); } /**** INSERT REFRESH_REVEAL + TRANSFER_KEYS *****/ + { + static unsigned int cnt; + 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, @@ -397,9 +393,29 @@ run (void *cls) TALER_CNC_KAPPA - 1, tprivs, &tpub)); - if (ROUNDS == i) - TALER_denom_sig_free (&depos[i].coin.denom_sig); + cnt++; + // fprintf (stderr, "CNT: %u - %llu\n", cnt, (unsigned long long) melt_serial_id); + } + 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); + } + + { + struct TALER_CoinSpendPublicKeyP ocp; + uint64_t rrc_serial; + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->get_old_coin_by_h_blind (plugin->cls, + &revealed_coins[0].coin_envelope_hash, + &ocp, + &rrc_serial)); + } } + if (ROUNDS == i) + TALER_denom_sig_free (&depos[i].coin.denom_sig); + } /* End of benchmark setup */ GNUNET_free(perm); // commit @@ -412,6 +428,7 @@ run (void *cls) 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, @@ -444,22 +461,10 @@ run (void *cls) } result = 0; drop: - GNUNET_break (GNUNET_OK == - plugin->drop_tables (plugin->cls)); + // 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++)