diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c index 2e8f0a02..929f3c15 100644 --- a/src/exchange/taler-exchange-httpd_db.c +++ b/src/exchange/taler-exchange-httpd_db.c @@ -66,7 +66,8 @@ TEH_DB_know_coin_transaction (void *cls, GNUNET_assert (NULL != mhd_ret); qs = TEH_plugin->ensure_coin_known (TEH_plugin->cls, session, - kcc->coin); + kcc->coin, + &kcc->known_coin_id); if (GNUNET_DB_STATUS_HARD_ERROR == qs) { *mhd_ret diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 95143758..a17e6a18 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -121,6 +121,11 @@ struct DepositContext */ struct TALER_Amount value; + /** + * ID of the coin in the database. + */ + uint64_t coin_id; + }; @@ -237,7 +242,7 @@ deposit_transaction (void *cls, qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls, session, - &deposit->coin.coin_pub, + dc->coin_id, GNUNET_NO, &tl); if (0 > qs) @@ -271,11 +276,11 @@ deposit_transaction (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deposited coin has insufficient funds left!\n"); - *mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection, - TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS, - &deposit->coin. - coin_pub, - tl); + *mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds ( + connection, + TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS, + &deposit->coin.coin_pub, + tl); TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); return GNUNET_DB_STATUS_HARD_ERROR; @@ -286,6 +291,7 @@ deposit_transaction (void *cls, qs = TEH_plugin->insert_deposit (TEH_plugin->cls, session, dc->exchange_timestamp, + dc->coin_id, deposit); if (GNUNET_DB_STATUS_HARD_ERROR == qs) { @@ -511,6 +517,7 @@ TEH_handler_deposit (struct MHD_Connection *connection, GNUNET_JSON_parse_free (spec); return mhd_ret; } + dc.coin_id = kcc.known_coin_id; } /* check deposit signature */ diff --git a/src/exchange/taler-exchange-httpd_melt.c b/src/exchange/taler-exchange-httpd_melt.c index 3a0195cf..e13e6775 100644 --- a/src/exchange/taler-exchange-httpd_melt.c +++ b/src/exchange/taler-exchange-httpd_melt.c @@ -150,6 +150,11 @@ struct MeltContext */ struct TALER_Amount coin_refresh_fee; + /** + * Unique ID of the coin this melt is about. + */ + uint64_t coin_id; + /** * Set to #GNUNET_YES if this coin's denomination was revoked and the operation * is thus only allowed for zombie coins where the transaction @@ -187,7 +192,7 @@ refresh_check_melt (struct MHD_Connection *connection, we might be a zombie coin */ qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls, session, - &rmc->refresh_session.coin.coin_pub, + rmc->coin_id, GNUNET_YES, &tl); if (0 > qs) @@ -343,6 +348,7 @@ melt_transaction (void *cls, if (0 >= (qs = TEH_plugin->insert_melt (TEH_plugin->cls, session, + rmc->coin_id, &rmc->refresh_session))) { if (GNUNET_DB_STATUS_SOFT_ERROR != qs) @@ -583,6 +589,7 @@ check_for_denomination_key (struct MHD_Connection *connection, &TEH_DB_know_coin_transaction, &kcc)) return mhd_ret; + rmc->coin_id = kcc.known_coin_id; } /* sanity-check that "total melt amount > melt fee" */ diff --git a/src/exchange/taler-exchange-httpd_recoup.c b/src/exchange/taler-exchange-httpd_recoup.c index c1f6ff33..52a59356 100644 --- a/src/exchange/taler-exchange-httpd_recoup.c +++ b/src/exchange/taler-exchange-httpd_recoup.c @@ -93,6 +93,11 @@ struct RecoupContext */ struct GNUNET_TIME_Absolute now; + /** + * Which coin is this about? + */ + uint64_t coin_id; + /** * #GNUNET_YES if the client claims the coin originated from a refresh. */ @@ -187,7 +192,7 @@ recoup_transaction (void *cls, /* Calculate remaining balance, including recoups already applied. */ qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls, session, - &pc->coin->coin_pub, + pc->coin_id, GNUNET_YES, &tl); if (0 > qs) @@ -293,6 +298,7 @@ recoup_transaction (void *cls, { qs = TEH_plugin->insert_recoup_refresh_request (TEH_plugin->cls, session, + pc->coin_id, pc->coin, pc->coin_sig, pc->coin_bks, @@ -305,6 +311,7 @@ recoup_transaction (void *cls, qs = TEH_plugin->insert_recoup_request (TEH_plugin->cls, session, &pc->target.reserve_pub, + pc->coin_id, pc->coin, pc->coin_sig, pc->coin_bks, @@ -343,12 +350,12 @@ recoup_transaction (void *cls, * @return MHD result code */ static MHD_RESULT -verify_and_execute_recoup (struct MHD_Connection *connection, - const struct TALER_CoinPublicInfo *coin, - const struct - TALER_DenominationBlindingKeyP *coin_bks, - const struct TALER_CoinSpendSignatureP *coin_sig, - int refreshed) +verify_and_execute_recoup ( + struct MHD_Connection *connection, + const struct TALER_CoinPublicInfo *coin, + const struct TALER_DenominationBlindingKeyP *coin_bks, + const struct TALER_CoinSpendSignatureP *coin_sig, + int refreshed) { struct RecoupContext pc; const struct TALER_EXCHANGEDB_DenominationKey *dki; @@ -464,6 +471,7 @@ verify_and_execute_recoup (struct MHD_Connection *connection, &TEH_DB_know_coin_transaction, &kcc)) return mhd_ret; + pc.coin_id = kcc.known_coin_id; } /* Perform actual recoup transaction */ diff --git a/src/exchangedb/exchange-0001.sql b/src/exchangedb/exchange-0001.sql index ad05e779..31c6c02d 100644 --- a/src/exchangedb/exchange-0001.sql +++ b/src/exchangedb/exchange-0001.sql @@ -168,9 +168,11 @@ CREATE INDEX IF NOT EXISTS reserves_out_for_get_withdraw_info CREATE TABLE IF NOT EXISTS known_coins - (coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (LENGTH(coin_pub)=32) + (known_coin_id BIGSERIAL PRIMARY KEY + ,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32) ,denom_pub_hash BYTEA NOT NULL REFERENCES denominations (denom_pub_hash) ON DELETE CASCADE - ,denom_sig BYTEA NOT NULL + ,denom_sig BYTEA NOT NULL, + UNIQUE (coin_pub, denom_pub_hash) ); COMMENT ON TABLE known_coins IS 'information about coins and their signatures, so we do not have to store the signatures more than once if a coin is involved in multiple operations'; @@ -183,7 +185,7 @@ CREATE INDEX IF NOT EXISTS known_coins_by_denomination CREATE TABLE IF NOT EXISTS refresh_commitments (melt_serial_id BIGSERIAL UNIQUE ,rc BYTEA PRIMARY KEY CHECK (LENGTH(rc)=64) - ,old_coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE + ,old_known_coin_id INT8 NOT NULL REFERENCES known_coins (known_coin_id) ON DELETE CASCADE ,old_coin_sig BYTEA NOT NULL CHECK(LENGTH(old_coin_sig)=64) ,amount_with_fee_val INT8 NOT NULL ,amount_with_fee_frac INT4 NOT NULL @@ -192,9 +194,9 @@ CREATE TABLE IF NOT EXISTS refresh_commitments COMMENT ON TABLE refresh_commitments IS 'Commitments made when melting coins and the gamma value chosen by the exchange.'; -CREATE INDEX IF NOT EXISTS refresh_commitments_old_coin_pub_index +CREATE INDEX IF NOT EXISTS refresh_commitments_old_coin_index ON refresh_commitments - (old_coin_pub); + (old_known_coin_id); CREATE TABLE IF NOT EXISTS refresh_revealed_coins @@ -221,7 +223,7 @@ COMMENT ON COLUMN refresh_revealed_coins.h_coin_ev COMMENT ON COLUMN refresh_revealed_coins.ev_sig IS 'exchange signature over the envelope'; -CREATE INDEX IF NOT EXISTS refresh_revealed_coins_coin_pub_index +CREATE INDEX IF NOT EXISTS refresh_revealed_coins_denom_index ON refresh_revealed_coins (denom_pub_hash); @@ -251,7 +253,7 @@ COMMENT ON INDEX refresh_transfer_keys_coin_tpub CREATE TABLE IF NOT EXISTS deposits (deposit_serial_id BIGSERIAL PRIMARY KEY - ,coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE + ,known_coin_id INT8 NOT NULL REFERENCES known_coins (known_coin_id) ON DELETE CASCADE ,amount_with_fee_val INT8 NOT NULL ,amount_with_fee_frac INT4 NOT NULL ,wallet_timestamp INT8 NOT NULL @@ -265,7 +267,7 @@ CREATE TABLE IF NOT EXISTS deposits ,wire TEXT NOT NULL ,tiny BOOLEAN NOT NULL DEFAULT FALSE ,done BOOLEAN NOT NULL DEFAULT FALSE - ,UNIQUE (coin_pub, merchant_pub, h_contract_terms) + ,UNIQUE (known_coin_id, merchant_pub, h_contract_terms) ); COMMENT ON TABLE deposits IS 'Deposits we have received and for which we need to make (aggregate) wire transfers (and manage refunds).'; @@ -274,13 +276,13 @@ COMMENT ON COLUMN deposits.done COMMENT ON COLUMN deposits.tiny IS 'Set to TRUE if we decided that the amount is too small to ever trigger a wire transfer by itself (requires real aggregation)'; -CREATE INDEX IF NOT EXISTS deposits_coin_pub_merchant_contract_index +CREATE INDEX IF NOT EXISTS deposits_coin_merchant_contract_index ON deposits - (coin_pub + (known_coin_id ,merchant_pub ,h_contract_terms ); -COMMENT ON INDEX deposits_coin_pub_merchant_contract_index +COMMENT ON INDEX deposits_coin_merchant_contract_index IS 'for get_deposit_for_wtid and test_deposit_done'; CREATE INDEX IF NOT EXISTS deposits_get_ready_index ON deposits @@ -289,7 +291,7 @@ CREATE INDEX IF NOT EXISTS deposits_get_ready_index ,wire_deadline ,refund_deadline ); -COMMENT ON INDEX deposits_coin_pub_merchant_contract_index +COMMENT ON INDEX deposits_get_ready_index IS 'for deposits_get_ready'; CREATE INDEX IF NOT EXISTS deposits_iterate_matching_index ON deposits @@ -304,23 +306,23 @@ COMMENT ON INDEX deposits_iterate_matching_index CREATE TABLE IF NOT EXISTS refunds (refund_serial_id BIGSERIAL UNIQUE - ,coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE + ,known_coin_id INT8 NOT NULL REFERENCES known_coins (known_coin_id) ON DELETE CASCADE ,merchant_pub BYTEA NOT NULL CHECK(LENGTH(merchant_pub)=32) ,merchant_sig BYTEA NOT NULL CHECK(LENGTH(merchant_sig)=64) ,h_contract_terms BYTEA NOT NULL CHECK(LENGTH(h_contract_terms)=64) ,rtransaction_id INT8 NOT NULL ,amount_with_fee_val INT8 NOT NULL ,amount_with_fee_frac INT4 NOT NULL - ,PRIMARY KEY (coin_pub, merchant_pub, h_contract_terms, rtransaction_id) + ,PRIMARY KEY (known_coin_id, merchant_pub, h_contract_terms, rtransaction_id) ); COMMENT ON TABLE refunds - IS 'Data on coins that were refunded. Technically, refunds always apply against specific deposit operations involving a coin. The combination of coin_pub, merchant_pub, h_contract_terms and rtransaction_id MUST be unique, and we usually select by coin_pub so that one goes first.'; + IS 'Data on coins that were refunded. Technically, refunds always apply against specific deposit operations involving a coin. The combination of known_coin_id, merchant_pub, h_contract_terms and rtransaction_id MUST be unique, and we usually select by known_coin_id so that one goes first.'; COMMENT ON COLUMN refunds.rtransaction_id IS 'used by the merchant to make refunds unique in case the same coin for the same deposit gets a subsequent (higher) refund'; -CREATE INDEX IF NOT EXISTS refunds_coin_pub_index +CREATE INDEX IF NOT EXISTS refunds_coin_index ON refunds - (coin_pub); + (known_coin_id); CREATE TABLE IF NOT EXISTS wire_out @@ -372,7 +374,7 @@ CREATE INDEX IF NOT EXISTS wire_fee_gc_index CREATE TABLE IF NOT EXISTS recoup (recoup_uuid BIGSERIAL UNIQUE - ,coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) + ,known_coin_id INT8 NOT NULL REFERENCES known_coins (known_coin_id) ON DELETE CASCADE ,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64) ,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32) ,amount_val INT8 NOT NULL @@ -382,25 +384,25 @@ CREATE TABLE IF NOT EXISTS recoup ); COMMENT ON TABLE recoup IS 'Information about recoups that were executed'; -COMMENT ON COLUMN recoup.coin_pub - IS 'Do not CASCADE ON DROP on the coin_pub, as we may keep the coin alive!'; +COMMENT ON COLUMN recoup.known_coin_id + IS 'Do not CASCADE ON DROP on the known_coin_id, as we may keep the coin alive!'; CREATE INDEX IF NOT EXISTS recoup_by_coin_index ON recoup - (coin_pub); + (known_coin_id); CREATE INDEX IF NOT EXISTS recoup_by_h_blind_ev ON recoup (h_blind_ev); CREATE INDEX IF NOT EXISTS recoup_for_by_reserve ON recoup - (coin_pub + (known_coin_id ,h_blind_ev ); CREATE TABLE IF NOT EXISTS recoup_refresh (recoup_refresh_uuid BIGSERIAL UNIQUE - ,coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) + ,known_coin_id INT8 NOT NULL REFERENCES known_coins (known_coin_id) ON DELETE CASCADE ,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64) ,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32) ,amount_val INT8 NOT NULL @@ -408,18 +410,18 @@ CREATE TABLE IF NOT EXISTS recoup_refresh ,timestamp INT8 NOT NULL ,h_blind_ev BYTEA NOT NULL REFERENCES refresh_revealed_coins (h_coin_ev) ON DELETE CASCADE ); -COMMENT ON COLUMN recoup_refresh.coin_pub - IS 'Do not CASCADE ON DROP on the coin_pub, as we may keep the coin alive!'; +COMMENT ON COLUMN recoup_refresh.known_coin_id + IS 'Do not CASCADE ON DROP on the known_coin_id, as we may keep the coin alive!'; CREATE INDEX IF NOT EXISTS recoup_refresh_by_coin_index ON recoup_refresh - (coin_pub); + (known_coin_id); CREATE INDEX IF NOT EXISTS recoup_refresh_by_h_blind_ev ON recoup_refresh (h_blind_ev); CREATE INDEX IF NOT EXISTS recoup_refresh_for_by_reserve ON recoup_refresh - (coin_pub + (known_coin_id ,h_blind_ev ); diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index dede901f..6e25e496 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -556,17 +556,16 @@ postgres_get_session (void *cls) " FROM known_coins" " WHERE denom_pub_hash=$1;", 1), - /* Used in #postgres_get_known_coin() to fetch - the denomination public key and signature for - a coin known to the exchange. */ - GNUNET_PQ_make_prepare ("get_known_coin", + /* Used in #postgres_check_known_coin() to fetch + the known_coin_id for a coin known to the exchange. */ + GNUNET_PQ_make_prepare ("check_known_coin", "SELECT" - " denom_pub_hash" - ",denom_sig" + " known_coin_id" " FROM known_coins" " WHERE coin_pub=$1" + " AND denom_pub_hash=$2" " FOR UPDATE;", - 1), + 2), /* Used in #postgres_get_coin_denomination() to fetch the denomination public key hash for a coin known to the exchange. */ @@ -592,7 +591,8 @@ postgres_get_session (void *cls) ",denom_pub_hash" ",denom_sig" ") VALUES " - "($1,$2,$3);", + "($1,$2,$3) " + "RETURNING known_coin_id;", 3), /* Used in #postgres_insert_melt() to store @@ -600,7 +600,7 @@ postgres_get_session (void *cls) GNUNET_PQ_make_prepare ("insert_melt", "INSERT INTO refresh_commitments " "(rc " - ",old_coin_pub " + ",old_known_coin_id " ",old_coin_sig " ",amount_with_fee_val " ",amount_with_fee_frac " @@ -615,14 +615,14 @@ postgres_get_session (void *cls) " kc.denom_pub_hash" ",denom.fee_refresh_val" ",denom.fee_refresh_frac" - ",old_coin_pub" + ",kc.coin_pub AS old_coin_pub" ",old_coin_sig" ",amount_with_fee_val" ",amount_with_fee_frac" ",noreveal_index" " FROM refresh_commitments" " JOIN known_coins kc" - " ON (refresh_commitments.old_coin_pub = kc.coin_pub)" + " ON (refresh_commitments.old_known_coin_id = kc.known_coin_id)" " JOIN denominations denom" " ON (kc.denom_pub_hash = denom.denom_pub_hash)" " WHERE rc=$1;", @@ -640,7 +640,7 @@ postgres_get_session (void *cls) GNUNET_PQ_make_prepare ("audit_get_refresh_commitments_incr", "SELECT" " denom.denom_pub" - ",old_coin_pub" + ",kc.coin_pub AS old_coin_pub" ",old_coin_sig" ",amount_with_fee_val" ",amount_with_fee_frac" @@ -649,7 +649,7 @@ postgres_get_session (void *cls) ",rc" " FROM refresh_commitments" " JOIN known_coins kc" - " ON (refresh_commitments.old_coin_pub = kc.coin_pub)" + " ON (refresh_commitments.old_known_coin_id = kc.known_coin_id)" " JOIN denominations denom" " ON (kc.denom_pub_hash = denom.denom_pub_hash)" " WHERE melt_serial_id>=$1" @@ -667,9 +667,9 @@ postgres_get_session (void *cls) ",melt_serial_id" " FROM refresh_commitments" " JOIN known_coins " - " ON (refresh_commitments.old_coin_pub = known_coins.coin_pub)" + " ON (refresh_commitments.old_known_coin_id = known_coins.known_coin_id)" " JOIN denominations denom USING (denom_pub_hash)" - " WHERE old_coin_pub=$1;", + " WHERE old_known_coin_id=$1;", 1), /* Store information about the desired denominations for a @@ -727,7 +727,7 @@ postgres_get_session (void *cls) /* Used in #postgres_insert_refund() to store refund information */ GNUNET_PQ_make_prepare ("insert_refund", "INSERT INTO refunds " - "(coin_pub " + "(known_coin_id " ",merchant_pub " ",merchant_sig " ",h_contract_terms " @@ -750,9 +750,9 @@ postgres_get_session (void *cls) ",denom.fee_refund_frac " ",refund_serial_id" " FROM refunds" - " JOIN known_coins USING (coin_pub)" + " JOIN known_coins USING (known_coin_id)" " JOIN denominations denom USING (denom_pub_hash)" - " WHERE coin_pub=$1;", + " WHERE known_coin_id=$1;", 1), /* Query the 'refunds' by coin public key, merchant_pub and contract hash */ GNUNET_PQ_make_prepare ("get_refunds_by_coin_and_contract", @@ -760,8 +760,7 @@ postgres_get_session (void *cls) " amount_with_fee_val" ",amount_with_fee_frac" " FROM refunds" - " WHERE" - " coin_pub=$1" + " WHERE known_coin_id=$1" " AND merchant_pub=$2" " AND h_contract_terms=$3;", 3), @@ -778,7 +777,7 @@ postgres_get_session (void *cls) ",amount_with_fee_frac" ",refund_serial_id" " FROM refunds" - " JOIN known_coins kc USING (coin_pub)" + " JOIN known_coins kc USING (known_coin_id)" " JOIN denominations denom ON (kc.denom_pub_hash = denom.denom_pub_hash)" " WHERE refund_serial_id>=$1" " ORDER BY refund_serial_id ASC;", @@ -793,7 +792,7 @@ postgres_get_session (void *cls) Used in #postgres_insert_deposit(). */ GNUNET_PQ_make_prepare ("insert_deposit", "INSERT INTO deposits " - "(coin_pub" + "(known_coin_id" ",amount_with_fee_val" ",amount_with_fee_frac" ",wallet_timestamp" @@ -824,9 +823,9 @@ postgres_get_session (void *cls) ",h_contract_terms" ",h_wire" " FROM deposits" - " JOIN known_coins USING (coin_pub)" + " JOIN known_coins USING (known_coin_id)" " JOIN denominations USING (denom_pub_hash)" - " WHERE ((coin_pub=$1)" + " WHERE ((known_coin_id=$1)" " AND (merchant_pub=$3)" " AND (h_contract_terms=$2))" " FOR UPDATE;", @@ -849,7 +848,7 @@ postgres_get_session (void *cls) ",done" ",deposit_serial_id" " FROM deposits" - " JOIN known_coins USING (coin_pub)" + " JOIN known_coins USING (known_coin_id)" " JOIN denominations denom USING (denom_pub_hash)" " WHERE (" " (deposit_serial_id>=$1)" @@ -866,14 +865,12 @@ postgres_get_session (void *cls) ",denom.fee_deposit_frac" ",wire_deadline" " FROM deposits" - " JOIN known_coins USING (coin_pub)" + " JOIN known_coins USING (known_coin_id)" " JOIN denominations denom USING (denom_pub_hash)" - " WHERE (" - " (coin_pub=$1)" + " WHERE (coin_pub=$1)" " AND (merchant_pub=$2)" " AND (h_contract_terms=$3)" - " AND (h_wire=$4)" - " );", + " AND (h_wire=$4);", 4), /* Used in #postgres_get_ready_deposit() */ GNUNET_PQ_make_prepare ("deposits_get_ready", @@ -887,11 +884,11 @@ postgres_get_session (void *cls) ",h_contract_terms" ",wire" ",merchant_pub" - ",coin_pub" + ",coin_pub" // FIXME: probably should also return known_coin_id! ",exchange_timestamp" ",wallet_timestamp" " FROM deposits" - " JOIN known_coins USING (coin_pub)" + " JOIN known_coins USING (known_coin_id)" " JOIN denominations denom USING (denom_pub_hash)" " WHERE tiny=FALSE" " AND done=FALSE" @@ -915,7 +912,7 @@ postgres_get_session (void *cls) ",coin_pub" " FROM deposits" " JOIN known_coins" - " USING (coin_pub)" + " USING (known_coin_id)" " JOIN denominations denom" " USING (denom_pub_hash)" " WHERE" @@ -943,7 +940,7 @@ postgres_get_session (void *cls) GNUNET_PQ_make_prepare ("test_deposit_done", "SELECT done" " FROM deposits" - " WHERE coin_pub=$1" + " WHERE known_coin_id=$1" " AND merchant_pub=$2" " AND h_contract_terms=$3" " AND h_wire=$4;", @@ -967,10 +964,10 @@ postgres_get_session (void *cls) ",deposit_serial_id" " FROM deposits" " JOIN known_coins" - " USING (coin_pub)" + " USING (known_coin_id)" " JOIN denominations denom" " USING (denom_pub_hash)" - " WHERE coin_pub=$1" + " WHERE known_coin_id=$1" " FOR UPDATE;", 1), @@ -988,7 +985,9 @@ postgres_get_session (void *cls) " USING (rc)" " JOIN denominations denoms" " ON (rrc.denom_pub_hash = denoms.denom_pub_hash)" - " WHERE old_coin_pub=$1" + " JOIN known_coins kc" + " ON (old_known_coin_id = kc.known_coin_id)" + " WHERE kc.coin_pub=$1" " ORDER BY tp.transfer_pub", 1), /* Used in #postgres_lookup_wire_transfer */ @@ -998,7 +997,7 @@ postgres_get_session (void *cls) ",deposits.h_contract_terms" ",deposits.wire" ",deposits.h_wire" - ",deposits.coin_pub" + ",known_coins.coin_pub" ",deposits.merchant_pub" ",wire_out.execution_date" ",deposits.amount_with_fee_val" @@ -1010,7 +1009,7 @@ postgres_get_session (void *cls) " JOIN deposits" " USING (deposit_serial_id)" " JOIN known_coins" - " USING (coin_pub)" + " USING (known_coin_id)" " JOIN denominations denom" " USING (denom_pub_hash)" " JOIN wire_out" @@ -1030,7 +1029,7 @@ postgres_get_session (void *cls) " JOIN aggregation_tracking" " USING (deposit_serial_id)" " JOIN known_coins" - " USING (coin_pub)" + " USING (known_coin_id)" " JOIN denominations denom" " USING (denom_pub_hash)" " JOIN wire_out" @@ -1120,7 +1119,7 @@ postgres_get_session (void *cls) GNUNET_PQ_make_prepare ("deposits_get_overdue", "SELECT" " deposit_serial_id" - ",coin_pub" + ",kc.coin_pub" // FIXME: also return coin_id? ",amount_with_fee_val" ",amount_with_fee_frac" ",wire" @@ -1128,11 +1127,13 @@ postgres_get_session (void *cls) ",tiny" ",done" " FROM deposits" + " JOIN known_coins kc" + " USING (known_coin_id)" " WHERE wire_deadline >= $1" " AND wire_deadline < $2" " AND NOT (EXISTS (SELECT 1" " FROM refunds" - " WHERE (refunds.coin_pub = deposits.coin_pub))" + " WHERE (refunds.known_coin_id = deposits.known_coin_id))" " OR EXISTS (SELECT 1" " FROM aggregation_tracking" " WHERE (aggregation_tracking.deposit_serial_id = deposits.deposit_serial_id)))" @@ -1168,7 +1169,7 @@ postgres_get_session (void *cls) information */ GNUNET_PQ_make_prepare ("recoup_insert", "INSERT INTO recoup " - "(coin_pub" + "(known_coin_id" ",coin_sig" ",coin_blind" ",amount_val" @@ -1182,7 +1183,7 @@ postgres_get_session (void *cls) information */ GNUNET_PQ_make_prepare ("recoup_refresh_insert", "INSERT INTO recoup_refresh " - "(coin_pub" + "(known_coin_id" ",coin_sig" ",coin_blind" ",amount_val" @@ -1209,7 +1210,7 @@ postgres_get_session (void *cls) ",amount_frac" " FROM recoup" " JOIN known_coins coins" - " USING (coin_pub)" + " USING (known_coin_id)" " JOIN reserves_out ro" " USING (h_blind_ev)" " JOIN denominations denoms" @@ -1223,9 +1224,9 @@ postgres_get_session (void *cls) "SELECT" " recoup_refresh_uuid" ",timestamp" - ",rc.old_coin_pub" + ",old_coins.coin_pub AS old_coin_pub" ",old_coins.denom_pub_hash AS old_denom_pub_hash" - ",recoup_refresh.coin_pub" + ",new_coins.coin_pub" ",coin_sig" ",coin_blind" ",denoms.denom_pub" @@ -1240,9 +1241,9 @@ postgres_get_session (void *cls) " INNER JOIN refresh_commitments rc" " ON (rrc.rc = rc.rc)" " INNER JOIN known_coins old_coins" - " ON (rc.old_coin_pub = old_coins.coin_pub)" + " ON (rc.old_known_coin_id = old_coins.known_coin_id)" " INNER JOIN known_coins new_coins" - " ON (new_coins.coin_pub = recoup_refresh.coin_pub)" + " ON (new_coins.known_coin_id = recoup_refresh.known_coin_id)" " INNER JOIN denominations denoms" " ON (new_coins.denom_pub_hash = denoms.denom_pub_hash)" " WHERE recoup_refresh_uuid>=$1" @@ -1279,7 +1280,7 @@ postgres_get_session (void *cls) ",coins.denom_sig" " FROM recoup" " JOIN known_coins coins" - " USING (coin_pub)" + " USING (known_coin_id)" " JOIN reserves_out ro" " USING (h_blind_ev)" " WHERE ro.reserve_pub=$1" @@ -1289,7 +1290,8 @@ postgres_get_session (void *cls) affecting old coins of refreshed coins */ GNUNET_PQ_make_prepare ("recoup_by_old_coin", "SELECT" - " coin_pub" + " known_coin_id" + ",coins.coin_pub" ",coin_sig" ",coin_blind" ",amount_val" @@ -1299,14 +1301,14 @@ postgres_get_session (void *cls) ",coins.denom_sig" ",recoup_refresh_uuid" " FROM recoup_refresh" - " JOIN known_coins coins" - " USING (coin_pub)" + " JOIN known_coins coins" + " USING (known_coin_id)" " WHERE h_blind_ev IN" " (SELECT rrc.h_coin_ev" " FROM refresh_commitments" " JOIN refresh_revealed_coins rrc" " USING (rc)" - " WHERE old_coin_pub=$1)" + " WHERE old_known_coin_id=$1)" " FOR UPDATE;", 1), /* Used in #postgres_get_reserve_history() */ @@ -1352,19 +1354,21 @@ postgres_get_session (void *cls) " FROM recoup" " JOIN reserves_out ro" " USING (h_blind_ev)" - " WHERE recoup.coin_pub=$1" + " WHERE recoup.known_coin_id=$1" " FOR UPDATE;", 1), /* Used in #postgres_get_coin_transactions() to obtain recoup transactions for a refreshed coin */ GNUNET_PQ_make_prepare ("recoup_by_refreshed_coin", "SELECT" - " rc.old_coin_pub" + " rc.old_known_coin_id" + ",old_known.coin_pub AS old_coin_pub" ",coin_sig" ",coin_blind" ",amount_val" ",amount_frac" ",timestamp" + ",coins.coin_pub" ",coins.denom_pub_hash" ",coins.denom_sig" ",recoup_refresh_uuid" @@ -1374,8 +1378,10 @@ postgres_get_session (void *cls) " JOIN refresh_commitments rc" " ON (rrc.rc = rc.rc)" " JOIN known_coins coins" - " USING (coin_pub)" - " WHERE coin_pub=$1" + " USING (known_coin_id)" + " JOIN known_coins old_known" + " ON (rc.old_known_coin_id = old_known.known_coin_id)" + " WHERE recoup_refresh.known_coin_id=$1" " FOR UPDATE;", 1), /* Used in #postgres_get_reserve_by_h_blind() */ @@ -1390,10 +1396,12 @@ postgres_get_session (void *cls) /* Used in #postgres_get_old_coin_by_h_blind() */ GNUNET_PQ_make_prepare ("old_coin_by_h_blind", "SELECT" - " rcom.old_coin_pub" + " kc.coin_pub" // FIXME: also return coin_id? " FROM refresh_revealed_coins" " JOIN refresh_commitments rcom" " USING (rc)" + " JOIN known_coins kc" + " ON (rcom.old_known_coin_id = kc.known_coin_id)" " WHERE h_coin_ev=$1" " LIMIT 1" " FOR UPDATE;", @@ -2595,6 +2603,7 @@ postgres_get_reserve_history (void *cls, static enum GNUNET_DB_QueryStatus postgres_have_deposit (void *cls, struct TALER_EXCHANGEDB_Session *session, + uint64_t coin_id, const struct TALER_EXCHANGEDB_Deposit *deposit, int check_extras, struct TALER_Amount *deposit_fee, @@ -2602,7 +2611,7 @@ postgres_have_deposit (void *cls, { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub), + GNUNET_PQ_query_param_uint64 (&coin_id), GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms), GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub), GNUNET_PQ_query_param_end @@ -2711,13 +2720,13 @@ postgres_mark_deposit_tiny (void *cls, static enum GNUNET_DB_QueryStatus postgres_test_deposit_done (void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t coin_id, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct GNUNET_HashCode *h_contract_terms, const struct GNUNET_HashCode *h_wire) { struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_uint64 (&coin_id), GNUNET_PQ_query_param_auto_from_type (merchant_pub), GNUNET_PQ_query_param_auto_from_type (h_contract_terms), GNUNET_PQ_query_param_auto_from_type (h_wire), @@ -3039,84 +3048,43 @@ postgres_iterate_matching_deposits ( /** - * Retrieve the record for a known coin. + * Check if a coin is known, and if so, return the @a known_coin_id. * * @param cls the plugin closure * @param session the database session handle * @param coin_pub the public key of the coin to search for - * @param coin_info place holder for the returned coin information object + * @param denom_pub_hash hash of the denomination of the coin + * @param[out] known_coin_id identifier of the coin in the database * @return transaction status code */ static enum GNUNET_DB_QueryStatus -postgres_get_known_coin (void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_CoinPublicInfo *coin_info) +postgres_check_known_coin (void *cls, + struct TALER_EXCHANGEDB_Session *session, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct GNUNET_HashCode *denom_pub_hash, + uint64_t *known_coin_id) { struct PostgresClosure *pc = cls; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &coin_info->denom_pub_hash), - GNUNET_PQ_result_spec_rsa_signature ("denom_sig", - &coin_info->denom_sig.rsa_signature), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + known_coin_id), GNUNET_PQ_result_spec_end }; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting known coin data for coin %s\n", TALER_B2S (coin_pub)); - coin_info->coin_pub = *coin_pub; - if (NULL == session) - session = postgres_get_session (pc); - if (NULL == session) - return GNUNET_DB_STATUS_HARD_ERROR; - return GNUNET_PQ_eval_prepared_singleton_select (session->conn, - "get_known_coin", - params, - rs); -} - - -/** - * Retrieve the denomination of a known coin. - * - * @param cls the plugin closure - * @param session the database session handle - * @param coin_pub the public key of the coin to search for - * @param[out] denom_hash where to store the hash of the coins denomination - * @return transaction status code - */ -static enum GNUNET_DB_QueryStatus -postgres_get_coin_denomination ( - void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct GNUNET_HashCode *denom_hash) -{ - struct PostgresClosure *pc = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - denom_hash), - GNUNET_PQ_result_spec_end - }; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Getting coin denomination of coin %s\n", - TALER_B2S (coin_pub)); if (NULL == session) session = postgres_get_session (pc); if (NULL == session) return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_PQ_eval_prepared_singleton_select (session->conn, - "get_coin_denomination", + "check_known_coin", params, rs); } @@ -3130,12 +3098,14 @@ postgres_get_coin_denomination ( * @param cls plugin closure * @param session the shared database session * @param coin_info the public coin info + * @param[out] known_coin_id set to identifier of the coin in the database * @return query result status */ static enum GNUNET_DB_QueryStatus insert_known_coin (void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinPublicInfo *coin_info) + const struct TALER_CoinPublicInfo *coin_info, + uint64_t *known_coin_id) { struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (&coin_info->coin_pub), @@ -3143,14 +3113,20 @@ insert_known_coin (void *cls, GNUNET_PQ_query_param_rsa_signature (coin_info->denom_sig.rsa_signature), GNUNET_PQ_query_param_end }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + known_coin_id), + GNUNET_PQ_result_spec_end + }; (void) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating known coin %s\n", TALER_B2S (&coin_info->coin_pub)); - return GNUNET_PQ_eval_prepared_non_select (session->conn, - "insert_known_coin", - params); + return GNUNET_PQ_eval_prepared_singleton_select (session->conn, + "insert_known_coin", + params, + rs); } @@ -3196,16 +3172,17 @@ postgres_count_known_coins (void *cls, * @param cls database connection plugin state * @param session database session * @param coin the coin that must be made known + * @param[out] known_coin_id set to identifier of the coin in the database * @return database transaction status, non-negative on success */ static enum GNUNET_DB_QueryStatus postgres_ensure_coin_known (void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinPublicInfo *coin) + const struct TALER_CoinPublicInfo *coin, + uint64_t *known_coin_id) { struct PostgresClosure *pc = cls; enum GNUNET_DB_QueryStatus qs; - struct TALER_CoinPublicInfo known_coin; #if EXPLICIT_LOCKS struct GNUNET_PQ_QueryParam no_params[] = { GNUNET_PQ_query_param_end @@ -3218,10 +3195,11 @@ postgres_ensure_coin_known (void *cls, #endif /* check if the coin is already known */ - qs = postgres_get_known_coin (pc, - session, - &coin->coin_pub, - &known_coin); + qs = postgres_check_known_coin (pc, + session, + &coin->coin_pub, + &coin->denom_pub_hash, + known_coin_id); if (0 > qs) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -3229,14 +3207,14 @@ postgres_ensure_coin_known (void *cls, } if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) { - GNUNET_CRYPTO_rsa_signature_free (known_coin.denom_sig.rsa_signature); return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; /* no change! */ } GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs); /* if not known, insert it */ qs = insert_known_coin (pc, session, - coin); + coin, + known_coin_id); if (0 >= qs) { if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) @@ -3254,6 +3232,7 @@ postgres_ensure_coin_known (void *cls, * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session connection to the database * @param exchange_timestamp time the exchange received the deposit request + * @param coin_id which coin is this about * @param deposit deposit information to store * @return query result status */ @@ -3261,10 +3240,11 @@ static enum GNUNET_DB_QueryStatus postgres_insert_deposit (void *cls, struct TALER_EXCHANGEDB_Session *session, struct GNUNET_TIME_Absolute exchange_timestamp, + uint64_t coin_id, const struct TALER_EXCHANGEDB_Deposit *deposit) { struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub), + GNUNET_PQ_query_param_uint64 (&coin_id), TALER_PQ_query_param_amount (&deposit->amount_with_fee), TALER_PQ_query_param_absolute_time (&deposit->timestamp), TALER_PQ_query_param_absolute_time (&deposit->refund_deadline), @@ -3301,10 +3281,11 @@ postgres_insert_deposit (void *cls, static enum GNUNET_DB_QueryStatus postgres_insert_refund (void *cls, struct TALER_EXCHANGEDB_Session *session, + uint64_t coin_id, const struct TALER_EXCHANGEDB_Refund *refund) { struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub), + GNUNET_PQ_query_param_uint64 (&coin_id), GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub), GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig), GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms), @@ -3397,7 +3378,7 @@ get_refunds_cb (void *cls, * * @param cls closure of plugin * @param session database handle to use - * @param coin_pub coin to get refunds for + * @param coin_id coin to get refunds for * @param merchant_pub merchant to get refunds for * @param h_contract contract (hash) to get refunds for * @param cb function to call for each refund found @@ -3408,7 +3389,7 @@ static enum GNUNET_DB_QueryStatus postgres_select_refunds_by_coin ( void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t coin_id, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct GNUNET_HashCode *h_contract, TALER_EXCHANGEDB_RefundCoinCallback cb, @@ -3417,7 +3398,7 @@ postgres_select_refunds_by_coin ( struct PostgresClosure *pg = cls; enum GNUNET_DB_QueryStatus qs; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_uint64 (&coin_id), GNUNET_PQ_query_param_auto_from_type (merchant_pub), GNUNET_PQ_query_param_auto_from_type (h_contract), GNUNET_PQ_query_param_end @@ -3535,6 +3516,7 @@ postgres_get_melt_index (void *cls, * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database handle to use + * @param coin_id which coin is the melt about * @param refresh_session session data to store * @return query status for the transaction */ @@ -3542,11 +3524,12 @@ static enum GNUNET_DB_QueryStatus postgres_insert_melt ( void *cls, struct TALER_EXCHANGEDB_Session *session, + uint64_t coin_id, const struct TALER_EXCHANGEDB_Refresh *refresh_session) { struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (&refresh_session->rc), - GNUNET_PQ_query_param_auto_from_type (&refresh_session->coin.coin_pub), + GNUNET_PQ_query_param_uint64 (&coin_id), GNUNET_PQ_query_param_auto_from_type (&refresh_session->coin_sig), TALER_PQ_query_param_amount (&refresh_session->amount_with_fee), GNUNET_PQ_query_param_uint32 (&refresh_session->noreveal_index), @@ -4029,9 +4012,9 @@ struct CoinHistoryContext struct TALER_EXCHANGEDB_TransactionList *head; /** - * Public key of the coin we are building the history for. + * Unique ID of the coin we are building the history for. */ - const struct TALER_CoinSpendPublicKeyP *coin_pub; + uint64_t known_coin_id; /** * Closure for all callbacks of this database plugin. @@ -4281,6 +4264,8 @@ add_old_coin_recoup (void *cls, recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupRefreshListEntry); { struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + &recoup->coin_id), GNUNET_PQ_result_spec_auto_from_type ("coin_pub", &recoup->coin.coin_pub), GNUNET_PQ_result_spec_auto_from_type ("coin_sig", @@ -4311,7 +4296,8 @@ add_old_coin_recoup (void *cls, chc->failed = true; return; } - recoup->old_coin_pub = *chc->coin_pub; + // recoup->old_coin_pub = *chc->coin_pub; + recoup->old_coin_id = chc->known_coin_id; } tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); tl->next = chc->head; @@ -4409,8 +4395,9 @@ add_coin_recoup_refresh (void *cls, recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupRefreshListEntry); { struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", - &recoup->old_coin_pub), + GNUNET_PQ_result_spec_auto_from_type ("old_known_coin_id", + &recoup->old_coin_id), + // GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", &recoup->old_coin_pub), GNUNET_PQ_result_spec_auto_from_type ("coin_sig", &recoup->coin_sig), GNUNET_PQ_result_spec_auto_from_type ("coin_blind", @@ -4419,6 +4406,8 @@ add_coin_recoup_refresh (void *cls, &recoup->value), TALER_PQ_result_spec_absolute_time ("timestamp", &recoup->timestamp), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &recoup->coin.coin_pub), GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &recoup->coin.denom_pub_hash), GNUNET_PQ_result_spec_rsa_signature ("denom_sig", @@ -4439,7 +4428,7 @@ add_coin_recoup_refresh (void *cls, chc->failed = true; return; } - recoup->coin.coin_pub = *chc->coin_pub; + recoup->coin_id = chc->known_coin_id; } tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); tl->next = chc->head; @@ -4474,7 +4463,7 @@ struct Work * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection - * @param coin_pub coin to investigate + * @param known_coin_id which coin to investigate * @param include_recoup should recoup transactions be included in the @a tlp * @param[out] tlp set to list of transactions, NULL if coin is fresh * @return database transaction status @@ -4483,7 +4472,7 @@ static enum GNUNET_DB_QueryStatus postgres_get_coin_transactions ( void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, int include_recoup, struct TALER_EXCHANGEDB_TransactionList **tlp) { @@ -4522,23 +4511,20 @@ postgres_get_coin_transactions ( { NULL, NULL } }; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_uint64 (&known_coin_id), GNUNET_PQ_query_param_end }; enum GNUNET_DB_QueryStatus qs; const struct Work *work; struct CoinHistoryContext chc = { .head = NULL, - .coin_pub = coin_pub, + .known_coin_id = known_coin_id, // FIXME: needed where? .session = session, .pg = pg, .db_cls = cls }; work = (GNUNET_YES == include_recoup) ? work_wp : work_op; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Getting transactions for coin %s\n", - TALER_B2S (coin_pub)); for (unsigned int i = 0; NULL != work[i].statement; i++) { qs = GNUNET_PQ_eval_prepared_multi_select (session->conn, @@ -6844,6 +6830,7 @@ postgres_select_reserve_closed_above_serial_id ( * @param cls closure * @param session database connection * @param reserve_pub public key of the reserve that is being refunded + * @param coin_id unique identifier of the recouped coin * @param coin information about the coin * @param coin_sig signature of the coin of type #TALER_SIGNATURE_WALLET_COIN_RECOUP * @param coin_blind blinding key of the coin @@ -6857,7 +6844,7 @@ postgres_insert_recoup_request ( void *cls, struct TALER_EXCHANGEDB_Session *session, const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_CoinPublicInfo *coin, + uint64_t coin_id, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_DenominationBlindingKeyP *coin_blind, const struct TALER_Amount *amount, @@ -6868,7 +6855,7 @@ postgres_insert_recoup_request ( struct GNUNET_TIME_Absolute expiry; struct TALER_EXCHANGEDB_Reserve reserve; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub), + GNUNET_PQ_query_param_uint64 (&coin_id), GNUNET_PQ_query_param_auto_from_type (coin_sig), GNUNET_PQ_query_param_auto_from_type (coin_blind), TALER_PQ_query_param_amount (amount), @@ -6936,7 +6923,7 @@ postgres_insert_recoup_request ( * * @param cls closure * @param session database connection - * @param coin public information about the refreshed coin + * @param coin_id unique identifier of the recoup-refreshed coin * @param coin_sig signature of the coin of type #TALER_SIGNATURE_WALLET_COIN_RECOUP * @param coin_blind blinding key of the coin * @param h_blind_ev blinded envelope, as calculated by the exchange @@ -6949,7 +6936,7 @@ static enum GNUNET_DB_QueryStatus postgres_insert_recoup_refresh_request ( void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinPublicInfo *coin, + uint64_t coin_id, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_DenominationBlindingKeyP *coin_blind, const struct TALER_Amount *amount, @@ -6957,7 +6944,7 @@ postgres_insert_recoup_refresh_request ( struct GNUNET_TIME_Absolute timestamp) { struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub), + GNUNET_PQ_query_param_uint64 (&coin_id), GNUNET_PQ_query_param_auto_from_type (coin_sig), GNUNET_PQ_query_param_auto_from_type (coin_blind), TALER_PQ_query_param_amount (amount), @@ -7339,8 +7326,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) plugin->free_reserve_history = &common_free_reserve_history; plugin->count_known_coins = &postgres_count_known_coins; plugin->ensure_coin_known = &postgres_ensure_coin_known; - plugin->get_known_coin = &postgres_get_known_coin; - plugin->get_coin_denomination = &postgres_get_coin_denomination; + plugin->check_known_coin = &postgres_check_known_coin; plugin->have_deposit = &postgres_have_deposit; plugin->mark_deposit_tiny = &postgres_mark_deposit_tiny; plugin->test_deposit_done = &postgres_test_deposit_done; diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index 043095e7..714aaa7d 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -516,6 +516,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session) int ret; enum GNUNET_DB_QueryStatus qs; struct GNUNET_TIME_Absolute now; + uint64_t coin_id; ret = GNUNET_SYSERR; RND_BLK (&refresh_session); @@ -562,10 +563,12 @@ test_melting (struct TALER_EXCHANGEDB_Session *session) FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->ensure_coin_known (plugin->cls, session, - &refresh_session.coin)); + &refresh_session.coin, + &coin_id)); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->insert_melt (plugin->cls, session, + coin_id, &refresh_session)); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_melt (plugin->cls, @@ -581,9 +584,11 @@ test_melting (struct TALER_EXCHANGEDB_Session *session) TALER_amount_cmp (&fee_refresh, &ret_refresh_session.melt_fee)); FAILIF (0 != - GNUNET_memcmp (&refresh_session.rc, &ret_refresh_session.session.rc)); - FAILIF (0 != GNUNET_memcmp (&refresh_session.coin_sig, - &ret_refresh_session.session.coin_sig)); + GNUNET_memcmp (&refresh_session.rc, + &ret_refresh_session.session.rc)); + FAILIF (0 != + GNUNET_memcmp (&refresh_session.coin_sig, + &ret_refresh_session.session.coin_sig)); FAILIF (NULL != ret_refresh_session.session.coin.denom_sig.rsa_signature); FAILIF (0 != memcmp (&refresh_session.coin.coin_pub, @@ -680,7 +685,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session) qs = plugin->get_coin_transactions (plugin->cls, session, - &refresh_session.coin.coin_pub, + coin_id, GNUNET_YES, &tl); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs); @@ -1521,6 +1526,7 @@ run (void *cls) uint64_t rr; enum GNUNET_DB_QueryStatus qs; struct GNUNET_TIME_Absolute now; + uint64_t coin_id; dkp = NULL; rh = NULL; @@ -1708,7 +1714,8 @@ run (void *cls) FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->ensure_coin_known (plugin->cls, session, - &deposit.coin)); + &deposit.coin, + &coin_id)); { struct TALER_EXCHANGEDB_Reserve pre_reserve; struct TALER_EXCHANGEDB_Reserve post_reserve; @@ -1723,7 +1730,7 @@ run (void *cls) plugin->insert_recoup_request (plugin->cls, session, &reserve_pub, - &deposit.coin, + coin_id, &coin_sig, &coin_blind, &value, @@ -1883,7 +1890,8 @@ run (void *cls) FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->ensure_coin_known (plugin->cls, session, - &deposit.coin)); + &deposit.coin, + &coin_id)); { struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute r; @@ -1895,10 +1903,12 @@ run (void *cls) plugin->insert_deposit (plugin->cls, session, now, + coin_id, &deposit)); FAILIF (1 != plugin->have_deposit (plugin->cls, session, + coin_id, &deposit, GNUNET_YES, &deposit_fee, @@ -1975,7 +1985,7 @@ run (void *cls) FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != plugin->test_deposit_done (plugin->cls, session, - &deposit.coin.coin_pub, + coin_id, &deposit.merchant_pub, &deposit.h_contract_terms, &deposit.h_wire)); @@ -1989,7 +1999,7 @@ run (void *cls) FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->test_deposit_done (plugin->cls, session, - &deposit.coin.coin_pub, + coin_id, &deposit.merchant_pub, &deposit.h_contract_terms, &deposit.h_wire)); @@ -2004,19 +2014,27 @@ run (void *cls) { struct GNUNET_TIME_Absolute r; struct TALER_Amount deposit_fee; + uint64_t coin_id2; FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != plugin->have_deposit (plugin->cls, session, + coin_id, &deposit2, GNUNET_YES, &deposit_fee, &r)); deposit2.merchant_pub = deposit.merchant_pub; RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */ + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->ensure_coin_known (plugin->cls, + session, + &deposit2.coin, + &coin_id2)); FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != plugin->have_deposit (plugin->cls, session, + coin_id2, &deposit2, GNUNET_YES, &deposit_fee, @@ -2042,11 +2060,12 @@ run (void *cls) FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->insert_refund (plugin->cls, session, + coin_id, &refund)); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->select_refunds_by_coin (plugin->cls, session, - &refund.coin.coin_pub, + coin_id, &refund.details.merchant_pub, &refund.details.h_contract_terms, &check_refund_cb, @@ -2102,7 +2121,7 @@ run (void *cls) plugin->insert_recoup_request (plugin->cls, session, &reserve_pub, - &deposit.coin, + coin_id, &coin_sig, &coin_blind, &value, @@ -2120,7 +2139,7 @@ run (void *cls) FAILIF (1 != auditor_row_cnt); qs = plugin->get_coin_transactions (plugin->cls, session, - &refund.coin.coin_pub, + coin_id, GNUNET_YES, &tl); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs); diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 9fb93236..c80e7e27 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -364,7 +364,12 @@ struct TALER_EXCHANGEDB_RecoupRefreshListEntry * Information about the coin that was paid back * (NOT the coin we are considering the history of!) */ - struct TALER_CoinPublicInfo coin; + struct TALER_CoinPublicInfo coin; // FIXME: check that where 'coin' is used, 'coin_id' likely also must be used! + + /** + * Unique ID of @e coin. + */ + uint64_t coin_id; /** * Blinding factor supplied to prove to the exchange that @@ -381,7 +386,12 @@ struct TALER_EXCHANGEDB_RecoupRefreshListEntry /** * Public key of the old coin that the refreshed coin was paid back to. */ - struct TALER_CoinSpendPublicKeyP old_coin_pub; + // struct TALER_CoinSpendPublicKeyP old_coin_pub; + + /** + * Unique ID of @e old_coin_pub. + */ + uint64_t old_coin_id; /** * How much was the coin still worth at this time? @@ -978,7 +988,7 @@ struct TALER_EXCHANGEDB_Session; * @param exchange_timestamp when did the exchange receive the deposit * @param wallet_timestamp when did the wallet sign the contract * @param merchant_pub public key of the merchant - * @param coin_pub public key of the coin + * @param coin_pub public key of the coin // FIXME: not unique! * @param amount_with_fee amount that was deposited including fee * @param deposit_fee amount the exchange gets to keep as transaction fees * @param h_contract_terms hash of the proposal data known to merchant and customer @@ -1029,7 +1039,7 @@ typedef void * @param exchange_timestamp when did the deposit happen * @param wallet_timestamp when did the contract happen * @param merchant_pub public key of the merchant - * @param denom_pub denomination public key of @a coin_pub + * @param denom_pub denomination public key of @a coin_pub // FIXME: not unique! * @param coin_pub public key of the coin * @param coin_sig signature from the coin * @param amount_with_fee amount that was deposited including fee @@ -1067,7 +1077,7 @@ typedef int * * @param cls closure * @param rowid unique serial ID for the refresh session in our DB - * @param denom_pub denomination public key of @a coin_pub + * @param denom_pub denomination public key of @a coin_pub // FIXME: not unique! * @param coin_pub public key of the coin * @param coin_sig signature from the coin * @param amount_with_fee amount that was deposited including fee @@ -1162,7 +1172,7 @@ typedef void * * @param cls closure * @param rowid unique serial ID for the refund in our DB - * @param denom_pub denomination public key of @a coin_pub + * @param denom_pub denomination public key of @a coin_pub // FIXME: not unique * @param coin_pub public key of the coin * @param merchant_pub public key of the merchant * @param merchant_sig signature of the merchant @@ -1281,7 +1291,7 @@ typedef void * @param account_details which account did the transfer go to? * @param exec_time execution time of the wire transfer (should be same for all callbacks with the same @e cls) * @param h_contract_terms which proposal was this payment about - * @param denom_pub denomination of @a coin_pub + * @param denom_pub denomination of @a coin_pub // FIXME: not unique! * @param coin_pub which public key was this payment about * @param coin_value amount contributed by this coin in total (with fee) * @param coin_fee applicable fee for this coin @@ -1351,7 +1361,7 @@ typedef int * @param timestamp when did we receive the recoup 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 public information about the coin // FIXME: unique??? * @param denom_pub denomination key of @a coin * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_RECOUP * @param coin_blind blinding factor used to blind the coin @@ -1378,7 +1388,7 @@ typedef int * @param rowid row identifier used to uniquely identify the recoup operation * @param timestamp when did we receive the recoup request * @param amount how much should be added back to the reserve - * @param old_coin_pub original coin that was refreshed to create @a coin + * @param old_coin_pub original coin that was refreshed to create @a coin // FIXME: not unique! * @param old_denom_pub_hash hash of public key of @a old_coin_pub * @param coin public information about the coin * @param denom_pub denomination key of @a coin @@ -1474,7 +1484,7 @@ typedef void * * @param cls closure * @param rowid deposit table row of the coin's deposit - * @param coin_pub public key of the coin + * @param coin_pub public key of the coin // FIXME: not unique! * @param amount value of the deposit, including fee * @param wire where should the funds be wired, including 'url' in payto://-format * @param deadline what was the requested wire transfer deadline @@ -1801,12 +1811,14 @@ struct TALER_EXCHANGEDB_Plugin * @param cls database connection plugin state * @param session database session * @param coin the coin that must be made known + * @param[out] known_coin_id set to identifier of the coin in the database * @return database transaction status, non-negative on success */ enum GNUNET_DB_QueryStatus (*ensure_coin_known)(void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinPublicInfo *coin); + const struct TALER_CoinPublicInfo *coin, + uint64_t *known_coin_id); /** @@ -1814,30 +1826,17 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls database connection plugin state * @param session database session - * @param coin the coin that must be made known - * @return database transaction status, non-negative on success - */ - enum GNUNET_DB_QueryStatus - (*get_known_coin)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_CoinPublicInfo *coin_info); - - - /** - * Retrieve the denomination of a known coin. - * - * @param cls the plugin closure - * @param session the database session handle * @param coin_pub the public key of the coin to search for - * @param[out] denom_hash where to store the hash of the coins denomination - * @return transaction status code + * @param denom_pub_hash hash of the denomination of the coin + * @param[out] known_coin_id identifier of the coin in the database + * @return database transaction status, non-negative on success */ enum GNUNET_DB_QueryStatus - (*get_coin_denomination)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct GNUNET_HashCode *denom_hash); + (*check_known_coin)(void *cls, + struct TALER_EXCHANGEDB_Session *session, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct GNUNET_HashCode *denom_pub_hash, + uint64_t *known_coin_id); /** @@ -1845,6 +1844,7 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param session database connection + * @param coin_id which coin is this about * @param deposit deposit to search for * @param check_extras whether to check extra fields or not * @param[out] deposit_fee set to the deposit fee the exchange charged @@ -1856,6 +1856,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*have_deposit)(void *cls, struct TALER_EXCHANGEDB_Session *session, + uint64_t coin_id, const struct TALER_EXCHANGEDB_Deposit *deposit, int check_extras, struct TALER_Amount *deposit_fee, @@ -1868,6 +1869,7 @@ struct TALER_EXCHANGEDB_Plugin * @param cls the @e cls of this struct with the plugin-specific state * @param session connection to the database * @param exchange_timestamp time the exchange received the deposit request + * @param coin_id which coin is this about * @param deposit deposit information to store * @return query result status */ @@ -1875,6 +1877,7 @@ struct TALER_EXCHANGEDB_Plugin (*insert_deposit)(void *cls, struct TALER_EXCHANGEDB_Session *session, struct GNUNET_TIME_Absolute exchange_timestamp, + uint64_t coin_id, const struct TALER_EXCHANGEDB_Deposit *deposit); @@ -1883,21 +1886,23 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param session connection to the database + * @param coin_id which coin is this about * @param refund refund information to store * @return query result status */ enum GNUNET_DB_QueryStatus (*insert_refund)(void *cls, struct TALER_EXCHANGEDB_Session *session, + uint64_t coin_id, const struct TALER_EXCHANGEDB_Refund *refund); /** - * Select refunds by @a coin_pub, @a merchant_pub and @a h_contract. + * Select refunds by @a coin_id, @a merchant_pub and @a h_contract. * * @param cls closure of plugin * @param session database handle to use - * @param coin_pub coin to get refunds for + * @param coin_id coin to get refunds for * @param merchant_pub merchant to get refunds for * @param h_contract_pub contract (hash) to get refunds for * @param cb function to call for each refund found @@ -1907,7 +1912,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*select_refunds_by_coin)(void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t coin_id, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct GNUNET_HashCode *h_contract, TALER_EXCHANGEDB_RefundCoinCallback cb, @@ -1936,7 +1941,7 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param session connection to the database - * @param coin_pub the coin to check for deposit + * @param coin_id the coin to check for deposit * @param merchant_pub merchant to receive the deposit * @param h_contract_terms contract terms of the deposit * @param h_wire hash of the merchant's wire details @@ -1947,7 +1952,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*test_deposit_done)(void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t coin_id, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct GNUNET_HashCode *h_contract_terms, const struct GNUNET_HashCode *h_wire); @@ -2029,12 +2034,14 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param session database handle to use + * @param coin_id which coin is the melt about * @param refresh_session operational data to store * @return query status for the transaction */ enum GNUNET_DB_QueryStatus (*insert_melt)(void *cls, struct TALER_EXCHANGEDB_Session *session, + uint64_t coin_id, const struct TALER_EXCHANGEDB_Refresh *refresh_session); @@ -2127,9 +2134,13 @@ struct TALER_EXCHANGEDB_Plugin * @e get_link_data_list() enable the owner of an old coin to determine * the private keys of the new coins after the melt. * + * Note that if multiple coins (of different denominations) share the + * same @a coin_pub, we simply return the link data associated with any of + * the coins. + * * @param cls the @e cls of this struct with the plugin-specific state * @param session database connection - * @param coin_pub public key of the coin + * @param coin_pub public key of the coin(s). * @param ldc function to call for each session the coin was melted into * @param ldc_cls closure for @a tdc * @return statement execution status @@ -2148,7 +2159,7 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param session database connection - * @param coin_pub coin to investigate + * @param known_coin_id which coin to investigate * @param include_recoup include recoup transactions of the coin? * @param[out] tlp set to list of transactions, NULL if coin is fresh * @return database transaction status @@ -2156,7 +2167,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*get_coin_transactions)(void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, int include_recoup, struct TALER_EXCHANGEDB_TransactionList **tlp); @@ -2196,6 +2207,9 @@ struct TALER_EXCHANGEDB_Plugin * If we did not execute the deposit yet, return when it is supposed * to be executed. * + * FIXME: check it is OK to do this by coin_pub (merging results + * from all coins with different denominations sharing the same coin_pub). + * * @param cls closure * @param session database connection * @param h_contract_terms hash of the proposal data @@ -2652,7 +2666,7 @@ struct TALER_EXCHANGEDB_Plugin * @param cls closure * @param session database connection * @param reserve_pub public key of the reserve that is being refunded - * @param coin public information about a coin + * @param coin_id unique identifier of the recouped coin * @param coin_sig signature of the coin of type #TALER_SIGNATURE_WALLET_COIN_RECOUP * @param coin_blind blinding key of the coin * @param h_blind_ev blinded envelope, as calculated by the exchange @@ -2666,7 +2680,7 @@ struct TALER_EXCHANGEDB_Plugin void *cls, struct TALER_EXCHANGEDB_Session *session, const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_CoinPublicInfo *coin, + uint64_t coin_id, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_DenominationBlindingKeyP *coin_blind, const struct TALER_Amount *amount, @@ -2680,7 +2694,7 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls closure * @param session database connection - * @param coin public information about the refreshed coin + * @param coin_id unique identifier of the recoup-refreshed coin * @param coin_sig signature of the coin of type #TALER_SIGNATURE_WALLET_COIN_RECOUP * @param coin_blind blinding key of the coin * @param h_blind_ev blinded envelope, as calculated by the exchange @@ -2693,7 +2707,7 @@ struct TALER_EXCHANGEDB_Plugin (*insert_recoup_refresh_request)( void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinPublicInfo *coin, + uint64_t coin_id, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_DenominationBlindingKeyP *coin_blind, const struct TALER_Amount *amount, @@ -2728,6 +2742,7 @@ struct TALER_EXCHANGEDB_Plugin * @param[out] old_coin_pub set to information about the old coin (on success only) * @return transaction status code */ + // FIXME: check use, likely bad: may need to return old_coin_id! enum GNUNET_DB_QueryStatus (*get_old_coin_by_h_blind)(void *cls, struct TALER_EXCHANGEDB_Session *session,