diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-02-17 15:10:14 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-02-17 15:18:09 +0100 |
commit | a351bfc4b4ca15ce7fd998cf9691e85cf84dc426 (patch) | |
tree | 88ec3b739914739f05d4c8cae2a2af40d29ebf82 /src/exchangedb | |
parent | 8bdf6ab19df70c16d335ecf82f2c3b2117eeb70e (diff) | |
download | exchange-a351bfc4b4ca15ce7fd998cf9691e85cf84dc426.tar.xz |
-fix CS nonce reuse check logic
Diffstat (limited to 'src/exchangedb')
-rw-r--r-- | src/exchangedb/exchange-0001.sql | 166 | ||||
-rw-r--r-- | src/exchangedb/irbt_callbacks.c | 8 | ||||
-rw-r--r-- | src/exchangedb/lrbt_callbacks.c | 8 | ||||
-rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 158 | ||||
-rw-r--r-- | src/exchangedb/test_exchangedb.c | 80 |
5 files changed, 231 insertions, 189 deletions
diff --git a/src/exchangedb/exchange-0001.sql b/src/exchangedb/exchange-0001.sql index df07e0252..fdc47b7c9 100644 --- a/src/exchangedb/exchange-0001.sql +++ b/src/exchangedb/exchange-0001.sql @@ -1,6 +1,6 @@ -- -- This file is part of TALER --- Copyright (C) 2014--2021 Taler Systems SA +-- 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 @@ -25,7 +25,7 @@ CREATE TABLE IF NOT EXISTS denominations (denominations_serial BIGSERIAL UNIQUE ,denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64) ,denom_type INT4 NOT NULL DEFAULT (1) -- 1 == RSA (for now, remove default later!) - ,age_mask INT4 NOT NULL DEFAULT (0) + ,age_restrictions INT4 NOT NULL DEFAULT (0) ,denom_pub BYTEA NOT NULL ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64) ,valid_from INT8 NOT NULL @@ -196,7 +196,6 @@ CREATE INDEX IF NOT EXISTS reserves_close_by_reserve_pub_index CREATE TABLE IF NOT EXISTS reserves_out (reserve_out_serial_id BIGSERIAL -- UNIQUE - ,wih BYTEA PRIMARY KEY CHECK (LENGTH(wih)=64) ,h_blind_ev BYTEA CHECK (LENGTH(h_blind_ev)=64) -- UNIQUE ,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ,denom_sig BYTEA NOT NULL @@ -206,11 +205,9 @@ CREATE TABLE IF NOT EXISTS reserves_out ,amount_with_fee_val INT8 NOT NULL ,amount_with_fee_frac INT4 NOT NULL ) - PARTITION BY HASH (wih); + PARTITION BY HASH (h_blind_ev); COMMENT ON TABLE reserves_out IS 'Withdraw operations performed on reserves.'; -COMMENT ON COLUMN reserves_out.wih - IS 'Hash that uniquely identifies the withdraw request. Used to detect request replays (crucial for CS) and to check the withdraw existed during recoup.'; COMMENT ON COLUMN reserves_out.h_blind_ev IS 'Hash of the blinded coin, used as primary key here so that broken clients that use a non-random coin or blinding factor fail to withdraw (otherwise they would fail on deposit when the coin is not unique there).'; COMMENT ON COLUMN reserves_out.denominations_serial @@ -643,7 +640,7 @@ COMMENT ON TABLE recoup COMMENT ON COLUMN recoup.known_coin_id IS 'Coin that is being debited in the recoup. Do not CASCADE ON DROP on the coin_pub, as we may keep the coin alive!'; COMMENT ON COLUMN recoup.reserve_out_serial_id - IS 'Identifies the wih of the recouped coin and provides the link to the credited reserve.'; + IS 'Identifies the h_blind_ev of the recouped coin and provides the link to the credited reserve.'; COMMENT ON COLUMN recoup.coin_sig IS 'Signature by the coin affirming the recoup, of type TALER_SIGNATURE_WALLET_COIN_RECOUP'; COMMENT ON COLUMN recoup.coin_blind @@ -750,6 +747,23 @@ COMMENT ON COLUMN wire_accounts.last_change -- and is of no concern to the auditor +CREATE TABLE IF NOT EXISTS cs_nonce_locks + (cs_nonce_lock_serial_id BIGSERIAL -- UNIQUE + ,nonce BYTEA PRIMARY KEY CHECK (LENGTH(nonce)=32) + ,op_hash BYTEA NOT NULL CHECK (LENGTH(op_hash)=64) + ,max_denomination_serial INT8 NOT NULL + ) + PARTITION BY HASH (nonce); +COMMENT ON TABLE cs_nonce_locks + IS 'ensures a Clause Schnorr client nonce is locked for use with an operation identified by a hash'; +COMMENT ON COLUMN cs_nonce_locks.nonce + IS 'actual nonce submitted by the client'; +COMMENT ON COLUMN cs_nonce_locks.op_hash + IS 'hash (RC for refresh, blind coin hash for withdraw) the nonce may be used with'; +COMMENT ON COLUMN cs_nonce_locks.max_denomination_serial + IS 'Maximum number of a CS denomination serial the nonce could be used with, for GC'; + + CREATE TABLE IF NOT EXISTS work_shards (shard_serial_id BIGSERIAL UNIQUE ,last_attempt INT8 NOT NULL @@ -818,7 +832,7 @@ CREATE INDEX IF NOT EXISTS revolving_work_shards_by_job_name_active_last_attempt CREATE OR REPLACE FUNCTION exchange_do_withdraw( - IN in_wih BYTEA, + IN cs_nonce BYTEA, IN amount_val INT8, IN amount_frac INT4, IN h_denom_pub BYTEA, @@ -832,8 +846,7 @@ CREATE OR REPLACE FUNCTION exchange_do_withdraw( OUT balance_ok BOOLEAN, OUT kycok BOOLEAN, OUT account_uuid INT8, - OUT ruuid INT8, - OUT out_denom_sig BYTEA) + OUT ruuid INT8) LANGUAGE plpgsql AS $$ DECLARE @@ -851,7 +864,8 @@ BEGIN -- reserves_in by reserve_pub (SELECT) -- wire_targets by wire_target_serial_id -SELECT denominations_serial INTO denom_serial +SELECT denominations_serial + INTO denom_serial FROM denominations WHERE denom_pub_hash=h_denom_pub; @@ -867,6 +881,7 @@ THEN RETURN; END IF; + SELECT current_balance_val ,current_balance_frac @@ -887,7 +902,7 @@ THEN balance_ok=FALSE; kycok=FALSE; account_uuid=0; - ruuid=0; + ruuid=2; RETURN; END IF; @@ -895,7 +910,6 @@ END IF; -- the query successful due to idempotency. INSERT INTO reserves_out (h_blind_ev - ,wih ,denominations_serial ,denom_sig ,reserve_uuid @@ -905,7 +919,6 @@ INSERT INTO reserves_out ,amount_with_fee_frac) VALUES (h_coin_envelope - ,in_wih ,denom_serial ,denom_sig ,ruuid @@ -918,25 +931,6 @@ ON CONFLICT DO NOTHING; IF NOT FOUND THEN -- idempotent query, all constraints must be satisfied - - SELECT - denom_sig - INTO - out_denom_sig - FROM reserves_in - WHERE wih=in_wih - LIMIT 1; -- limit 1 should not be required (without p2p transfers) - - IF NOT FOUND - THEN - reserve_found=FALSE; - balance_ok=FALSE; - kycok=FALSE; - account_uuid=0; - ruuid=0; - ASSERT false, 'internal logic error'; - END IF; - reserve_found=TRUE; balance_ok=TRUE; kycok=TRUE; @@ -983,6 +977,44 @@ WHERE reserve_found=TRUE; balance_ok=TRUE; + + +-- Special actions needed for a CS withdraw? +IF NOT NULL cs_nonce +THEN + -- Cache CS signature to prevent replays in the future + -- (and check if cached signature exists at the same time). + INSERT INTO cs_nonce_locks + (nonce + ,max_denomination_serial + ,op_hash) + VALUES + (cs_nonce + ,denom_serial + ,h_coin_envelope) + ON CONFLICT DO NOTHING; + + IF NOT FOUND + THEN + -- See if the existing entry is identical. + SELECT 1 + FROM cs_nonce_locks + WHERE nonce=cs_nonce + AND op_hash=h_coin_envelope; + IF NOT FOUND + THEN + reserve_found=FALSE; + balance_ok=FALSE; + kycok=FALSE; + account_uuid=0; + ruuid=1; -- FIXME: return error message more nicely! + ASSERT false, 'nonce reuse attempted by client'; + END IF; + END IF; +END IF; + + + -- Obtain KYC status based on the last wire transfer into -- this reserve. FIXME: likely not adequate for reserves that got P2P transfers! SELECT @@ -996,9 +1028,6 @@ SELECT WHERE reserve_pub=rpub LIMIT 1; -- limit 1 should not be required (without p2p transfers) --- Return denomination signature as result that --- was given as the argument. -out_denom_sig=denom_sig; END $$; @@ -1223,6 +1252,7 @@ END $$; CREATE OR REPLACE FUNCTION exchange_do_melt( + IN in_cs_rms BYTEA, IN in_amount_with_fee_val INT8, IN in_amount_with_fee_frac INT4, IN in_rc BYTEA, @@ -1236,6 +1266,8 @@ CREATE OR REPLACE FUNCTION exchange_do_melt( OUT out_noreveal_index INT4) LANGUAGE plpgsql AS $$ +DECLARE + denom_max INT8; BEGIN -- Shards: INSERT refresh_commitments (by rc) -- (rare:) SELECT refresh_commitments (by old_coin_pub) -- crosses shards! @@ -1333,6 +1365,56 @@ THEN RETURN; END IF; + + +-- Special actions needed for a CS melt? +IF NOT NULL in_cs_rms +THEN + -- Get maximum denominations serial value in + -- existence, this will determine how long the + -- nonce will be locked. + SELECT + denominations_serial + INTO + denom_max + FROM denominations + ORDER BY denominations_serial DESC + LIMIT 1; + + -- Cache CS signature to prevent replays in the future + -- (and check if cached signature exists at the same time). + INSERT INTO cs_nonce_locks + (nonce + ,max_denomination_serial + ,op_hash) + VALUES + (cs_rms + ,denom_serial + ,in_rc) + ON CONFLICT DO NOTHING; + + IF NOT FOUND + THEN + -- Record exists, make sure it is the same + SELECT 1 + FROM cs_nonce_locks + WHERE nonce=cs_rms + AND op_hash=in_rc; + + IF NOT FOUND + THEN + -- Nonce reuse detected + out_balance_ok=FALSE; + out_zombie_bad=FALSE; + out_noreveal_index=42; -- FIXME: return error message more nicely! + ASSERT false, 'nonce reuse attempted by client'; + END IF; + END IF; +END IF; + + + + -- Everything fine, return success! out_balance_ok=TRUE; out_noreveal_index=in_noreveal_index; @@ -1806,6 +1888,8 @@ DECLARE deposit_min INT8; -- minimum deposit still alive DECLARE reserve_out_min INT8; -- minimum reserve_out still alive +DECLARE + denom_min INT8; -- minimum denomination still alive BEGIN DELETE FROM prewire @@ -1901,6 +1985,16 @@ DELETE FROM refunds DELETE FROM aggregation_tracking WHERE deposit_serial_id < deposit_min; +SELECT + denominations_serial + INTO + denom_min + FROM denominations + ORDER BY denominations_serial ASC + LIMIT 1; + +DELETE FROM cs_nonce_locks + WHERE max_denomination_serial <= denom_min; END $$; diff --git a/src/exchangedb/irbt_callbacks.c b/src/exchangedb/irbt_callbacks.c index cb0685ba6..8cc4e2370 100644 --- a/src/exchangedb/irbt_callbacks.c +++ b/src/exchangedb/irbt_callbacks.c @@ -53,13 +53,13 @@ irbt_cb_table_denominations (struct PostgresClosure *pg, &td->details.denominations.expire_legal), TALER_PQ_query_param_amount (&td->details.denominations.coin), TALER_PQ_query_param_amount ( - &td->details.denominations.fee_withdraw), + &td->details.denominations.fees.withdraw), TALER_PQ_query_param_amount ( - &td->details.denominations.fee_deposit), + &td->details.denominations.fees.deposit), TALER_PQ_query_param_amount ( - &td->details.denominations.fee_refresh), + &td->details.denominations.fees.refresh), TALER_PQ_query_param_amount ( - &td->details.denominations.fee_refund), + &td->details.denominations.fees.refund), GNUNET_PQ_query_param_end }; diff --git a/src/exchangedb/lrbt_callbacks.c b/src/exchangedb/lrbt_callbacks.c index dd7852131..a14c212d1 100644 --- a/src/exchangedb/lrbt_callbacks.c +++ b/src/exchangedb/lrbt_callbacks.c @@ -80,16 +80,16 @@ lrbt_cb_table_denominations (void *cls, &td.details.denominations.coin), TALER_PQ_RESULT_SPEC_AMOUNT ( "fee_withdraw", - &td.details.denominations.fee_withdraw), + &td.details.denominations.fees.withdraw), TALER_PQ_RESULT_SPEC_AMOUNT ( "fee_deposit", - &td.details.denominations.fee_deposit), + &td.details.denominations.fees.deposit), TALER_PQ_RESULT_SPEC_AMOUNT ( "fee_refresh", - &td.details.denominations.fee_refresh), + &td.details.denominations.fees.refresh), TALER_PQ_RESULT_SPEC_AMOUNT ( "fee_refund", - &td.details.denominations.fee_refund), + &td.details.denominations.fees.refund), GNUNET_PQ_result_spec_end }; diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 878c36f96..5d8db5ce7 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014--2021 Taler Systems SA + 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 @@ -579,7 +579,6 @@ prepare_statements (struct PostgresClosure *pg) ",kycok AS kyc_ok" ",account_uuid AS payment_target_uuid" ",ruuid" - ",out_denom_sig" " FROM exchange_do_withdraw" " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);", 10), @@ -612,8 +611,8 @@ prepare_statements (struct PostgresClosure *pg) ",out_zombie_bad AS zombie_required" ",out_noreveal_index AS noreveal_index" " FROM exchange_do_melt" - " ($1,$2,$3,$4,$5,$6,$7,$8);", - 8), + " ($1,$2,$3,$4,$5,$6,$7,$8,$9);", + 9), /* Used in #postgres_do_refund() to refund a deposit. */ GNUNET_PQ_make_prepare ( "call_refund", @@ -667,7 +666,7 @@ prepare_statements (struct PostgresClosure *pg) " USING (reserve_uuid)" " JOIN denominations denom" " USING (denominations_serial)" - " WHERE wih=$1;", + " WHERE h_blind_ev=$1;", 1), /* Used during #postgres_get_reserve_history() to obtain all of the /reserve/withdraw operations that @@ -1672,16 +1671,16 @@ prepare_statements (struct PostgresClosure *pg) " ON (denoms.denominations_serial = coins.denominations_serial)" " WHERE coins.coin_pub=$1;", 1), - /* Used in #postgres_get_reserve_by_wih() */ + /* Used in #postgres_get_reserve_by_h_blind() */ GNUNET_PQ_make_prepare ( - "reserve_by_wih", + "reserve_by_h_blind", "SELECT" " reserves.reserve_pub" ",reserve_out_serial_id" " FROM reserves_out" " JOIN reserves" " USING (reserve_uuid)" - " WHERE wih=$1" + " WHERE h_blind_ev=$1" " LIMIT 1;", 1), /* Used in #postgres_get_old_coin_by_h_blind() */ @@ -3100,13 +3099,13 @@ postgres_insert_denomination_info ( GNUNET_PQ_query_param_timestamp_nbo (&issue->properties.expire_deposit), GNUNET_PQ_query_param_timestamp_nbo (&issue->properties.expire_legal), TALER_PQ_query_param_amount_nbo (&issue->properties.value), - TALER_PQ_query_param_amount_nbo (&issue->properties.fee_withdraw), - TALER_PQ_query_param_amount_nbo (&issue->properties.fee_deposit), - TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refresh), - TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refund), - GNUNET_PQ_query_param_uint32 (&denom_pub->age_mask.mask), + TALER_PQ_query_param_amount_nbo (&issue->properties.fees.withdraw), + TALER_PQ_query_param_amount_nbo (&issue->properties.fees.deposit), + TALER_PQ_query_param_amount_nbo (&issue->properties.fees.refresh), + TALER_PQ_query_param_amount_nbo (&issue->properties.fees.refund), GNUNET_PQ_query_param_end }; + struct TALER_DenomFeeSet fees; GNUNET_assert (denom_pub->age_mask.mask == issue->age_mask.mask); @@ -3122,20 +3121,13 @@ postgres_insert_denomination_info ( GNUNET_assert (! GNUNET_TIME_absolute_is_zero ( GNUNET_TIME_timestamp_ntoh ( issue->properties.expire_legal).abs_time)); - /* check fees match coin currency */ - GNUNET_assert (GNUNET_YES == - TALER_amount_cmp_currency_nbo (&issue->properties.value, - &issue->properties.fee_withdraw)); + /* check fees match denomination currency */ + TALER_denom_fee_set_ntoh (&fees, + &issue->properties.fees); GNUNET_assert (GNUNET_YES == - TALER_amount_cmp_currency_nbo (&issue->properties.value, - &issue->properties.fee_deposit)); - GNUNET_assert (GNUNET_YES == - TALER_amount_cmp_currency_nbo (&issue->properties.value, - &issue->properties.fee_refresh)); - GNUNET_assert (GNUNET_YES == - TALER_amount_cmp_currency_nbo (&issue->properties.value, - &issue->properties.fee_refund)); - + TALER_denom_fee_check_currency ( + issue->properties.value.currency, + &fees)); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "denomination_insert", params); @@ -3176,13 +3168,13 @@ postgres_get_denomination_info ( TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("coin", &issue->properties.value), TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_withdraw", - &issue->properties.fee_withdraw), + &issue->properties.fees.withdraw), TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_deposit", - &issue->properties.fee_deposit), + &issue->properties.fees.deposit), TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refresh", - &issue->properties.fee_refresh), + &issue->properties.fees.refresh), TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund", - &issue->properties.fee_refund), + &issue->properties.fees.refund), GNUNET_PQ_result_spec_uint32 ("age_mask", &issue->age_mask.mask), GNUNET_PQ_result_spec_end @@ -3262,13 +3254,13 @@ domination_cb_helper (void *cls, TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("coin", &issue.properties.value), TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_withdraw", - &issue.properties.fee_withdraw), + &issue.properties.fees.withdraw), TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_deposit", - &issue.properties.fee_deposit), + &issue.properties.fees.deposit), TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refresh", - &issue.properties.fee_refresh), + &issue.properties.fees.refresh), TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund", - &issue.properties.fee_refund), + &issue.properties.fees.refund), TALER_PQ_result_spec_denom_pub ("denom_pub", &denom_pub), GNUNET_PQ_result_spec_uint32 ("age_mask", @@ -3401,13 +3393,13 @@ dominations_cb_helper (void *cls, TALER_PQ_RESULT_SPEC_AMOUNT ("coin", &meta.value), TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", - &meta.fee_withdraw), + &meta.fees.withdraw), TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &meta.fee_deposit), + &meta.fees.deposit), TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", - &meta.fee_refresh), + &meta.fees.refresh), TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", - &meta.fee_refund), + &meta.fees.refund), TALER_PQ_result_spec_denom_pub ("denom_pub", &denom_pub), GNUNET_PQ_result_spec_uint32 ("age_mask", @@ -4328,7 +4320,7 @@ postgres_reserves_in_insert (void *cls, * key of the hash of the blinded message. * * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param wih hash that uniquely identifies the withdraw operation + * @param bch hash that uniquely identifies the withdraw operation * @param collectable corresponding collectable coin (blind signature) * if a coin is found * @return statement execution status @@ -4336,12 +4328,12 @@ postgres_reserves_in_insert (void *cls, static enum GNUNET_DB_QueryStatus postgres_get_withdraw_info ( void *cls, - const struct TALER_WithdrawIdentificationHash *wih, + const struct TALER_BlindedCoinHash *bch, struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (wih), + GNUNET_PQ_query_param_auto_from_type (bch), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { @@ -4374,7 +4366,7 @@ postgres_get_withdraw_info ( * and possibly persisting the withdrawal details. * * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param wih hash that uniquely identifies the withdraw operation + * @param nonce client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals * @param[in,out] collectable corresponding collectable coin (blind signature) if a coin is found; possibly updated if a (different) signature exists already * @param now current time (rounded) * @param[out] found set to true if the reserve was found @@ -4386,8 +4378,8 @@ postgres_get_withdraw_info ( static enum GNUNET_DB_QueryStatus postgres_do_withdraw ( void *cls, - const struct TALER_WithdrawIdentificationHash *wih, - struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable, + const struct TALER_CsNonce *nonce, + const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable, struct GNUNET_TIME_Timestamp now, bool *found, bool *balance_ok, @@ -4397,7 +4389,9 @@ postgres_do_withdraw ( struct PostgresClosure *pg = cls; struct GNUNET_TIME_Timestamp gc; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (wih), + NULL == nonce + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (nonce), TALER_PQ_query_param_amount (&collectable->amount_with_fee), GNUNET_PQ_query_param_auto_from_type (&collectable->denom_pub_hash), GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_pub), @@ -4408,9 +4402,6 @@ postgres_do_withdraw ( GNUNET_PQ_query_param_timestamp (&gc), GNUNET_PQ_query_param_end }; - enum GNUNET_DB_QueryStatus qs; - bool no_out_sig; - struct TALER_BlindedDenominationSignature out_sig; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_bool ("reserve_found", found), @@ -4422,33 +4413,17 @@ postgres_do_withdraw ( &kyc->payment_target_uuid), GNUNET_PQ_result_spec_uint64 ("ruuid", ruuid), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_blinded_denom_sig ("out_denom_sig", - &out_sig), - &no_out_sig), GNUNET_PQ_result_spec_end }; -#if 0 - memset (&out_sig, - 0, - sizeof (out_sig)); -#endif gc = GNUNET_TIME_absolute_to_timestamp ( GNUNET_TIME_absolute_add (now.abs_time, pg->legal_reserve_expiration_time)); kyc->type = TALER_EXCHANGEDB_KYC_WITHDRAW; - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_withdraw", - params, - rs); - if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) && - (! no_out_sig) ) - { - TALER_blinded_denom_sig_free (&collectable->sig); - collectable->sig = out_sig; - } - return qs; + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_withdraw", + params, + rs); } @@ -4600,6 +4575,7 @@ postgres_do_deposit ( static enum GNUNET_DB_QueryStatus postgres_do_melt ( void *cls, + const struct TALER_RefreshMasterSecretP *rms, struct TALER_EXCHANGEDB_Refresh *refresh, uint64_t known_coin_id, bool *zombie_required, @@ -4607,6 +4583,9 @@ postgres_do_melt ( { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { + NULL == rms + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (rms), TALER_PQ_query_param_amount (&refresh->amount_with_fee), GNUNET_PQ_query_param_auto_from_type (&refresh->rc), GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub), @@ -9428,21 +9407,21 @@ postgres_select_reserve_closed_above_serial_id ( * from given the hash of the blinded coin. * * @param cls closure - * @param wih hash that uniquely identifies the withdraw request + * @param bch hash that uniquely identifies the withdraw request * @param[out] reserve_pub set to information about the reserve (on success only) * @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in reserves_out * @return transaction status code */ static enum GNUNET_DB_QueryStatus -postgres_get_reserve_by_wih ( +postgres_get_reserve_by_h_blind ( void *cls, - const struct TALER_WithdrawIdentificationHash *wih, + const struct TALER_BlindedCoinHash *bch, struct TALER_ReservePublicKeyP *reserve_pub, uint64_t *reserve_out_serial_id) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (wih), + GNUNET_PQ_query_param_auto_from_type (bch), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { @@ -9454,7 +9433,7 @@ postgres_get_reserve_by_wih ( }; return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "reserve_by_wih", + "reserve_by_h_blind", params, rs); } @@ -10241,13 +10220,13 @@ postgres_lookup_denomination_key ( TALER_PQ_RESULT_SPEC_AMOUNT ("coin", &meta->value), TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", - &meta->fee_withdraw), + &meta->fees.withdraw), TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &meta->fee_deposit), + &meta->fees.deposit), TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", - &meta->fee_refresh), + &meta->fees.refresh), TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", - &meta->fee_refund), + &meta->fees.refund), GNUNET_PQ_result_spec_uint32 ("age_mask", &meta->age_mask.mask), GNUNET_PQ_result_spec_end @@ -10289,27 +10268,18 @@ postgres_add_denomination_key ( GNUNET_PQ_query_param_timestamp (&meta->expire_deposit), GNUNET_PQ_query_param_timestamp (&meta->expire_legal), TALER_PQ_query_param_amount (&meta->value), - TALER_PQ_query_param_amount (&meta->fee_withdraw), - TALER_PQ_query_param_amount (&meta->fee_deposit), - TALER_PQ_query_param_amount (&meta->fee_refresh), - TALER_PQ_query_param_amount (&meta->fee_refund), + TALER_PQ_query_param_amount (&meta->fees.withdraw), + TALER_PQ_query_param_amount (&meta->fees.deposit), + TALER_PQ_query_param_amount (&meta->fees.refresh), + TALER_PQ_query_param_amount (&meta->fees.refund), GNUNET_PQ_query_param_uint32 (&meta->age_mask.mask), GNUNET_PQ_query_param_end }; /* Sanity check: ensure fees match coin currency */ GNUNET_assert (GNUNET_YES == - TALER_amount_cmp_currency (&meta->value, - &meta->fee_withdraw)); - GNUNET_assert (GNUNET_YES == - TALER_amount_cmp_currency (&meta->value, - &meta->fee_deposit)); - GNUNET_assert (GNUNET_YES == - TALER_amount_cmp_currency (&meta->value, - &meta->fee_refresh)); - GNUNET_assert (GNUNET_YES == - TALER_amount_cmp_currency (&meta->value, - &meta->fee_refund)); + TALER_denom_fee_check_currency (meta->value.currency, + &meta->fees)); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "denomination_insert", iparams); @@ -11722,8 +11692,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) = &postgres_select_recoup_refresh_above_serial_id; plugin->select_reserve_closed_above_serial_id = &postgres_select_reserve_closed_above_serial_id; - plugin->get_reserve_by_wih - = &postgres_get_reserve_by_wih; + plugin->get_reserve_by_h_blind + = &postgres_get_reserve_by_h_blind; plugin->get_old_coin_by_h_blind = &postgres_get_old_coin_by_h_blind; plugin->insert_denomination_revocation diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index f9e64fdc1..807407145 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -263,20 +263,14 @@ destroy_denom_key_pair (struct DenomKeyPair *dkp) * * @param size the size of the denomination key * @param now time to use for key generation, legal expiration will be 3h later. - * @param fee_withdraw withdraw fee to use - * @param fee_deposit deposit fee to use - * @param fee_refresh refresh fee to use - * @param fee_refund refund fee to use + * @param fees fees to use * @return the denominaiton key pair; NULL upon error */ static struct DenomKeyPair * create_denom_key_pair (unsigned int size, struct GNUNET_TIME_Timestamp now, const struct TALER_Amount *value, - const struct TALER_Amount *fee_withdraw, - const struct TALER_Amount *fee_deposit, - const struct TALER_Amount *fee_refresh, - const struct TALER_Amount *fee_refund) + const struct TALER_DenomFeeSet *fees) { struct DenomKeyPair *dkp; struct TALER_EXCHANGEDB_DenominationKey dki; @@ -315,11 +309,10 @@ create_denom_key_pair (unsigned int size, (now.abs_time, GNUNET_TIME_relative_multiply ( GNUNET_TIME_UNIT_HOURS, 3)))); - TALER_amount_hton (&dki.issue.properties.value, value); - TALER_amount_hton (&dki.issue.properties.fee_withdraw, fee_withdraw); - TALER_amount_hton (&dki.issue.properties.fee_deposit, fee_deposit); - TALER_amount_hton (&dki.issue.properties.fee_refresh, fee_refresh); - TALER_amount_hton (&dki.issue.properties.fee_refund, fee_refund); + TALER_amount_hton (&dki.issue.properties.value, + value); + TALER_denom_fee_set_hton (&dki.issue.properties.fees, + fees); TALER_denom_pub_hash (&dkp->pub, &dki.issue.properties.denom_hash); @@ -359,10 +352,7 @@ create_denom_key_pair (unsigned int size, static struct TALER_Amount value; -static struct TALER_Amount fee_withdraw; -static struct TALER_Amount fee_deposit; -static struct TALER_Amount fee_refresh; -static struct TALER_Amount fee_refund; +static struct TALER_DenomFeeSet fees; static struct TALER_Amount fee_closing; static struct TALER_Amount amount_with_fee; @@ -881,10 +871,7 @@ test_gc (void) dkp = create_denom_key_pair (RSA_KEY_SIZE, past, &value, - &fee_withdraw, - &fee_deposit, - &fee_refresh, - &fee_refund); + &fees); GNUNET_assert (NULL != dkp); if (GNUNET_OK != plugin->gc (plugin->cls)) @@ -1080,7 +1067,7 @@ test_wire_out (const struct TALER_EXCHANGEDB_Deposit *deposit) coin_pub_wt = deposit->coin.coin_pub; coin_value_wt = deposit->amount_with_fee; - coin_fee_wt = fee_deposit; + coin_fee_wt = fees.deposit; GNUNET_assert (0 < TALER_amount_subtract (&transfer_value_wt, &coin_value_wt, @@ -1349,7 +1336,6 @@ run (void *cls) struct GNUNET_TIME_Timestamp now; struct TALER_WireSaltP salt; struct TALER_CoinPubHash c_hash; - struct TALER_WithdrawIdentificationHash wih; uint64_t known_coin_id; uint64_t rrc_serial; struct TALER_EXCHANGEDB_Refresh refresh; @@ -1410,17 +1396,17 @@ run (void *cls) &value)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":0.000010", - &fee_withdraw)); + &fees.withdraw)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":0.000010", - &fee_deposit)); - deposit.deposit_fee = fee_deposit; + &fees.deposit)); + deposit.deposit_fee = fees.deposit; GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":0.000010", - &fee_refresh)); + &fees.refresh)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":0.000010", - &fee_refund)); + &fees.refund)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":1.000010", &amount_with_fee)); @@ -1464,10 +1450,7 @@ run (void *cls) dkp = create_denom_key_pair (RSA_KEY_SIZE, now, &value, - &fee_withdraw, - &fee_deposit, - &fee_refresh, - &fee_refund); + &fees); GNUNET_assert (NULL != dkp); TALER_denom_pub_hash (&dkp->pub, &cbc.denom_pub_hash); @@ -1502,10 +1485,7 @@ run (void *cls) TALER_coin_ev_hash (&pd.blinded_planchet, &cbc.denom_pub_hash, &cbc.h_coin_envelope)); - GNUNET_assert (GNUNET_OK == - TALER_withdraw_request_hash (&pd.blinded_planchet, - &cbc.denom_pub_hash, - &wih)); GNUNET_assert ( + GNUNET_assert ( GNUNET_OK == TALER_denom_sign_blinded ( &cbc.sig, @@ -1529,7 +1509,7 @@ run (void *cls) FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->do_withdraw (plugin->cls, - &wih, + NULL, &cbc, now, &found, @@ -1551,16 +1531,16 @@ run (void *cls) value.fraction, value.currency)); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->get_reserve_by_wih (plugin->cls, - &wih, - &reserve_pub3, - &reserve_out_serial_id)); + plugin->get_reserve_by_h_blind (plugin->cls, + &cbc.h_coin_envelope, + &reserve_pub3, + &reserve_out_serial_id)); FAILIF (0 != GNUNET_memcmp (&reserve_pub, &reserve_pub3)); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_withdraw_info (plugin->cls, - &wih, + &cbc.h_coin_envelope, &cbc2)); FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_sig, &cbc.reserve_sig)); @@ -1649,12 +1629,12 @@ run (void *cls) refund.details.h_contract_terms = deposit.h_contract_terms; refund.details.rtransaction_id = 1; refund.details.refund_amount = value; - refund.details.refund_fee = fee_refund; + refund.details.refund_fee = fees.refund; RND_BLK (&refund.details.merchant_sig); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->do_refund (plugin->cls, &refund, - &fee_deposit, + &fees.deposit, known_coin_id, ¬_found, &refund_ok, @@ -1686,6 +1666,7 @@ run (void *cls) refresh.noreveal_index = MELT_NOREVEAL_INDEX; FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->do_melt (plugin->cls, + NULL, &refresh, known_coin_id, &zombie_required, @@ -1709,7 +1690,7 @@ run (void *cls) TALER_amount_cmp (&refresh.amount_with_fee, &ret_refresh_session.session.amount_with_fee)); FAILIF (0 != - TALER_amount_cmp (&fee_refresh, + TALER_amount_cmp (&fees.refresh, &ret_refresh_session.melt_fee)); FAILIF (0 != GNUNET_memcmp (&refresh.rc, @@ -1755,10 +1736,7 @@ run (void *cls) new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE, now, &value, - &fee_withdraw, - &fee_deposit, - &fee_refresh, - &fee_refund); + &fees); GNUNET_assert (NULL != new_dkp[cnt]); new_denom_pubs[cnt] = new_dkp[cnt]->pub; ccoin = &revealed_coins[cnt]; @@ -2174,7 +2152,7 @@ run (void *cls) memset (&deposit, 0, sizeof (deposit)); - deposit.deposit_fee = fee_deposit; + deposit.deposit_fee = fees.deposit; RND_BLK (&deposit.coin.coin_pub); TALER_denom_pub_hash (&dkp->pub, &deposit.coin.denom_pub_hash); @@ -2196,7 +2174,7 @@ run (void *cls) &deposit.wire_salt, &h_wire_wt); deposit.amount_with_fee = value; - deposit.deposit_fee = fee_deposit; + deposit.deposit_fee = fees.deposit; deposit.refund_deadline = deadline; deposit.wire_deadline = deadline; |