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++)