summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c26
-rw-r--r--src/exchangedb/test_exchangedb.c128
-rw-r--r--src/include/taler_exchangedb_plugin.h2
3 files changed, 148 insertions, 8 deletions
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index 1f1e5f11..c9c3d5fd 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -3373,9 +3373,7 @@ static void
free_dpk_result (struct TALER_DenominationPublicKey *denom_pubs,
unsigned int denom_pubs_len)
{
- unsigned int i;
-
- for (i=0;i<denom_pubs_len;i++)
+ for (unsigned int i=0;i<denom_pubs_len;i++)
{
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[i].rsa_public_key);
denom_pubs[i].rsa_public_key = NULL;
@@ -3724,10 +3722,9 @@ postgres_get_refresh_transfer_public_key (void *cls,
/**
- * Insert signature of a new coin generated during refresh into
+ * Get signature of a new coin generated during refresh into
* the database indexed by the refresh session and the index
- * of the coin. This data is later used should an old coin
- * be used to try to obtain the private keys during "/refresh/link".
+ * of the coin.
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param session database connection
@@ -5988,7 +5985,7 @@ postgres_get_reserve_by_h_blind (void *cls,
* @param denom_pub_hash hash of the revoked denomination key
* @param master_sig signature affirming the revocation
* @return #GNUNET_OK on success,
- * #GNUNET_NO if the entry already exists
+ * #GNUNET_NO if the entry already exists (transaction must be rolled back!)
* #GNUNET_SYSERR on DB errors
*/
static int
@@ -6010,6 +6007,21 @@ postgres_insert_denomination_revocation (void *cls,
params);
if (PGRES_COMMAND_OK != PQresultStatus (result))
{
+ const char *efield;
+
+ efield = PQresultErrorField (result,
+ PG_DIAG_SQLSTATE);
+ if ( (PGRES_FATAL_ERROR == PQresultStatus(result)) &&
+ (NULL != strstr ("23505", /* unique violation */
+ efield)) )
+ {
+ /* This means we had the same reserve/justification/details
+ before */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Uniqueness violation, revocation details already known\n");
+ PQclear (result);
+ return GNUNET_NO;
+ }
ret = GNUNET_SYSERR;
BREAK_DB_ERR (result, session->conn);
}
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index 5175ef4f..f3a5adcb 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -663,18 +663,35 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
for (cnt=0; cnt < MELT_NEW_COINS; cnt++)
{
struct GNUNET_HashCode hc;
+ struct TALER_DenominationSignature test_sig;
RND_BLK (&hc);
ev_sigs[cnt].rsa_signature
= GNUNET_CRYPTO_rsa_sign_fdh (new_dkp[cnt]->priv.rsa_private_key,
&hc);
GNUNET_assert (NULL != ev_sigs[cnt].rsa_signature);
+ FAILIF (GNUNET_NO !=
+ plugin->get_refresh_out (plugin->cls,
+ session,
+ &session_hash,
+ cnt,
+ &test_sig));
FAILIF (GNUNET_OK !=
plugin->insert_refresh_out (plugin->cls,
session,
&session_hash,
cnt,
&ev_sigs[cnt]));
+ FAILIF (GNUNET_OK !=
+ plugin->get_refresh_out (plugin->cls,
+ session,
+ &session_hash,
+ cnt,
+ &test_sig));
+ FAILIF (0 !=
+ GNUNET_CRYPTO_rsa_signature_cmp (test_sig.rsa_signature,
+ ev_sigs[cnt].rsa_signature));
+ GNUNET_CRYPTO_rsa_signature_free (test_sig.rsa_signature);
}
ldl = plugin->get_link_data_list (plugin->cls,
@@ -706,6 +723,18 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
ldl);
{
+ /* Just to test fetching a coin with melt history */
+ struct TALER_EXCHANGEDB_TransactionList *tl;
+
+ tl = plugin->get_coin_transactions (plugin->cls,
+ session,
+ &meltp->coin.coin_pub);
+ plugin->free_coin_transaction_list (plugin->cls,
+ tl);
+ }
+
+
+ {
int ok;
ok = GNUNET_NO;
@@ -1338,7 +1367,38 @@ test_wire_out (struct TALER_EXCHANGEDB_Session *session,
}
+/**
+ * Function called about paybacks the exchange has to perform.
+ *
+ * @param cls closure with the expected value for @a coin_blind
+ * @param rowid row identifier used to uniquely identify the payback operation
+ * @param timestamp when did we receive the payback request
+ * @param amount how much should be added back to the reserve
+ * @param reserve_pub public key of the reserve
+ * @param coin public information about the coin
+ * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_PAYBACK
+ * @param coin_blind blinding factor used to blind the coin
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static int
+payback_cb (void *cls,
+ uint64_t rowid,
+ struct GNUNET_TIME_Absolute timestamp,
+ const struct TALER_Amount *amount,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_CoinPublicInfo *coin,
+ const struct TALER_CoinSpendSignatureP *coin_sig,
+ const struct TALER_DenominationBlindingKeyP *coin_blind)
+{
+ const struct TALER_DenominationBlindingKeyP *cb = cls;
+ FAILIF (0 != memcmp (cb,
+ coin_blind,
+ sizeof (*cb)));
+ return GNUNET_OK;
+ drop:
+ return GNUNET_SYSERR;
+}
/**
@@ -1355,7 +1415,10 @@ run (void *cls)
struct GNUNET_TIME_Absolute deadline;
struct TALER_DenominationBlindingKeyP coin_blind;
struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_ReservePublicKeyP reserve_pub2;
struct DenomKeyPair *dkp;
+ struct GNUNET_HashCode dkp_pub_hash;
+ struct TALER_MasterSignatureP master_sig;
struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
struct TALER_EXCHANGEDB_CollectableBlindcoin cbc2;
struct TALER_EXCHANGEDB_ReserveHistory *rh;
@@ -1407,6 +1470,14 @@ run (void *cls)
result = 77;
goto drop;
}
+
+ /* test DB is empty */
+ FAILIF (GNUNET_NO !=
+ plugin->select_payback_above_serial_id (plugin->cls,
+ session,
+ 0,
+ &payback_cb,
+ NULL));
RND_BLK (&reserve_pub);
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":1.000010",
@@ -1473,6 +1544,8 @@ run (void *cls)
&fee_deposit,
&fee_refresh,
&fee_refund);
+ GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key,
+ &dkp_pub_hash);
RND_BLK(&cbc.h_coin_envelope);
RND_BLK(&cbc.reserve_sig);
cbc.denom_pub = dkp->pub;
@@ -1493,6 +1566,16 @@ run (void *cls)
value.value,
value.fraction,
value.currency));
+
+ FAILIF (GNUNET_YES !=
+ plugin->get_reserve_by_h_blind (plugin->cls,
+ session,
+ &cbc.h_coin_envelope,
+ &reserve_pub2));
+ FAILIF (0 != memcmp (&reserve_pub,
+ &reserve_pub2,
+ sizeof (reserve_pub)));
+
FAILIF (GNUNET_YES !=
plugin->get_withdraw_info (plugin->cls,
session,
@@ -1715,6 +1798,43 @@ run (void *cls)
&refund));
+ /* test payback / revocation */
+ RND_BLK (&master_sig);
+ FAILIF (GNUNET_OK !=
+ plugin->insert_denomination_revocation (plugin->cls,
+ session,
+ &dkp_pub_hash,
+ &master_sig));
+ FAILIF (GNUNET_OK !=
+ plugin->commit (plugin->cls,
+ session));
+ FAILIF (GNUNET_OK !=
+ plugin->start (plugin->cls,
+ session));
+ FAILIF (GNUNET_NO !=
+ plugin->insert_denomination_revocation (plugin->cls,
+ session,
+ &dkp_pub_hash,
+ &master_sig));
+ plugin->rollback (plugin->cls,
+ session);
+ FAILIF (GNUNET_OK !=
+ plugin->start (plugin->cls,
+ session));
+ {
+ struct TALER_MasterSignatureP msig;
+
+ FAILIF (GNUNET_OK !=
+ plugin->get_denomination_revocation (plugin->cls,
+ session,
+ &dkp_pub_hash,
+ &msig));
+ FAILIF (0 != memcmp (&msig,
+ &master_sig,
+ sizeof (msig)));
+ }
+
+
RND_BLK (&coin_sig);
RND_BLK (&coin_blind);
FAILIF (GNUNET_OK !=
@@ -1728,6 +1848,13 @@ run (void *cls)
&cbc.h_coin_envelope,
deadline));
+ FAILIF (GNUNET_OK !=
+ plugin->select_payback_above_serial_id (plugin->cls,
+ session,
+ 0,
+ &payback_cb,
+ &coin_blind));
+
auditor_row_cnt = 0;
FAILIF (GNUNET_OK !=
plugin->select_refunds_above_serial_id (plugin->cls,
@@ -1856,6 +1983,7 @@ run (void *cls)
FAILIF (GNUNET_OK !=
test_wire_fees (session));
+
result = 0;
drop:
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index a5295378..a287ea56 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -2022,7 +2022,7 @@ struct TALER_EXCHANGEDB_Plugin
* @param denom_pub_hash hash of the revoked denomination key
* @param master_sig signature affirming the revocation
* @return #GNUNET_OK on success,
- * #GNUNET_NO if the entry already exists
+ * #GNUNET_NO if the entry already exists (transaction must be rolled back!)
* #GNUNET_SYSERR on DB errors
*/
int