diff options
| author | Christian Grothoff <grothoff@gnunet.org> | 2023-01-27 10:12:08 +0100 | 
|---|---|---|
| committer | Christian Grothoff <grothoff@gnunet.org> | 2023-01-27 10:12:08 +0100 | 
| commit | 7e8e2f43178139b35f726dd0584ef629e1853af8 (patch) | |
| tree | 080cc46d4bc4a62493c42d3132df7d539b15c4bb /src/exchangedb | |
| parent | f199b45e52e0cc66b75c4fc7243a11c06cf6e058 (diff) | |
| parent | 10cf3b3b65c89b3304a4d4f40c4b1a7eb5e47d14 (diff) | |
Merge branch 'master' of git+ssh://git.taler.net/exchange
Diffstat (limited to 'src/exchangedb')
19 files changed, 860 insertions, 168 deletions
diff --git a/src/exchangedb/0002-partners.sql b/src/exchangedb/0002-partners.sql index ff57f8fc..c80f2d74 100644 --- a/src/exchangedb/0002-partners.sql +++ b/src/exchangedb/0002-partners.sql @@ -25,6 +25,7 @@ CREATE TABLE partners    ,wad_fee_frac INT4 NOT NULL    ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)    ,partner_base_url TEXT NOT NULL +  ,PRIMARY KEY (partner_master_pub, start_date)    );  COMMENT ON TABLE partners    IS 'exchanges we do wad transfers to'; diff --git a/src/exchangedb/0003-aml_history.sql b/src/exchangedb/0003-aml_history.sql index c2ab532d..1c737265 100644 --- a/src/exchangedb/0003-aml_history.sql +++ b/src/exchangedb/0003-aml_history.sql @@ -110,7 +110,7 @@ BEGIN    EXECUTE FORMAT (      'CREATE INDEX ' || table_name || '_main_index '      'ON ' || table_name || ' ' -    '(h_payto ASC, decision_time ASC);' +    '(h_payto, decision_time DESC);'    );  END $$; diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am index feeb09cd..2ae5fe42 100644 --- a/src/exchangedb/Makefile.am +++ b/src/exchangedb/Makefile.am @@ -296,7 +296,7 @@ check_PROGRAMS = \    perf-exchangedb-reserves-in-insert-postgres\    test-exchangedb-by-j-postgres\    test-exchangedb-batch-reserves-in-insert-postgres\ -  test-exchangedb-populate-table-postgres\ +  test-exchangedb-populate-select-refunds-by-coin-postgres\    test-exchangedb-populate-link-data-postgres\    test-exchangedb-populate-ready-deposit-postgres @@ -306,7 +306,7 @@ TESTS = \    test-exchangedb-by-j-postgres\    perf-exchangedb-reserves-in-insert-postgres\    test-exchangedb-batch-reserves-in-insert-postgres\ -  test-exchangedb-populate-table-postgres\ +  test-exchangedb-populate-select-refunds-by-coin-postgres\    test-exchangedb-populate-link-data-postgres\    test-exchangedb-populate-ready-deposit-postgres  test_exchangedb_postgres_SOURCES = \ @@ -369,9 +369,9 @@ test_exchangedb_batch_reserves_in_insert_postgres_LDADD = \    -lgnunetutil \    $(XLIB) -test_exchangedb_populate_table_postgres_SOURCES = \ -  test_exchangedb_populate_table.c -test_exchangedb_populate_table_postgres_LDADD = \ +test_exchangedb_populate_select_refunds_by_coin_postgres_SOURCES = \ +  test_exchangedb_populate_select_refunds_by_coin.c +test_exchangedb_populate_select_refunds_by_coin_postgres_LDADD = \    libtalerexchangedb.la \    $(top_builddir)/src/json/libtalerjson.la \    $(top_builddir)/src/util/libtalerutil.la \ diff --git a/src/exchangedb/exchange_do_get_ready_deposit.sql b/src/exchangedb/exchange_do_get_ready_deposit.sql new file mode 100644 index 00000000..b887571e --- /dev/null +++ b/src/exchangedb/exchange_do_get_ready_deposit.sql @@ -0,0 +1,64 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2014--2022 Taler Systems SA +-- +-- TALER is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 3, or (at your option) any later version. +-- +-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +-- A PARTICULAR PURPOSE.  See the GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/> +-- +CREATE OR REPLACE FUNCTION exchange_do_get_ready_deposit( +  IN in_now INT8, +  IN in_start_shard_now INT8, +  IN in_end_shard_now INT8, +  OUT out_payto_uri VARCHAR, +  OUT out_merchant_pub BYTEA +) +LANGUAGE plpgsql +AS $$ +DECLARE + var_wire_target_h_payto BYTEA; +DECLARE + var_coin_pub BYTEA; +DECLARE + var_deposit_serial_id INT8; +BEGIN + +SELECT +   coin_pub +  ,deposit_serial_id +  INTO +   var_coin_pub +  ,var_deposit_serial_id +  FROM deposits_by_ready +  WHERE wire_deadline <= in_now +  AND shard >= in_start_shard_now +  AND shard <=in_end_shard_now +  ORDER BY +   wire_deadline ASC +  ,shard ASC; + +SELECT +  merchant_pub + ,wire_target_h_payto + INTO +  out_merchant_pub + ,var_wire_target_h_payto + FROM deposits + WHERE coin_pub=var_coin_pub +   AND deposit_serial_id=var_deposit_serial_id; + +SELECT + payto_uri + INTO out_payto_uri + FROM wire_targets + WHERE wire_target_h_payto=var_wire_target_h_payto; + +RETURN; +END $$; diff --git a/src/exchangedb/exchange_do_insert_aml_decision.sql b/src/exchangedb/exchange_do_insert_aml_decision.sql new file mode 100644 index 00000000..b3f77c8c --- /dev/null +++ b/src/exchangedb/exchange_do_insert_aml_decision.sql @@ -0,0 +1,102 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2023 Taler Systems SA +-- +-- TALER is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 3, or (at your option) any later version. +-- +-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +-- A PARTICULAR PURPOSE.  See the GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/> +-- + +CREATE OR REPLACE FUNCTION exchange_do_insert_aml_decision( +  IN in_h_payto BYTEA, +  IN in_new_threshold_val INT8, +  IN in_new_threshold_frac INT4, +  IN in_new_status INT4, +  IN in_decision_time INT8, +  IN in_justification VARCHAR, +  IN in_decider_pub BYTEA, +  IN in_decider_sig BYTEA, +  OUT out_invalid_officer BOOLEAN, +  OUT out_last_date INT8) +LANGUAGE plpgsql +AS $$ +BEGIN +-- Check officer is eligible to make decisions. +PERFORM +  FROM exchange.aml_staff +  WHERE decider_pub=in_decider_pub +    AND is_active +    AND NOT read_only; +IF NOT FOUND +THEN +  out_invalid_officer=TRUE; +  out_last_date=0; +  RETURN; +END IF; +out_invalid_officer=FALSE; + +-- Check no more recent decision exists. +SELECT decision_time +  INTO out_last_date +  FROM exchange.aml_history +  WHERE h_payto=in_h_payto +  ORDER BY decision_time DESC; +IF FOUND +THEN +  IF out_last_date >= in_decision_time +  THEN +    -- Refuse to insert older decision. +    RETURN; +  END IF; +  UPDATE exchange.aml_status +    SET threshold_val=in_threshold_val +       ,threshold_frac=in_threshold_frac +       ,status=in_new_status +   WHERE h_payto=in_h_payto; +  ASSERT FOUND, 'cannot have AML decision history but no AML status'; +ELSE +  out_last_date = 0; +  INSERT INTO exchange.aml_status +    (h_payto +    ,threshold_val +    ,threshold_frac +    ,status) +    VALUES +    (in_h_payto +    ,in_threshold_val +    ,in_threshold_frac +    ,in_new_status); +END IF; + + +INSERT INTO exchange.aml_history +  (h_payto +  ,new_threshold_val +  ,new_threshold_frac +  ,new_status +  ,decision_time +  ,justification +  ,decider_pub +  ,decider_sig +  ) VALUES +  (in_h_payto +  ,in_new_threshold_val +  ,in_new_threshold_frac +  ,in_new_status +  ,in_decision_time +  ,in_justification +  ,in_decider_pub +  ,in_decider_sig); + +END $$; + + +COMMENT ON FUNCTION exchange_do_insert_aml_decision(BYTEA, INT8, INT4, INT4, INT8, VARCHAR, BYTEA, BYTEA) +  IS 'Checks whether the AML officer is eligible to make AML decisions and if so inserts the decision into the table'; diff --git a/src/exchangedb/exchange_do_insert_aml_officer.sql b/src/exchangedb/exchange_do_insert_aml_officer.sql new file mode 100644 index 00000000..5cb926c0 --- /dev/null +++ b/src/exchangedb/exchange_do_insert_aml_officer.sql @@ -0,0 +1,74 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2023 Taler Systems SA +-- +-- TALER is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 3, or (at your option) any later version. +-- +-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +-- A PARTICULAR PURPOSE.  See the GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/> +-- + +CREATE OR REPLACE FUNCTION exchange_do_insert_aml_officer( +  IN in_decider_pub BYTEA, +  IN in_master_sig BYTEA, +  IN in_decider_name VARCHAR, +  IN in_is_active BOOLEAN, +  IN in_read_only BOOLEAN, +  IN in_last_change INT8, +  OUT out_last_change INT8) +LANGUAGE plpgsql +AS $$ +BEGIN +INSERT INTO exchange.aml_staff +  (decider_pub +  ,master_sig +  ,decider_name +  ,is_active +  ,read_only +  ,last_change +  ) VALUES +  (in_decider_pub +  ,in_master_sig +  ,in_decider_name +  ,in_is_active +  ,in_read_only +  ,in_last_change) + ON CONFLICT DO NOTHING; +IF FOUND +THEN +  out_last_change=0; +  RETURN; +END IF; + +-- Check update is most recent... +SELECT last_change +  INTO out_last_change +  FROM exchange.aml_staff +  WHERE decider_pub=in_decider_pub; +ASSERT FOUND, 'cannot have INSERT conflict but no AML staff record'; + +IF out_last_change >= in_last_change +THEN +  -- Refuse to insert older status + RETURN; +END IF; + +-- We are more recent, update existing record. +UPDATE exchange.aml_staff +  SET master_sig=in_master_sig +     ,decider_name=in_decider_name +     ,is_active=in_is_active +     ,read_only=in_read_only +     ,last_change=in_last_change +  WHERE decider_pub=in_decider_pub; +END $$; + + +COMMENT ON FUNCTION exchange_do_insert_aml_officer(BYTEA, BYTEA, VARCHAR, BOOL, BOOL, INT8) +  IS 'Inserts or updates AML staff record, making sure the update is more recent than the previous change'; diff --git a/src/exchangedb/exchange_do_refund_by_coin.sql b/src/exchangedb/exchange_do_refund_by_coin.sql new file mode 100644 index 00000000..ee00e2b5 --- /dev/null +++ b/src/exchangedb/exchange_do_refund_by_coin.sql @@ -0,0 +1,94 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2014--2022 Taler Systems SA +-- +-- TALER is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 3, or (at your option) any later version. +-- +-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +-- A PARTICULAR PURPOSE.  See the GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/> +-- +/*DROP FUNCTION exchange_do_refund_by_coin( +  IN in_coin_pub BYTEA, +  IN in_merchant_pub BYTEA, +  IN in_h_contract BYTEA +);*/ +CREATE OR REPLACE FUNCTION exchange_do_refund_by_coin( +  IN in_coin_pub BYTEA, +  IN in_merchant_pub BYTEA, +  IN in_h_contract BYTEA +) +RETURNS SETOF record +LANGUAGE plpgsql +AS $$ +DECLARE +  curs CURSOR +  FOR +  SELECT +    amount_with_fee_val +   ,amount_with_fee_frac +   ,deposit_serial_id +  FROM refunds +  WHERE coin_pub=in_coin_pub; +DECLARE +  i RECORD; +BEGIN +OPEN curs; +LOOP +    FETCH NEXT FROM curs INTO i; +    EXIT WHEN NOT FOUND; +    RETURN QUERY +      SELECT +        i.amount_with_fee_val +       ,i.amount_with_fee_frac +       FROM deposits +       WHERE +         coin_pub=in_coin_pub +         AND merchant_pub=in_merchant_pub +         AND h_contract_terms=in_h_contract +         AND i.deposit_serial_id = deposit_serial_id; +END LOOP; +CLOSE curs; +END $$; + +/*RETURNS TABLE(amount_with_fee_val INT8, amount_with_fee_frac INT4) +LANGUAGE plpgsql +AS $$ +DECLARE +  curs CURSOR +  FOR +  SELECT +    r.amount_with_fee_val +   ,r.amount_with_fee_frac +   ,r.deposit_serial_id +  FROM refunds r +  WHERE r.coin_pub=in_coin_pub; +DECLARE +  i RECORD; +BEGIN +OPEN curs; +LOOP +    FETCH NEXT FROM curs INTO i; +    IF FOUND +    THEN +      RETURN QUERY +      SELECT +        i.amount_with_fee_val +       ,i.amount_with_fee_frac +       FROM deposits +       WHERE +         merchant_pub=in_merchant_pub +         AND h_contract_terms=in_h_contract +         AND i.deposit_serial_id = deposit_serial_id; +    END IF; +    EXIT WHEN NOT FOUND; +END LOOP; +CLOSE curs; + +END $$; +*/ diff --git a/src/exchangedb/pg_get_ready_deposit.c b/src/exchangedb/pg_get_ready_deposit.c index af123529..73ac9e47 100644 --- a/src/exchangedb/pg_get_ready_deposit.c +++ b/src/exchangedb/pg_get_ready_deposit.c @@ -41,6 +41,7 @@ TEH_PG_get_ready_deposit (void *cls,      GNUNET_PQ_query_param_uint64 (&end_shard_row),      GNUNET_PQ_query_param_end    }; +    struct GNUNET_PQ_ResultSpec rs[] = {      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",                                            merchant_pub), @@ -57,26 +58,180 @@ TEH_PG_get_ready_deposit (void *cls,                "Finding ready deposits by deadline %s (%llu)\n",                GNUNET_TIME_absolute2s (now),                (unsigned long long) now.abs_value_us); -  PREPARE (pg, -           "deposits_get_ready", -           "SELECT" -           " payto_uri" -           ",merchant_pub" -           " FROM deposits_by_ready dbr" -           "  JOIN deposits dep" -           "    ON (dbr.coin_pub = dep.coin_pub AND" -           "        dbr.deposit_serial_id = dep.deposit_serial_id)" -           "  JOIN wire_targets wt" -           "    USING (wire_target_h_payto)" -           " WHERE dbr.wire_deadline<=$1" -           "   AND dbr.shard >= $2" -           "   AND dbr.shard <= $3" -           " ORDER BY " -           "   dbr.wire_deadline ASC" -           "  ,dbr.shard ASC" -           " LIMIT 1;"); +  int choose_mode =-2; +  const char *query; + +  if (-2 == choose_mode) +  { +    const char *mode = getenv ("NEW_LOGIC"); +    char dummy; +    if ( (NULL==mode) || +         (1 != sscanf (mode, +                       "%d%c", +                       &choose_mode, +                       &dummy)) ) +      { +        if (NULL != mode) +          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                      "Bad mode `%s' specified\n", +                      mode); +      } +    if (NULL==mode) +      choose_mode=0; + + +  } +  switch (choose_mode) +  { +  case 0: +    query="deposits_get_ready"; +    PREPARE (pg, +             query, +             "SELECT" +             " payto_uri" +             ",merchant_pub" +             " FROM deposits_by_ready dbr" +             "  JOIN deposits dep" +             "    ON (dbr.coin_pub = dep.coin_pub AND" +             "        dbr.deposit_serial_id = dep.deposit_serial_id)" +             "  JOIN wire_targets wt" +             "    USING (wire_target_h_payto)" +             " WHERE dbr.wire_deadline<=$1" +             "   AND dbr.shard >= $2" +             "   AND dbr.shard <= $3" +             " ORDER BY " +             "   dbr.wire_deadline ASC" +             "  ,dbr.shard ASC" +             " LIMIT 1;"); +    break; +  case 1: +    query="deposits_get_ready_v1"; +    PREPARE (pg, +             query, +             "WITH rc AS MATERIALIZED (" +             " SELECT" +             " coin_pub" +             ",deposit_serial_id" +             " FROM deposits_by_ready" +             " WHERE" +             " wire_deadline<=$1" +             " AND shard >= $2" +             " AND shard <= $3" +             " ORDER BY " +             "   wire_deadline ASC" +             "  ,shard ASC" +             "  LIMIT 1" +             ")" +             "SELECT" +             " wt.payto_uri" +             ",dep.merchant_pub" +             " FROM (" +             " SELECT" +             " wire_target_h_payto" +             ",merchant_pub" +             " FROM deposits" +             " WHERE coin_pub=(SELECT coin_pub FROM rc)" +             " AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)" +             ") dep" +             "  JOIN wire_targets wt" +             "    ON (dep.wire_target_h_payto = wt.wire_target_h_payto)" +             ); + +    break; +  case 2: +    query = "stored_procedure_get_ready_deposit"; +    PREPARE (pg, +             query, +             "SELECT" +             " out_payto_uri AS payto_uri" +             ",out_merchant_pub AS merchant_pub" +             " FROM" +             " exchange_do_get_ready_deposit" +             " ($1, $2, $3) "); +    break; +  case 3: +    query="deposits_get_ready_v3"; +    PREPARE (pg, +             query, +             "WITH rc AS MATERIALIZED (" +             " SELECT" +             " coin_pub" +             ",deposit_serial_id" +             " FROM deposits_by_ready" +             " WHERE" +             " wire_deadline<=$1" +             " AND shard >= $2" +             " AND shard <= $3" +             " ORDER BY " +             "   wire_deadline ASC" +             "  ,shard ASC" +             "  LIMIT 1" +             ")" +             "SELECT" +             " wt.payto_uri" +             ",dep.merchant_pub" +             " FROM (" +             " SELECT" +             " wire_target_h_payto" +             ",merchant_pub" +             ",coin_pub" +             " FROM deposits" +             " WHERE coin_pub=(SELECT coin_pub FROM rc)" +             " AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)" +             ") dep" +             "  JOIN wire_targets wt" +             "    ON (dep.wire_target_h_payto = wt.wire_target_h_payto)" +             "  JOIN rc" +             "    ON (dep.coin_pub=rc.coin_pub)" +             ); + +    break; +  case 4: +    query="deposits_get_ready_v4"; +    PREPARE (pg, +             query, +             "WITH rc AS MATERIALIZED (" +             " SELECT" +             " coin_pub" +             ",deposit_serial_id" +             " FROM deposits_by_ready" +             " WHERE" +             " wire_deadline<=$1" +             " AND shard >= $2" +             " AND shard <= $3" +             " ORDER BY " +             "   wire_deadline ASC" +             "  ,shard ASC" +             "  LIMIT 1" +             ")," +             "WITH rv AS MATERIALIZED (" +             " SELECT" +             " payto_uri" +             ",wire_target_h_payto" +             " FROM wire_targets" +             ")" +             "SELECT" +             " rv.payto_uri" +             ",dep.merchant_pub" +             " FROM (" +             " SELECT" +             " wire_target_h_payto" +             ",merchant_pub" +             " FROM deposits" +             " WHERE coin_pub=(SELECT coin_pub FROM rc)" +             " AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)" +             ") dep" +             " JOIN rv" +             "  ON (rv.wire_target_h_payto=dep.wire_target_h_payto)" +             ); +    break; +  default: +    GNUNET_break (0); +    return GNUNET_DB_STATUS_HARD_ERROR; +  } +    return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, -                                                   "deposits_get_ready", +                                                   query,                                                     params,                                                     rs);  } diff --git a/src/exchangedb/pg_insert_aml_decision.c b/src/exchangedb/pg_insert_aml_decision.c index d046c87f..85570ed8 100644 --- a/src/exchangedb/pg_insert_aml_decision.c +++ b/src/exchangedb/pg_insert_aml_decision.c @@ -1,6 +1,6 @@  /*     This file is part of TALER -   Copyright (C) 2022 Taler Systems SA +   Copyright (C) 2022, 2023 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 @@ -32,10 +32,12 @@ TEH_PG_insert_aml_decision (    const struct TALER_PaytoHashP *h_payto,    const struct TALER_Amount *new_threshold,    enum TALER_AmlDecisionState new_status, -  struct GNUNET_TIME_Absolute decision_time, +  struct GNUNET_TIME_Timestamp decision_time,    const char *justification,    const struct TALER_AmlOfficerPublicKeyP *decider_pub, -  const struct TALER_AmlOfficerSignatureP *decider_sig) +  const struct TALER_AmlOfficerSignatureP *decider_sig, +  bool *invalid_officer, +  struct GNUNET_TIME_Timestamp *last_date)  {    struct PostgresClosure *pg = cls;    uint32_t ns = (uint32_t) new_status; @@ -43,27 +45,29 @@ TEH_PG_insert_aml_decision (      GNUNET_PQ_query_param_auto_from_type (h_payto),      TALER_PQ_query_param_amount (new_threshold),      GNUNET_PQ_query_param_uint32 (&ns), -    GNUNET_PQ_query_param_absolute_time (&decision_time), +    GNUNET_PQ_query_param_timestamp (&decision_time),      GNUNET_PQ_query_param_string (justification),      GNUNET_PQ_query_param_auto_from_type (decider_pub),      GNUNET_PQ_query_param_auto_from_type (decider_sig),      GNUNET_PQ_query_param_end    }; +  struct GNUNET_PQ_ResultSpec rs[] = { +    GNUNET_PQ_result_spec_bool ("out_invalid_officer", +                                invalid_officer), +    GNUNET_PQ_result_spec_timestamp ("out_last_date", +                                     last_date), +    GNUNET_PQ_result_spec_end +  };    PREPARE (pg, -           "insert_aml_decision", -           "INSERT INTO aml_history " -           "(h_payto" -           ",new_threshold_val" -           ",new_threshold_frac" -           ",new_status" -           ",decision_time" -           ",justification" -           ",decider_pub" -           ",decider_sig" -           ") VALUES " +           "do_insert_aml_decision", +           "SELECT" +           " out_invalid_officer" +           ",out_last_date" +           " FROM exchange_do_insert_aml_decision"             "($1, $2, $3, $4, $5, $6, $7, $8);"); -  return GNUNET_PQ_eval_prepared_non_select (pg->conn, -                                             "insert_aml_decision", -                                             params); +  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, +                                                   "do_insert_aml_decision", +                                                   params, +                                                   rs);  } diff --git a/src/exchangedb/pg_insert_aml_decision.h b/src/exchangedb/pg_insert_aml_decision.h index 205c1c74..b539945a 100644 --- a/src/exchangedb/pg_insert_aml_decision.h +++ b/src/exchangedb/pg_insert_aml_decision.h @@ -1,6 +1,6 @@  /*     This file is part of TALER -   Copyright (C) 2022 Taler Systems SA +   Copyright (C) 2022, 2023 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 @@ -38,6 +38,9 @@   * @param justification human-readable text justifying the decision   * @param decider_pub public key of the staff member   * @param decider_sig signature of the staff member + * @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now + * @param[out] last_date set to the previous decision time; + *   the INSERT is not performed if @a last_date is not before @a decision_time   * @return database transaction status   */  enum GNUNET_DB_QueryStatus @@ -46,10 +49,12 @@ TEH_PG_insert_aml_decision (    const struct TALER_PaytoHashP *h_payto,    const struct TALER_Amount *new_threshold,    enum TALER_AmlDecisionState new_status, -  struct GNUNET_TIME_Absolute decision_time, +  struct GNUNET_TIME_Timestamp decision_time,    const char *justification,    const struct TALER_AmlOfficerPublicKeyP *decider_pub, -  const struct TALER_AmlOfficerSignatureP *decider_sig); +  const struct TALER_AmlOfficerSignatureP *decider_sig, +  bool *invalid_officer, +  struct GNUNET_TIME_Timestamp *last_date);  #endif diff --git a/src/exchangedb/pg_insert_aml_officer.c b/src/exchangedb/pg_insert_aml_officer.c index fc2cadef..c1f635a6 100644 --- a/src/exchangedb/pg_insert_aml_officer.c +++ b/src/exchangedb/pg_insert_aml_officer.c @@ -1,6 +1,6 @@  /*     This file is part of TALER -   Copyright (C) 2022 Taler Systems SA +   Copyright (C) 2022, 2023 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 @@ -34,7 +34,8 @@ TEH_PG_insert_aml_officer (    const char *decider_name,    bool is_active,    bool read_only, -  struct GNUNET_TIME_Absolute last_change) +  struct GNUNET_TIME_Timestamp last_change, +  struct GNUNET_TIME_Timestamp *previous_change)  {    struct PostgresClosure *pg = cls;    struct GNUNET_PQ_QueryParam params[] = { @@ -43,22 +44,23 @@ TEH_PG_insert_aml_officer (      GNUNET_PQ_query_param_string (decider_name),      GNUNET_PQ_query_param_bool (is_active),      GNUNET_PQ_query_param_bool (read_only), -    GNUNET_PQ_query_param_absolute_time (&last_change), +    GNUNET_PQ_query_param_timestamp (&last_change),      GNUNET_PQ_query_param_end    }; +  struct GNUNET_PQ_ResultSpec rs[] = { +    GNUNET_PQ_result_spec_timestamp ("out_last_change", +                                     previous_change), +    GNUNET_PQ_result_spec_end +  };    PREPARE (pg, -           "insert_aml_staff", -           "INSERT INTO aml_staff " -           "(decider_pub" -           ",master_sig" -           ",decider_name" -           ",is_active" -           ",read_only" -           ",last_change" -           ") VALUES " +           "do_insert_aml_staff", +           "SELECT" +           " out_last_change" +           " FROM exchange_do_insert_aml_officer"             "($1, $2, $3, $4, $5, $6);"); -  return GNUNET_PQ_eval_prepared_non_select (pg->conn, -                                             "insert_aml_staff", -                                             params); +  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, +                                                   "do_insert_aml_staff", +                                                   params, +                                                   rs);  } diff --git a/src/exchangedb/pg_insert_aml_officer.h b/src/exchangedb/pg_insert_aml_officer.h index be034d9f..3c6f5d82 100644 --- a/src/exchangedb/pg_insert_aml_officer.h +++ b/src/exchangedb/pg_insert_aml_officer.h @@ -27,7 +27,10 @@  /** - * Insert AML staff record. + * Insert AML staff record.  If the time given in + * @a last_change is before the previous change in the + * database, only @e previous_change is returned and + * no actual change is committed to the database.   *   * @param cls closure   * @param decider_pub public key of the staff member @@ -36,6 +39,7 @@   * @param is_active true to enable, false to set as inactive   * @param read_only true to set read-only access   * @param last_change when was the change made effective + * @param[out] previous_change set to the time of the previous change   * @return database transaction status   */  enum GNUNET_DB_QueryStatus @@ -46,6 +50,7 @@ TEH_PG_insert_aml_officer (    const char *decider_name,    bool is_active,    bool read_only, -  struct GNUNET_TIME_Absolute last_change); +  struct GNUNET_TIME_Timestamp last_change, +  struct GNUNET_TIME_Timestamp *previous_change);  #endif diff --git a/src/exchangedb/pg_insert_partner.c b/src/exchangedb/pg_insert_partner.c index 567f3776..5abb2c91 100644 --- a/src/exchangedb/pg_insert_partner.c +++ b/src/exchangedb/pg_insert_partner.c @@ -28,13 +28,13 @@  enum GNUNET_DB_QueryStatus  TEH_PG_insert_partner (void *cls, -                         const struct TALER_MasterPublicKeyP *master_pub, -                         struct GNUNET_TIME_Timestamp start_date, -                         struct GNUNET_TIME_Timestamp end_date, -                         struct GNUNET_TIME_Relative wad_frequency, -                         const struct TALER_Amount *wad_fee, -                         const char *partner_base_url, -                         const struct TALER_MasterSignatureP *master_sig) +                       const struct TALER_MasterPublicKeyP *master_pub, +                       struct GNUNET_TIME_Timestamp start_date, +                       struct GNUNET_TIME_Timestamp end_date, +                       struct GNUNET_TIME_Relative wad_frequency, +                       const struct TALER_Amount *wad_fee, +                       const char *partner_base_url, +                       const struct TALER_MasterSignatureP *master_sig)  {    struct PostgresClosure *pg = cls;    struct GNUNET_PQ_QueryParam params[] = { @@ -61,10 +61,9 @@ TEH_PG_insert_partner (void *cls,             "  ,master_sig"             "  ,partner_base_url"             "  ) VALUES " -           "  ($1, $2, $3, $4, $5, $6, $7, $8);"); +           "  ($1, $2, $3, $4, $5, $6, $7, $8)" +           "  ON CONFLICT DO NOTHING;");    return GNUNET_PQ_eval_prepared_non_select (pg->conn,                                               "insert_partner",                                               params);  } - - diff --git a/src/exchangedb/pg_persist_policy_details.c b/src/exchangedb/pg_persist_policy_details.c index 2b778787..3bc7afa9 100644 --- a/src/exchangedb/pg_persist_policy_details.c +++ b/src/exchangedb/pg_persist_policy_details.c @@ -59,7 +59,15 @@ TEH_PG_persist_policy_details (      GNUNET_PQ_result_spec_end    }; -  // FIXME: prepare missing!!?! +  PREPARE (pg, +           "call_insert_or_update_policy_details", +           "SELECT" +           " out_policy_details_serial_id AS policy_details_serial_id" +           ",out_accumulated_total_val AS accumulated_total_val" +           ",out_accumulated_total_frac AS accumulated_total_frac" +           ",out_fulfillment_state AS fulfillment_state" +           " FROM exchange_do_insert_or_update_policy_details" +           "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);");    return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,                                                     "call_insert_or_update_policy_details",                                                     params, diff --git a/src/exchangedb/pg_select_refunds_by_coin.c b/src/exchangedb/pg_select_refunds_by_coin.c index b9db2b70..255cac34 100644 --- a/src/exchangedb/pg_select_refunds_by_coin.c +++ b/src/exchangedb/pg_select_refunds_by_coin.c @@ -112,17 +112,47 @@ TEH_PG_select_refunds_by_coin (      GNUNET_PQ_query_param_auto_from_type (h_contract),      GNUNET_PQ_query_param_end    }; +  struct GNUNET_PQ_QueryParam params5[] = { +    GNUNET_PQ_query_param_auto_from_type (coin_pub), +    GNUNET_PQ_query_param_end +  }; +    struct SelectRefundContext srctx = {      .cb = cb,      .cb_cls = cb_cls,      .pg = pg,      .status = GNUNET_OK    }; +  static int percent_refund = -2; +  const char *query; +  struct GNUNET_PQ_QueryParam *xparams = params; -  if (NULL == getenv ("NEW_LOGIC")) +  if (-2 == percent_refund)    { +    const char *mode = getenv ("NEW_LOGIC"); +    char dummy; + +    if ( (NULL==mode) || +         (1 != sscanf (mode, +                       "%d%c", +                       &percent_refund, +                       &dummy)) ) +      { +        if (NULL != mode) +          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                      "Bad mode `%s' specified\n", +                      mode); +      } +      if (NULL==mode) +        percent_refund=0; +  } + +  switch (percent_refund) +  { +  case 0: +    query = "get_refunds_by_coin_and_contract-v0";      PREPARE (pg, -             "get_refunds_by_coin_and_contract", +             query,               "SELECT"               " ref.amount_with_fee_val"               ",ref.amount_with_fee_frac" @@ -132,12 +162,26 @@ TEH_PG_select_refunds_by_coin (               " WHERE ref.coin_pub=$1"               "   AND dep.merchant_pub=$2"               "   AND dep.h_contract_terms=$3;"); -  } -  else -  { -    // FIXME-Joseph +    break; +  case 1: +    query = "get_refunds_by_coin_and_contract-v1"; +    PREPARE (pg, +             query, +             "SELECT" +             " ref.amount_with_fee_val" +             ",ref.amount_with_fee_frac" +             " FROM refunds ref" +             " LEFT JOIN deposits dep" +             "   ON dep.coin_pub = ref.coin_pub" +             "   AND ref.deposit_serial_id = dep.deposit_serial_id" +             " WHERE ref.coin_pub=$1" +             "   AND dep.merchant_pub=$2" +             "   AND dep.h_contract_terms=$3;"); +    break; +  case 2: +    query = "get_refunds_by_coin_and_contract-v2";      PREPARE (pg, -             "get_refunds_by_coin_and_contract", +             query,               "WITH rc AS MATERIALIZED("               "SELECT"               " amount_with_fee_val" @@ -149,21 +193,139 @@ TEH_PG_select_refunds_by_coin (               "SELECT"               "   rc.amount_with_fee_val"               "  ,rc.amount_with_fee_frac" -             " FROM " -             "(SELECT" -             "   rc.amount_with_fee_val" -             "  ,rc.amount_with_fee_frac"               "  FROM deposits dep" +             " JOIN rc" +             " ON rc.deposit_serial_id = dep.deposit_serial_id"               "  WHERE" -             "  dep.coin_pub = $1" // optional... +             "      dep.coin_pub = $1"               "  AND dep.merchant_pub = $2" -             "  AND dep.h_contract_terms = $3) dep" -             " JOIN rc" -             "   USING (coin_pub,deposit_serial_id)"); +             "  AND dep.h_contract_terms = $3"); +    break; +  case 3: +    query = "get_refunds_by_coin_and_contract-v3"; +    PREPARE (pg, +             query, +             "WITH rc AS MATERIALIZED(" +             "SELECT" +             " amount_with_fee_val" +             ",amount_with_fee_frac" +             ",deposit_serial_id" +             " FROM refunds" +             " WHERE coin_pub=$1)" +             "SELECT" +             "   rc.amount_with_fee_val" +             "  ,rc.amount_with_fee_frac" +             "  FROM (" +             "SELECT" +             " amount_with_fee_val" +             ",amount_with_fee_frac" +             " FROM deposits depos" +             "  WHERE" +             "  depos.coin_pub = $1" +             "  AND depos.merchant_pub = $2" +             "  AND depos.h_contract_terms = $3) dep, rc;"); +    break; +  case 4: +    query = "get_refunds_by_coin_and_contract-v4"; +    PREPARE (pg, +             query, +             "WITH rc AS MATERIALIZED(" +             "SELECT" +             " amount_with_fee_val" +             ",amount_with_fee_frac" +             ",coin_pub" +             ",deposit_serial_id" +             " FROM refunds ref" +             " WHERE ref.coin_pub=$1)" +             "SELECT" +             "   rc.amount_with_fee_val" +             "  ,rc.amount_with_fee_frac" +             "  ,deposit_serial_id" +             "  FROM (" +             "SELECT" +             " amount_with_fee_val" +             ",amount_with_fee_frac" +             " FROM deposits depos" +             "  WHERE" +             "  depos.merchant_pub = $2" +             "  AND depos.h_contract_terms = $3) dep JOIN rc " +             "USING(deposit_serial_id, coin_pub);"); +    break; +  case 5: +    query = "get_refunds_by_coin_and_contract-v-broken"; +    xparams = params5; +    PREPARE (pg, +             query, +             "SELECT" +             " amount_with_fee_val" +             ",amount_with_fee_frac" +             ",coin_pub" +             ",deposit_serial_id" +             " FROM refunds" +             " WHERE coin_pub=$1;"); +    break; +  case 8: +    query = "get_refunds_by_coin_and_contract-v8"; +    PREPARE (pg, +             query, +             "WITH" +             " rc AS MATERIALIZED(" +             "  SELECT" +             "   amount_with_fee_val" +             "  ,amount_with_fee_frac" +             "  ,coin_pub" +             "  ,deposit_serial_id" +             "  FROM refunds" +             "  WHERE coin_pub=$1)," +             " dep AS MATERIALIZED(" +             "  SELECT" +             "   deposit_serial_id" +             "  FROM deposits" +             "  WHERE coin_pub = $1" +             "    AND merchant_pub = $2" +             "    AND h_contract_terms = $3" +             ")" +             "SELECT" +             "   rc.amount_with_fee_val" +             "  ,rc.amount_with_fee_frac" +             "  FROM " +             "  rc JOIN dep USING (deposit_serial_id);"); +    break; +  case 9: +    query = "get_refunds_by_coin_and_contract-v9-broken"; +    PREPARE (pg, +             query, +             "SELECT" +             "   ref.amount_with_fee_val" +             "  ,ref.amount_with_fee_frac" +             " FROM deposits dep" +             " JOIN refunds ref USING(deposit_serial_id)" +             " WHERE dep.coin_pub IN (" +             "   SELECT coin_pub" +             "     FROM refunds" +             "    WHERE coin_pub=$1)" +             "  AND merchant_pub = $2" +             "  AND h_contract_terms = $3;"); +    break; +  case 10: +    query = "get_refunds_by_coin_and_contract-v10-broken"; +    PREPARE (pg, +             query, +             "SELECT" +             " *" +             " FROM" +             " exchange_do_refund_by_coin" +             " ($1, $2, $3) " +             " AS (amount_with_fee_val INT8, amount_with_fee_frac INT4);"); +    break; +  default: +    GNUNET_break (0); +    return GNUNET_DB_STATUS_HARD_ERROR;    } +    qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, -                                             "get_refunds_by_coin_and_contract", -                                             params, +                                             query, +                                             xparams,                                               &get_refunds_cb,                                               &srctx);    if (GNUNET_SYSERR == srctx.status) diff --git a/src/exchangedb/procedures.sql.in b/src/exchangedb/procedures.sql.in index 19483024..ef6341a1 100644 --- a/src/exchangedb/procedures.sql.in +++ b/src/exchangedb/procedures.sql.in @@ -37,10 +37,14 @@ SET search_path TO exchange;  #include "exchange_do_reserve_open_deposit.sql"  #include "exchange_do_reserve_open.sql"  #include "exchange_do_insert_or_update_policy_details.sql" +#include "exchange_do_insert_aml_decision.sql" +#include "exchange_do_insert_aml_officer.sql"  #include "exchange_do_batch_reserves_in_insert.sql"  #include "exchange_do_batch_reserves_update.sql"  #include "exchange_do_batch2_reserves_in_insert.sql"  #include "exchange_do_batch4_reserves_in_insert.sql"  #include "exchange_do_batch8_reserves_in_insert.sql" +#include "exchange_do_refund_by_coin.sql" +#include "exchange_do_get_ready_deposit.sql"  COMMIT; diff --git a/src/exchangedb/test_exchangedb_populate_link_data.c b/src/exchangedb/test_exchangedb_populate_link_data.c index ff294874..1323f3b3 100644 --- a/src/exchangedb/test_exchangedb_populate_link_data.c +++ b/src/exchangedb/test_exchangedb_populate_link_data.c @@ -24,14 +24,6 @@  #include "taler_exchangedb_plugin.h"  #include "math.h" - -#define NUM_ROWS 1000 - -/** - * Global result from the testcase. - */ -static int result; -  /**   * Report line of error if @a cond is true, and jump to label "drop".   */ @@ -55,22 +47,10 @@ static int result;  #define ZR_BLK(ptr) \    memset (ptr, 0, sizeof (*ptr)) - -/** - * Currency we use.  Must match test-exchange-db-*.conf. - */  #define CURRENCY "EUR" - -/** - * How big do we make the RSA keys? - */  #define RSA_KEY_SIZE 1024 -static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins; - -static struct TALER_TransferPrivateKeyP tprivs[TALER_CNC_KAPPA]; - -static struct TALER_TransferPublicKeyP tpub;  #define ROUNDS 10 +#define NUM_ROWS 1000  #define MELT_NEW_COINS 5  #define MELT_NOREVEAL_INDEX 1  /** @@ -82,7 +62,10 @@ static struct TALER_DenomFeeSet fees;   * Denomination keys used for fresh coins in melt test.   */  static struct DenomKeyPair **new_dkp; - +static int result; +static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins; +static struct TALER_TransferPrivateKeyP tprivs[TALER_CNC_KAPPA]; +static struct TALER_TransferPublicKeyP tpub;  struct DenomKeyPair  {    struct TALER_DenominationPrivateKey priv; @@ -222,8 +205,6 @@ handle_link_data_cb (void *cls,    }  } - -  /**   * Main function that will be run by the scheduler.   * diff --git a/src/exchangedb/test_exchangedb_populate_ready_deposit.c b/src/exchangedb/test_exchangedb_populate_ready_deposit.c index 49b1bf5d..97273fc9 100644 --- a/src/exchangedb/test_exchangedb_populate_ready_deposit.c +++ b/src/exchangedb/test_exchangedb_populate_ready_deposit.c @@ -24,9 +24,6 @@  #include "taler_exchangedb_plugin.h"  #include "math.h" - -#define NUM_ROWS 1000 -  /**   * Global result from the testcase.   */ @@ -55,20 +52,13 @@ static int result;  #define ZR_BLK(ptr) \    memset (ptr, 0, sizeof (*ptr)) -  /**   * Currency we use.  Must match test-exchange-db-*.conf.   */  #define CURRENCY "EUR" - -/** - * How big do we make the RSA keys? - */  #define RSA_KEY_SIZE 1024 -static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins; - - -#define ROUNDS 100 +#define NUM_ROWS 1000000 +#define ROUNDS 10000  #define MELT_NEW_COINS 5  #define MELT_NOREVEAL_INDEX 1  /** @@ -81,7 +71,7 @@ static struct TALER_MerchantWireHashP h_wire_wt;   * Denomination keys used for fresh coins in melt test.   */  static struct DenomKeyPair **new_dkp; - +static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;  struct DenomKeyPair  {    struct TALER_DenominationPrivateKey priv; @@ -389,7 +379,6 @@ run (void *cls)                                       &nonce_ok,                                       &ruuid));        } -        {          /* ENSURE_COIN_KNOWN */          uint64_t known_coin_id; @@ -408,23 +397,23 @@ run (void *cls)          refresh.noreveal_index = MELT_NOREVEAL_INDEX;        }          /*STORE INTO DEPOSIT*/ -        { -          struct GNUNET_TIME_Timestamp now; -          now = GNUNET_TIME_timestamp_get (); -          FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != -                  plugin->insert_deposit (plugin->cls, -                                          now, -                                          &depos[i])); -        } -        if (ROUNDS == i) -          TALER_denom_sig_free (&depos[i].coin.denom_sig); +      { +        struct GNUNET_TIME_Timestamp now; +        now = GNUNET_TIME_timestamp_get (); +        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +                plugin->insert_deposit (plugin->cls, +                                        now, +                                        &depos[i])); +      } +      if (ROUNDS == i) +        TALER_denom_sig_free (&depos[i].coin.denom_sig);      }    /* End of benchmark setup */    GNUNET_free(perm);    // commit    FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=            plugin->commit (plugin->cls)); -  /**** CALL GET LINK DATA ****/ +  /**** CALL GET READY DEPOSIT ****/    for (unsigned int r=0; r< ROUNDS; r++)    {      struct GNUNET_TIME_Absolute time; diff --git a/src/exchangedb/test_exchangedb_populate_table.c b/src/exchangedb/test_exchangedb_populate_select_refunds_by_coin.c index face454f..c094b204 100644 --- a/src/exchangedb/test_exchangedb_populate_table.c +++ b/src/exchangedb/test_exchangedb_populate_select_refunds_by_coin.c @@ -24,8 +24,6 @@  #include "taler_exchangedb_plugin.h"  #include "math.h" -#define NUM_ROWS 10000 -  /**   * Global result from the testcase.   */ @@ -41,7 +39,6 @@ static int result;      goto drop;                                  \    } while (0) -  /**   * Initializes @a ptr with random data.   */ @@ -54,16 +51,13 @@ static int result;  #define ZR_BLK(ptr) \    memset (ptr, 0, sizeof (*ptr)) -  /**   * Currency we use.  Must match test-exchange-db-*.conf.   */  #define CURRENCY "EUR" -/** - * How big do we make the RSA keys? - */  #define RSA_KEY_SIZE 1024 -#define ROUNDS 1000 +#define ROUNDS 10000 +#define NUM_ROWS 1000000  #define MELT_NEW_COINS 5  #define MELT_NOREVEAL_INDEX 1  /** @@ -72,14 +66,14 @@ static int result;  static struct TALER_EXCHANGEDB_Plugin *plugin;  static struct TALER_DenomFeeSet fees;  static struct TALER_MerchantWireHashP h_wire_wt; - +static struct DenomKeyPair **new_dkp; +static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;  struct DenomKeyPair  {    struct TALER_DenominationPrivateKey priv;    struct TALER_DenominationPublicKey pub;  }; -static struct DenomKeyPair **new_dkp; -static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins; +  /**   * Destroy a denomination key pair.  The key is not necessarily removed from the DB.   * @@ -185,7 +179,6 @@ check_refund_cb (void *cls,                   const struct TALER_Amount *amount_with_fee)  {    const struct TALER_EXCHANGEDB_Refund *refund = cls; -    if (0 != TALER_amount_cmp (amount_with_fee,                               &refund->details.refund_amount))    { @@ -207,7 +200,6 @@ run (void *cls)  {    struct GNUNET_CONFIGURATION_Handle *cfg = cls;    const uint32_t num_partitions = 10; -  struct DenomKeyPair *dkp = NULL;    struct GNUNET_TIME_Timestamp ts;    struct TALER_EXCHANGEDB_Deposit *depos=NULL;    struct GNUNET_TIME_Timestamp deadline; @@ -226,6 +218,8 @@ run (void *cls)    struct TALER_CoinSpendPublicKeyP coin_pub;    struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;    struct TALER_DenominationPublicKey *new_denom_pubs = NULL; +  unsigned int count=0; +    ref = GNUNET_new_array (ROUNDS +1,                            struct TALER_EXCHANGEDB_Refund);    depos = GNUNET_new_array (ROUNDS +1, @@ -400,18 +394,72 @@ run (void *cls)                                        now,                                        &depos[i]));      } - -    /* 100% Refund */      {        bool not_found;        bool refund_ok;        bool gone;        bool conflict; -      ref[i].coin = depos[i].coin; -      ref[i].details.merchant_pub = depos[i].merchant_pub; +      unsigned int refund_percent=0; +      switch (refund_percent){ +      case 2 ://100% refund +        ref[i].coin = depos[i].coin; +        ref[i].details.merchant_pub = depos[i].merchant_pub; +        RND_BLK(&ref[i].details.merchant_sig); +        ref[i].details.h_contract_terms = depos[i].h_contract_terms; +        ref[i].coin.coin_pub = depos[i].coin.coin_pub; +        ref[i].details.rtransaction_id = i; +        ref[i].details.refund_amount = value; +        ref[i].details.refund_fee = fees.refund; +        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +                plugin->do_refund (plugin->cls, +                                   &ref[i], +                                   &fees.deposit, +                                   known_coin_id, +                                   ¬_found, +                                   &refund_ok, +                                   &gone, +                                   &conflict)); +        break; +    case 1 ://10% refund +      if (count < (NUM_ROWS/10)) +      { +        ref[i].coin = depos[i].coin; +        ref[i].details.merchant_pub = depos[i].merchant_pub; +        RND_BLK(&ref[i].details.merchant_sig); +        ref[i].details.h_contract_terms = depos[i].h_contract_terms; +        ref[i].coin.coin_pub = depos[i].coin.coin_pub; +        ref[i].details.rtransaction_id = i; +        ref[i].details.refund_amount = value; +        ref[i].details.refund_fee = fees.refund; +      } +      else +      { +        ref[i].coin = depos[i].coin; +        RND_BLK(&ref[i].details.merchant_pub); +        RND_BLK(&ref[i].details.merchant_sig); +        RND_BLK(&ref[i].details.h_contract_terms); +        RND_BLK(&ref[i].coin.coin_pub); +        ref[i].details.rtransaction_id = i; +        ref[i].details.refund_amount = value; +        ref[i].details.refund_fee = fees.refund; +      } +      FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +              plugin->do_refund (plugin->cls, +                                 &ref[i], +                                 &fees.deposit, +                                 known_coin_id, +                                 ¬_found, +                                 &refund_ok, +                                 &gone, +                                 &conflict)); +      count++; +      break; +    case 0://no refund +      ref[i].coin=depos[i].coin; +      RND_BLK(&ref[i].details.merchant_pub);        RND_BLK(&ref[i].details.merchant_sig); -      ref[i].details.h_contract_terms = depos[i].h_contract_terms; -      ref[i].coin.coin_pub = depos[i].coin.coin_pub; +      RND_BLK(&ref[i].details.h_contract_terms); +      RND_BLK(&ref[i].coin.coin_pub);        ref[i].details.rtransaction_id = i;        ref[i].details.refund_amount = value;        ref[i].details.refund_fee = fees.refund; @@ -424,10 +472,8 @@ run (void *cls)                                   &refund_ok,                                   &gone,                                   &conflict)); - -      /*      FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != -              plugin->insert_refund (plugin->cls, -              &ref[i]));*/ +        break; +      }/* END OF SWITCH CASE */      }      if (ROUNDS == i)        TALER_denom_sig_free (&depos[i].coin.denom_sig); @@ -443,7 +489,7 @@ run (void *cls)      struct GNUNET_TIME_Relative duration;      time = GNUNET_TIME_absolute_get (); -    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != +    FAILIF (0 >              plugin->select_refunds_by_coin (plugin->cls,                                              &ref[r].coin.coin_pub,                                              &ref[r].details.merchant_pub, @@ -476,10 +522,8 @@ run (void *cls)    result = 0;  drop:    GNUNET_break (GNUNET_OK == -  plugin->drop_tables (plugin->cls)); +                plugin->drop_tables (plugin->cls));  cleanup: -  if (NULL != dkp) -    destroy_denom_key_pair (dkp);    if (NULL != revealed_coins)    {      for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) @@ -502,7 +546,6 @@ cleanup:      }    GNUNET_free(depos);    GNUNET_free(ref); -  dkp = NULL;    TALER_EXCHANGEDB_plugin_unload (plugin);    plugin = NULL;  }  | 
