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) | |
-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 df07e025..fdc47b7c 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 cb0685ba..8cc4e237 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 dd785213..a14c212d 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 878c36f9..5d8db5ce 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 f9e64fdc..80740714 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; | 
