gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] branch master updated: adapt to latest GNUnet API: GNUN


From: gnunet
Subject: [taler-exchange] branch master updated: adapt to latest GNUnet API: GNUNET_JSON_spec_mark_optional() changed
Date: Tue, 05 Apr 2022 17:15:54 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new f3a4b009 adapt to latest GNUnet API: GNUNET_JSON_spec_mark_optional() 
changed
f3a4b009 is described below

commit f3a4b00907410444055f47d4ff2074b44f981ad3
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Tue Apr 5 17:15:50 2022 +0200

    adapt to latest GNUnet API: GNUNET_JSON_spec_mark_optional() changed
---
 contrib/gana                                       |   2 +-
 src/exchange/Makefile.am                           |   1 +
 src/exchange/taler-exchange-httpd_deposit.c        |   6 +-
 src/exchange/taler-exchange-httpd_melt.c           |  19 ++-
 src/exchange/taler-exchange-httpd_metrics.h        |   3 +-
 src/exchange/taler-exchange-httpd_purses_create.c  | 154 +++++++++++++++------
 src/exchange/taler-exchange-httpd_purses_create.h  |  47 +++++++
 src/exchange/taler-exchange-httpd_recoup-refresh.c |   6 +-
 src/exchange/taler-exchange-httpd_recoup.c         |   6 +-
 .../taler-exchange-httpd_refreshes_reveal.c        |  20 +--
 src/exchangedb/exchange-0001-part.sql              |  96 ++++++++++++-
 src/exchangedb/plugin_exchangedb_postgres.c        | 104 ++++++++++++--
 src/include/taler_exchangedb_plugin.h              |  27 +++-
 src/lib/exchange_api_common.c                      |  22 +--
 src/lib/exchange_api_deposit.c                     |   3 +-
 src/lib/exchange_api_handle.c                      |   9 +-
 src/lib/exchange_api_link.c                        |   9 +-
 src/lib/exchange_api_purse_create_with_deposit.c   |   5 +-
 src/lib/exchange_api_refund.c                      |  12 +-
 .../testing_api_cmd_auditor_deposit_confirmation.c |   3 +-
 20 files changed, 441 insertions(+), 113 deletions(-)

diff --git a/contrib/gana b/contrib/gana
index 8e5eda95..313216ee 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 8e5eda9507f42af6a394d218a65082b3294855b7
+Subproject commit 313216ee11fe604d39ea5f1b71b1ad96a60391d9
diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am
index dd8edfb9..c4c1656a 100644
--- a/src/exchange/Makefile.am
+++ b/src/exchange/Makefile.am
@@ -103,6 +103,7 @@ taler_exchange_httpd_SOURCES = \
   taler-exchange-httpd_melt.c taler-exchange-httpd_melt.h \
   taler-exchange-httpd_metrics.c taler-exchange-httpd_metrics.h \
   taler-exchange-httpd_mhd.c taler-exchange-httpd_mhd.h \
+  taler-exchange-httpd_purses_create.c taler-exchange-httpd_purses_create.h \
   taler-exchange-httpd_recoup.c taler-exchange-httpd_recoup.h \
   taler-exchange-httpd_recoup-refresh.c taler-exchange-httpd_recoup-refresh.h \
   taler-exchange-httpd_refreshes_reveal.c 
taler-exchange-httpd_refreshes_reveal.h \
diff --git a/src/exchange/taler-exchange-httpd_deposit.c 
b/src/exchange/taler-exchange-httpd_deposit.c
index 011f5f15..0ce5add3 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -224,14 +224,16 @@ TEH_handler_deposit (struct MHD_Connection *connection,
                                  &deposit.h_contract_terms),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
-                                   &deposit.coin.h_age_commitment)),
+                                   &deposit.coin.h_age_commitment),
+      &deposit.coin.no_age_commitment),
     GNUNET_JSON_spec_fixed_auto ("coin_sig",
                                  &deposit.csig),
     GNUNET_JSON_spec_timestamp ("timestamp",
                                 &deposit.timestamp),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_timestamp ("refund_deadline",
-                                  &deposit.refund_deadline)),
+                                  &deposit.refund_deadline),
+      NULL),
     GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
                                 &deposit.wire_deadline),
     GNUNET_JSON_spec_end ()
diff --git a/src/exchange/taler-exchange-httpd_melt.c 
b/src/exchange/taler-exchange-httpd_melt.c
index 2ff03023..3d6f05c0 100644
--- a/src/exchange/taler-exchange-httpd_melt.c
+++ b/src/exchange/taler-exchange-httpd_melt.c
@@ -120,9 +120,9 @@ struct MeltContext
   bool coin_is_dirty;
 
   /**
-   * True if @e rms is set.
+   * True if @e rms is missing.
    */
-  bool have_rms;
+  bool no_rms;
 };
 
 
@@ -161,9 +161,9 @@ melt_transaction (void *cls,
 
   if (0 >
       (qs = TEH_plugin->do_melt (TEH_plugin->cls,
-                                 rmc->have_rms
-                                 ? &rmc->rms
-                                 : NULL,
+                                 rmc->no_rms
+                                 ? NULL
+                                 : &rmc->rms,
                                  &rmc->refresh_session,
                                  rmc->known_coin_id,
                                  &rmc->zombie_required,
@@ -443,7 +443,8 @@ TEH_handler_melt (struct MHD_Connection *connection,
                                  &rmc.refresh_session.coin.denom_pub_hash),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("age_commitment_hash",
-                                   
&rmc.refresh_session.coin.h_age_commitment)),
+                                   &rmc.refresh_session.coin.h_age_commitment),
+      &rmc.refresh_session.coin.no_age_commitment),
     GNUNET_JSON_spec_fixed_auto ("confirm_sig",
                                  &rmc.refresh_session.coin_sig),
     TALER_JSON_spec_amount ("value_with_fee",
@@ -453,7 +454,8 @@ TEH_handler_melt (struct MHD_Connection *connection,
                                  &rmc.refresh_session.rc),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("rms",
-                                   &rmc.rms)),
+                                   &rmc.rms),
+      &rmc.no_rms),
     GNUNET_JSON_spec_end ()
   };
 
@@ -469,9 +471,6 @@ TEH_handler_melt (struct MHD_Connection *connection,
       return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES;
   }
 
-  rmc.have_rms = (NULL != json_object_get (root,
-                                           "rms"));
-
   {
     MHD_RESULT res;
 
diff --git a/src/exchange/taler-exchange-httpd_metrics.h 
b/src/exchange/taler-exchange-httpd_metrics.h
index a74fa44f..d1d20d9a 100644
--- a/src/exchange/taler-exchange-httpd_metrics.h
+++ b/src/exchange/taler-exchange-httpd_metrics.h
@@ -35,7 +35,8 @@ enum TEH_MetricTypeRequest
   TEH_MT_REQUEST_DEPOSIT = 1,
   TEH_MT_REQUEST_WITHDRAW = 2,
   TEH_MT_REQUEST_MELT = 3,
-  TEH_MT_REQUEST_COUNT = 4 /* MUST BE LAST! */
+  TEH_MT_REQUEST_PURSE_CREATE = 4,
+  TEH_MT_REQUEST_COUNT = 5 /* MUST BE LAST! */
 };
 
 /**
diff --git a/src/exchange/taler-exchange-httpd_purses_create.c 
b/src/exchange/taler-exchange-httpd_purses_create.c
index 326dad5c..610320da 100644
--- a/src/exchange/taler-exchange-httpd_purses_create.c
+++ b/src/exchange/taler-exchange-httpd_purses_create.c
@@ -63,6 +63,11 @@ struct Coin
    * Amount to be put into the purse from this coin.
    */
   struct TALER_Amount amount_minus_fee;
+
+  /**
+   * ID of the coin in known_coins.
+   */
+  uint64_t known_coin_id;
 };
 
 
@@ -141,6 +146,10 @@ struct PurseCreateContext
    */
   unsigned int num_coins;
 
+  /**
+   * Minimum age for deposits into this purse.
+   */
+  uint32_t min_age;
 };
 
 
@@ -165,7 +174,7 @@ reply_create_success (struct MHD_Connection *connection,
          pcc->exchange_timestamp,
          pcc->purse_expiration,
          &pcc->amount,
-         &pcc->total_deposited,
+         &pcc->deposit_total,
          pcc->purse_pub,
          &pcc->merge_pub,
          &pcc->h_contract_terms,
@@ -180,8 +189,8 @@ reply_create_success (struct MHD_Connection *connection,
   return TALER_MHD_REPLY_JSON_PACK (
     connection,
     MHD_HTTP_OK,
-    GNUNET_JSON_pack_amount ("total_deposited",
-                             &pcc->deposit_total),
+    TALER_JSON_pack_amount ("total_deposited",
+                            &pcc->deposit_total),
     GNUNET_JSON_pack_timestamp ("exchange_timestamp",
                                 pcc->exchange_timestamp),
     GNUNET_JSON_pack_data_auto ("exchange_sig",
@@ -215,7 +224,7 @@ create_transaction (void *cls,
 
   /* 1) create purse */
   qs = TEH_plugin->insert_purse_request (TEH_plugin->cls,
-                                         &pcc->purse_pub,
+                                         pcc->purse_pub,
                                          &pcc->merge_pub,
                                          pcc->purse_expiration,
                                          &pcc->h_contract_terms,
@@ -244,6 +253,7 @@ create_transaction (void *cls,
     struct TALER_Amount target_amount;
     struct TALER_Amount balance;
     struct TALER_PurseContractSignatureP purse_sig;
+    uint32_t min_age;
 
     TEH_plugin->rollback (TEH_plugin->cls);
     qs = TEH_plugin->select_purse_request (TEH_plugin->cls,
@@ -251,6 +261,7 @@ create_transaction (void *cls,
                                            &merge_pub,
                                            &purse_expiration,
                                            &h_contract_terms,
+                                           &min_age,
                                            &target_amount,
                                            &balance,
                                            &purse_sig);
@@ -270,8 +281,10 @@ create_transaction (void *cls,
           MHD_HTTP_CONFLICT,
           TALER_JSON_pack_ec (
             TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA),
-          GNUNET_JSON_pack_amount ("amount",
-                                   &amount),
+          TALER_JSON_pack_amount ("amount",
+                                  &target_amount),
+          GNUNET_JSON_pack_uint64 ("min_age",
+                                   min_age),
           GNUNET_JSON_pack_timestamp ("purse_expiration",
                                       purse_expiration),
           GNUNET_JSON_pack_data_auto ("purse_sig",
@@ -287,15 +300,17 @@ create_transaction (void *cls,
   {
     struct Coin *coin = &pcc->coins[i];
     bool balance_ok = false;
+    bool conflict = true;
 
     qs = TEH_plugin->do_purse_deposit (TEH_plugin->cls,
-                                       &pcc->purse_pub,
+                                       pcc->purse_pub,
                                        &coin->cpi.coin_pub,
                                        &coin->amount,
                                        &coin->coin_sig,
                                        &coin->amount_minus_fee,
-                                       &balance_ok);
-    if (qs < 0)
+                                       &balance_ok,
+                                       &conflict);
+    if (qs <= 0)
     {
       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
         return qs;
@@ -313,14 +328,58 @@ create_transaction (void *cls,
         = TEH_RESPONSE_reply_coin_insufficient_funds (
             connection,
             TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS,
-            &coin->pci.coin_pub);
+            &coin->cpi.coin_pub);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    if (conflict)
+    {
+      struct TALER_Amount amount;
+      struct TALER_CoinSpendPublicKeyP coin_pub;
+      struct TALER_CoinSpendSignatureP coin_sig;
+      char *partner_url = NULL;
+
+      TEH_plugin->rollback (TEH_plugin->cls);
+      qs = TEH_plugin->get_purse_deposit (TEH_plugin->cls,
+                                          pcc->purse_pub,
+                                          &coin->cpi.coin_pub,
+                                          &amount,
+                                          &coin_sig,
+                                          &partner_url);
+      if (qs < 0)
+      {
+        GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+        TALER_LOG_WARNING (
+          "Failed to fetch purse deposit information from database\n");
+        *mhd_ret = TALER_MHD_reply_with_error (connection,
+                                               MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                               
TALER_EC_GENERIC_DB_FETCH_FAILED,
+                                               "get purse deposit");
+        return GNUNET_DB_STATUS_HARD_ERROR;
+      }
+
+      *mhd_ret
+        = TALER_MHD_REPLY_JSON_PACK (
+            connection,
+            MHD_HTTP_CONFLICT,
+            TALER_JSON_pack_ec (
+              TALER_EC_EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA),
+            GNUNET_JSON_pack_data_auto ("coin_pub",
+                                        &coin_pub),
+            GNUNET_JSON_pack_data_auto ("coin_sig",
+                                        &coin_sig),
+            GNUNET_JSON_pack_allow_null (
+              GNUNET_JSON_pack_string ("partner_url",
+                                       partner_url)),
+            TALER_JSON_pack_amount ("amount",
+                                    &amount));
+      GNUNET_free (partner_url);
       return GNUNET_DB_STATUS_HARD_ERROR;
     }
   }
   /* 3) if present, persist contract */
   in_conflict = true;
   qs = TEH_plugin->insert_contract (TEH_plugin->cls,
-                                    &pcc->purse_pub,
+                                    pcc->purse_pub,
                                     &pcc->contract_pub,
                                     pcc->econtract_size,
                                     pcc->econtract,
@@ -345,12 +404,12 @@ create_transaction (void *cls,
     void *econtract;
     struct GNUNET_HashCode h_econtract;
 
-    qs = select_contract (cls,
-                          &pcc->purse_pub,
-                          &pub_ckey,
-                          &econtract_sig,
-                          &econtract_size,
-                          &econtract);
+    qs = TEH_plugin->select_contract (TEH_plugin->cls,
+                                      pcc->purse_pub,
+                                      &pub_ckey,
+                                      &econtract_sig,
+                                      &econtract_size,
+                                      &econtract);
     if (qs <= 0)
     {
       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -411,8 +470,8 @@ parse_coin (struct MHD_Connection *connection,
                                &coin->cpi.denom_sig),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
-                                   &coin->cpi.h_age_commitment)),
-    &coin->cpi.no_age_commitment),
+                                   &coin->cpi.h_age_commitment),
+      &coin->cpi.no_age_commitment),
     GNUNET_JSON_spec_fixed_auto ("coin_sig",
                                  &coin->coin_sig),
     GNUNET_JSON_spec_fixed_auto ("coin_pub",
@@ -432,10 +491,10 @@ parse_coin (struct MHD_Connection *connection,
 
   if (GNUNET_OK !=
       TALER_wallet_purse_deposit_verify (TEH_base_url,
-                                         &pcc->purse_pub,
+                                         pcc->purse_pub,
                                          &pcc->amount,
-                                         &coin->coin_pub,
-                                         &coin->csig))
+                                         &coin->cpi.coin_pub,
+                                         &coin->coin_sig))
   {
     TALER_LOG_WARNING ("Invalid signature on /purses/$PID/create request\n");
     GNUNET_JSON_parse_free (spec);
@@ -451,13 +510,13 @@ parse_coin (struct MHD_Connection *connection,
     struct TEH_DenominationKey *dk;
     MHD_RESULT mret;
 
-    dk = TEH_keys_denomination_by_hash (&coin->denom_pub_hash,
+    dk = TEH_keys_denomination_by_hash (&coin->cpi.denom_pub_hash,
                                         connection,
                                         &mret);
     if (NULL == dk)
     {
       GNUNET_JSON_parse_free (spec);
-      return (MHD_YES == mret) ? GNUNET_NO : GNUNET_SYSERR:
+      return (MHD_YES == mret) ? GNUNET_NO : GNUNET_SYSERR;
     }
     if (0 > TALER_amount_cmp (&dk->meta.value,
                               &coin->amount))
@@ -478,10 +537,10 @@ parse_coin (struct MHD_Connection *connection,
       return (MHD_YES ==
               TEH_RESPONSE_reply_expired_denom_pub_hash (
                 connection,
-                &coin->denom_pub_hash,
+                &coin->cpi.denom_pub_hash,
                 TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
                 "PURSE CREATE"))
-             ? GNUNET_NO : GNUNET_SYSERR:
+        ? GNUNET_NO : GNUNET_SYSERR;
     }
     if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
     {
@@ -490,7 +549,7 @@ parse_coin (struct MHD_Connection *connection,
       return (MHD_YES ==
               TEH_RESPONSE_reply_expired_denom_pub_hash (
                 connection,
-                &coin->denom_pub_hash,
+                &coin->cpi.denom_pub_hash,
                 TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
                 "PURSE CREATE"))
              ? GNUNET_NO : GNUNET_SYSERR;
@@ -502,12 +561,12 @@ parse_coin (struct MHD_Connection *connection,
       return (MHD_YES ==
               TEH_RESPONSE_reply_expired_denom_pub_hash (
                 connection,
-                &deposit.coin.denom_pub_hash,
+                &coin->cpi.denom_pub_hash,
                 TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
                 "PURSE CREATE"))
              ? GNUNET_NO : GNUNET_SYSERR;
     }
-    if (dk->denom_pub.cipher != deposit.coin.denom_sig.cipher)
+    if (dk->denom_pub.cipher != coin->cpi.denom_sig.cipher)
     {
       /* denomination cipher and denomination signature cipher not the same */
       GNUNET_JSON_parse_free (spec);
@@ -531,9 +590,9 @@ parse_coin (struct MHD_Connection *connection,
                                          NULL);
     }
     GNUNET_assert (0 <=
-                   TALER_amount_subtact (&coin->amount_minus_fee,
-                                         &coin->amount,
-                                         &coin->deposit_fee));
+                   TALER_amount_subtract (&coin->amount_minus_fee,
+                                          &coin->amount,
+                                          &coin->deposit_fee));
     /* check coin signature */
     switch (dk->denom_pub.cipher)
     {
@@ -547,7 +606,7 @@ parse_coin (struct MHD_Connection *connection,
       break;
     }
     if (GNUNET_YES !=
-        TALER_test_coin_valid (&deposit.coin,
+        TALER_test_coin_valid (&coin->cpi,
                                &dk->denom_pub))
     {
       TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
@@ -578,9 +637,9 @@ parse_coin (struct MHD_Connection *connection,
     /* make sure coin is 'known' in database */
     for (unsigned int tries = 0; tries<MAX_TRANSACTION_COMMIT_RETRIES; tries++)
     {
-      qs = TEH_make_coin_known (&deposit.coin,
+      qs = TEH_make_coin_known (&coin->cpi,
                                 connection,
-                                &pcc.known_coin_id,
+                                &coin->known_coin_id,
                                 &mhd_ret);
       /* no transaction => no serialization failures should be possible */
       if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
@@ -611,7 +670,7 @@ TEH_handler_purses_create (
 {
   struct PurseCreateContext pcc = {
     .purse_pub = purse_pub,
-    .exchange_timestamp = GNUNET_TIME_timestamp_get ();
+    .exchange_timestamp = GNUNET_TIME_timestamp_get ()
   };
   json_t *deposits;
   json_t *deposit;
@@ -623,15 +682,18 @@ TEH_handler_purses_create (
     GNUNET_JSON_spec_uint32 ("min_age",
                              &pcc.min_age),
     GNUNET_JSON_spec_mark_optional (
-      GNUNET_JSON_spec_var_size ("econtract",
-                                 &pcc.econtract,
-                                 &pcc.ecotract_size)),
+      GNUNET_JSON_spec_varsize ("econtract",
+                                &pcc.econtract,
+                                &pcc.econtract_size),
+      NULL),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("econtract_sig",
-                                   &pcc.econtract_sig)),
+                                   &pcc.econtract_sig),
+      NULL),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("contract_pub",
-                                   &pcc.contract_pub)),
+                                   &pcc.contract_pub),
+      NULL),
     GNUNET_JSON_spec_fixed_auto ("merge_pub",
                                  &pcc.merge_pub),
     GNUNET_JSON_spec_fixed_auto ("purse_sig",
@@ -694,7 +756,7 @@ TEH_handler_purses_create (
     GNUNET_JSON_parse_free (spec);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_BAD_REQUEST,
-                                       
TALER_EC_EXCHANGE_GENERIC_PARAMETER_MALFORMED,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
                                        "deposits");
   }
   gf = TEH_keys_global_fee_by_time (TEH_keys_get_state (),
@@ -709,8 +771,8 @@ TEH_handler_purses_create (
                                        NULL);
   }
   /* parse deposits */
-  pcc.coins = GNUNET_new_array (struct Coin,
-                                pcc.num_coins);
+  pcc.coins = GNUNET_new_array (pcc.num_coins,
+                                struct Coin);
   json_array_foreach (deposits, idx, deposit)
   {
     enum GNUNET_GenericReturnValue res;
@@ -742,12 +804,12 @@ TEH_handler_purses_create (
   TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
 
   if (GNUNET_OK !=
-      TALER_wallet_purse_create_verify (&pcc.purse_expiration,
+      TALER_wallet_purse_create_verify (pcc.purse_expiration,
                                         &pcc.h_contract_terms,
                                         &pcc.merge_pub,
                                         pcc.min_age,
                                         &pcc.amount,
-                                        &pcc.purse_pub,
+                                        pcc.purse_pub,
                                         &pcc.purse_sig))
   {
     TALER_LOG_WARNING ("Invalid signature on /purses/$PID/create request\n");
diff --git a/src/exchange/taler-exchange-httpd_purses_create.h 
b/src/exchange/taler-exchange-httpd_purses_create.h
new file mode 100644
index 00000000..4dfbabf9
--- /dev/null
+++ b/src/exchange/taler-exchange-httpd_purses_create.h
@@ -0,0 +1,47 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2022 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU Affero 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 Affero General Public License for more 
details.
+
+  You should have received a copy of the GNU Affero General Public License 
along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-exchange-httpd_purses_create.h
+ * @brief Handle /purses/$PID/create requests
+ * @author Christian Grothoff
+ */
+#ifndef TALER_EXCHANGE_HTTPD_PURSES_CREATE_H
+#define TALER_EXCHANGE_HTTPD_PURSES_CREATE_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include <microhttpd.h>
+#include "taler-exchange-httpd.h"
+
+
+/**
+ * Handle a "/purses/$PURSE_PUB/create" request.  Parses the JSON, and, if
+ * successful, passes the JSON data to #create_transaction() to further check
+ * the details of the operation specified.  If everything checks out, this
+ * will ultimately lead to the "purses create" being executed, or rejected.
+ *
+ * @param connection the MHD connection to handle
+ * @param purse_pub public key of the purse
+ * @param root uploaded JSON data
+ * @return MHD result code
+  */
+MHD_RESULT
+TEH_handler_purses_create (struct MHD_Connection *connection,
+                           const struct
+                           TALER_PurseContractPublicKeyP *purse_pub,
+                           const json_t *root);
+
+
+#endif
diff --git a/src/exchange/taler-exchange-httpd_recoup-refresh.c 
b/src/exchange/taler-exchange-httpd_recoup-refresh.c
index dbeadfbd..a00eeba4 100644
--- a/src/exchange/taler-exchange-httpd_recoup-refresh.c
+++ b/src/exchange/taler-exchange-httpd_recoup-refresh.c
@@ -390,10 +390,12 @@ TEH_handler_recoup_refresh (struct MHD_Connection 
*connection,
                                  &coin_sig),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
-                                   &coin.h_age_commitment)),
+                                   &coin.h_age_commitment),
+      &coin.no_age_commitment),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("cs_nonce",
-                                   &nonce)),
+                                   &nonce),
+      NULL),
     GNUNET_JSON_spec_end ()
   };
 
diff --git a/src/exchange/taler-exchange-httpd_recoup.c 
b/src/exchange/taler-exchange-httpd_recoup.c
index 101e7bff..6bda8af9 100644
--- a/src/exchange/taler-exchange-httpd_recoup.c
+++ b/src/exchange/taler-exchange-httpd_recoup.c
@@ -403,10 +403,12 @@ TEH_handler_recoup (struct MHD_Connection *connection,
                                  &coin_sig),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
-                                   &coin.h_age_commitment)),
+                                   &coin.h_age_commitment),
+      &coin.no_age_commitment),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("cs_nonce",
-                                   &nonce)),
+                                   &nonce),
+      NULL),
     GNUNET_JSON_spec_end ()
   };
 
diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c 
b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
index e1cf6ab2..8a5d8a80 100644
--- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
@@ -132,9 +132,9 @@ struct RevealContext
   unsigned int num_fresh_coins;
 
   /**
-   * True if @e rms was provided.
+   * True if @e rms was not provided.
    */
-  bool have_rms;
+  bool no_rms;
 };
 
 
@@ -337,9 +337,9 @@ check_commitment (struct RevealContext *rctx,
     }
     TALER_refresh_get_commitment (&rc_expected,
                                   TALER_CNC_KAPPA,
-                                  rctx->have_rms
-                                  ? &rctx->rms
-                                  : NULL,
+                                  rctx->no_rms
+                                  ? NULL
+                                  : &rctx->rms,
                                   rctx->num_fresh_coins,
                                   rcs,
                                   &rctx->melt.session.coin.coin_pub,
@@ -484,7 +484,7 @@ resolve_refreshes_reveal_denominations (struct 
MHD_Connection *connection,
     if (NULL == dks[i])
       return ret;
     if ( (TALER_DENOMINATION_CS == dks[i]->denom_pub.cipher) &&
-         (! rctx->have_rms) )
+         (rctx->no_rms) )
     {
       return TALER_MHD_reply_with_error (
         connection,
@@ -937,10 +937,12 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
                            &new_denoms_h),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_json ("old_age_commitment",
-                             &old_age_commitment)),
+                             &old_age_commitment),
+      NULL),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("rms",
-                                   &rctx.rms)),
+                                   &rctx.rms),
+      &rctx.no_rms),
     GNUNET_JSON_spec_end ()
   };
 
@@ -981,8 +983,6 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
       return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
     }
   }
-  rctx.have_rms = (NULL != json_object_get (root,
-                                            "rms"));
 
   /* Check we got enough transfer private keys */
   /* Note we do +1 as 1 row (cut-and-choose!) is missing! */
diff --git a/src/exchangedb/exchange-0001-part.sql 
b/src/exchangedb/exchange-0001-part.sql
index c068ff6f..2c416f03 100644
--- a/src/exchangedb/exchange-0001-part.sql
+++ b/src/exchangedb/exchange-0001-part.sql
@@ -2469,22 +2469,108 @@ END $$;
 
 
 
-
-
-
-
 CREATE OR REPLACE FUNCTION exchange_do_purse_deposit(
+  IN in_partner_id INT8,
   IN in_purse_pub BYTEA,
   IN in_amount_with_fee_val INT8,
   IN in_amount_with_fee_frac INT4,
   IN in_coin_pub BYTEA,
   IN in_coin_sig BYTEA,
+  IN in_amount_without_fee_val INT8,
+  IN in_amount_without_fee_frac INT4,
   OUT out_balance_ok BOOLEAN,
   OUT out_conflict BOOLEAN)
 LANGUAGE plpgsql
 AS $$
 BEGIN
-  -- FIXME
+
+-- Store the deposit request.
+INSERT INTO purse_deposits
+  (partner_serial_id
+  ,purse_pub
+  ,coin_pub
+  ,amount_with_fee_val
+  ,amount_with_fee_frac
+  ,coin_sig)
+  VALUES
+  (in_partner_id
+  ,in_purse_pub
+  ,in_coin_pub
+  ,in_amount_with_fee_val
+  ,in_amount_with_fee_frac
+  ,in_coin_sig)
+  ON CONFLICT DO NOTHING;
+
+IF NOT FOUND
+THEN
+  -- Idempotency check: check if coin_sig is the same,
+  -- if so, success, otherwise conflict!
+  SELECT
+    1
+  FROM purse_deposits
+  WHERE coin_pub = in_coin_pub
+    AND purse_pub = in_purse_pub
+    AND coin_sig = in_cion_sig;
+  IF NOT FOUND
+  THEN
+    -- Deposit exists, but with differences. Not allowed.
+    out_balance_ok=FALSE;
+    out_conflict=TRUE;
+    RETURN;
+  END IF;
+END IF;
+
+
+-- Debit the coin
+-- Check and update balance of the coin.
+UPDATE known_coins
+  SET
+    remaining_frac=remaining_frac-in_amount_with_fee_frac
+       + CASE
+         WHEN remaining_frac < in_amount_with_fee_frac
+         THEN 100000000
+         ELSE 0
+         END,
+    remaining_val=remaining_val-in_amount_with_fee_val
+       - CASE
+         WHEN remaining_frac < in_amount_with_fee_frac
+         THEN 1
+         ELSE 0
+         END
+  WHERE coin_pub=in_coin_pub
+    AND ( (remaining_val > in_amount_with_fee_val) OR
+          ( (remaining_frac >= in_amount_with_fee_frac) AND
+            (remaining_val >= in_amount_with_fee_val) ) );
+
+IF NOT FOUND
+THEN
+  -- Insufficient balance.
+  out_balance_ok=FALSE;
+  out_conflict=FALSE;
+  RETURN;
+END IF;
+
+
+-- Credit the purse.
+UPDATE purse_requests
+  SET
+    balance_frac=balance_frac+in_amount_without_fee_frac
+       - CASE
+         WHEN balance_frac+in_amount_without_fee_frac >= 100000000
+         THEN 100000000
+         ELSE 0
+         END,
+    balance_val=balance_val+in_amount_without_fee_val
+       + CASE
+         WHEN balance_frac+in_amount_without_fee_frac >= 100000000
+         THEN 1
+         ELSE 0
+         END
+  WHERE purse_pub=in_purse_pub;
+
+out_conflict=FALSE;
+out_balance_ok=TRUE;
+
 END $$;
 
 
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index 64cc0a77..aed69725 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -799,6 +799,15 @@ prepare_statements (struct PostgresClosure *pg)
       " FROM exchange_do_deposit"
       " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17);",
       17),
+    /* used in postgres_do_purse_deposit() */
+    GNUNET_PQ_make_prepare (
+      "call_purse_deposit",
+      "SELECT "
+      " out_balance_ok AS balance_ok"
+      ",out_conflict AS conflict"
+      " FROM exchange_do_purse_deposit"
+      " ($1,$2,$3,$4,$5,$6,$7,$8);",
+      8),
     /* Used in #postgres_do_melt() to melt a coin. */
     GNUNET_PQ_make_prepare (
       "call_melt",
@@ -3342,13 +3351,19 @@ prepare_statements (struct PostgresClosure *pg)
       " FROM purse_requests"
       " WHERE merge_pub=$1;",
       1),
-    /* Used in #postgres_do_purse_deposit() */
+    /* Used in #postgres_get_purse_deposit */
     GNUNET_PQ_make_prepare (
-      "call_purse_deposit",
-      "SELECT 1"
-      " FROM exchange_do_purse_deposit"
-      "  ($1, $2, $3, $4, $5);",
-      5),
+      "select_purse_deposit_by_coin_pub",
+      "SELECT "
+      " coin_sig"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",partner_base_url"
+      " FROM purse_deposits"
+      " LEFT JOIN partners USING (partner_serial_id)"
+      " WHERE coin_pub=$2"
+      "   AND purse_pub=$1;",
+      2),
     /* Used in #postgres_do_purse_merge() */
     GNUNET_PQ_make_prepare (
       "call_purse_merge",
@@ -13181,10 +13196,79 @@ postgres_do_purse_deposit (
   const struct TALER_Amount *amount,
   const struct TALER_CoinSpendSignatureP *coin_sig,
   const struct TALER_Amount *amount_minus_fee,
-  bool *balance_ok)
+  bool *balance_ok,
+  bool *conflict)
 {
-  GNUNET_break (0); // FIXME
-  return GNUNET_DB_STATUS_HARD_ERROR;
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (0), /* FIXME: partner ID */
+    GNUNET_PQ_query_param_auto_from_type (purse_pub),
+    TALER_PQ_query_param_amount (amount),
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (coin_sig),
+    TALER_PQ_query_param_amount (amount_minus_fee),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_bool ("balance_ok",
+                                balance_ok),
+    GNUNET_PQ_result_spec_bool ("conflict",
+                                conflict),
+    GNUNET_PQ_result_spec_end
+  };
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "call_purse_deposit",
+                                                   params,
+                                                   rs);
+}
+
+
+/**
+ * Function called to obtain a coin deposit data from
+ * depositing the coin into a purse.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub purse to credit
+ * @param coin_pub coin to deposit (debit)
+ * @param[out] amount set fraction of the coin's value that was deposited 
(with fee)
+ * @param[out] coin_sig set to signature affirming the operation
+ * @param[out] partner_url set to the URL of the partner exchange, or NULL for 
ourselves, must be freed by caller
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_get_purse_deposit (
+  void *cls,
+  const struct TALER_PurseContractPublicKeyP *purse_pub,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  struct TALER_Amount *amount,
+  struct TALER_CoinSpendSignatureP *coin_sig,
+  char **partner_url)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (purse_pub),
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_end
+  };
+  bool is_null;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+                                          coin_sig),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                 amount),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_string ("partner_base_url",
+                                    partner_url),
+      &is_null),
+    GNUNET_PQ_result_spec_end
+  };
+
+  *partner_url = NULL;
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"select_purse_deposit_by_coin_pub",
+                                                   params,
+                                                   rs);
 }
 
 
@@ -13589,6 +13673,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
     = &postgres_select_purse_by_merge_pub;
   plugin->do_purse_deposit
     = &postgres_do_purse_deposit;
+  plugin->get_purse_deposit
+    = &postgres_get_purse_deposit;
   plugin->do_purse_merge
     = &postgres_do_purse_merge;
   plugin->select_purse_merge
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 9c9410d6..c065f581 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -4567,6 +4567,8 @@ struct TALER_EXCHANGEDB_Plugin
    *        remaining balance is below @a amount;
    *             in this case, the return value will be
    *             #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure
+   * @param[out] conflict the same coin was deposited into
+   *        this purse with a different amount already
    * @return transaction status code
    */
   enum GNUNET_DB_QueryStatus
@@ -4577,7 +4579,30 @@ struct TALER_EXCHANGEDB_Plugin
     const struct TALER_Amount *amount,
     const struct TALER_CoinSpendSignatureP *coin_sig,
     const struct TALER_Amount *amount_minus_fee,
-    bool *balance_ok);
+    bool *balance_ok,
+    bool *conflict);
+
+
+  /**
+   * Function called to obtain a coin deposit data from
+   * depositing the coin into a purse.
+   *
+   * @param cls the @e cls of this struct with the plugin-specific state
+   * @param purse_pub purse to credit
+   * @param coin_pub coin to deposit (debit)
+   * @param[out] amount set fraction of the coin's value that was deposited 
(with fee)
+   * @param[out] coin_sig set to signature affirming the operation
+   * @param[out] partner_url set to the URL of the partner exchange, or NULL 
for ourselves, must be freed by caller
+   * @return transaction status code
+   */
+  enum GNUNET_DB_QueryStatus
+  (*get_purse_deposit)(
+    void *cls,
+    const struct TALER_PurseContractPublicKeyP *purse_pub,
+    const struct TALER_CoinSpendPublicKeyP *coin_pub,
+    struct TALER_Amount *amount,
+    struct TALER_CoinSpendSignatureP *coin_sig,
+    char **partner_url);
 
 
   /**
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c
index df1c43e4..04f2a4df 100644
--- a/src/lib/exchange_api_common.c
+++ b/src/lib/exchange_api_common.c
@@ -447,7 +447,8 @@ TALER_EXCHANGE_verify_coin_history (
       struct TALER_MerchantPublicKeyP merchant_pub;
       struct GNUNET_TIME_Timestamp refund_deadline = {0};
       struct TALER_CoinSpendSignatureP sig;
-      struct TALER_AgeCommitmentHash hac = {0};
+      struct TALER_AgeCommitmentHash hac;
+      bool no_hac;
       struct GNUNET_JSON_Specification spec[] = {
         GNUNET_JSON_spec_fixed_auto ("coin_sig",
                                      &sig),
@@ -459,12 +460,14 @@ TALER_EXCHANGE_verify_coin_history (
                                      h_denom_pub),
         GNUNET_JSON_spec_mark_optional (
           GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
-                                       &hac)),
+                                       &hac),
+          &no_hac),
         GNUNET_JSON_spec_timestamp ("timestamp",
                                     &wallet_timestamp),
         GNUNET_JSON_spec_mark_optional (
           GNUNET_JSON_spec_timestamp ("refund_deadline",
-                                      &refund_deadline)),
+                                      &refund_deadline),
+          NULL),
         TALER_JSON_spec_amount_any ("deposit_fee",
                                     &fee),
         GNUNET_JSON_spec_fixed_auto ("merchant_pub",
@@ -486,7 +489,7 @@ TALER_EXCHANGE_verify_coin_history (
             &fee,
             &h_wire,
             &h_contract_terms,
-            TALER_AgeCommitmentHash_isNullOrZero (&hac) ?  NULL : &hac,
+            no_hac ? NULL : &hac,
             NULL /* h_extensions! */,
             h_denom_pub,
             wallet_timestamp,
@@ -519,7 +522,8 @@ TALER_EXCHANGE_verify_coin_history (
     {
       struct TALER_CoinSpendSignatureP sig;
       struct TALER_RefreshCommitmentP rc;
-      struct TALER_AgeCommitmentHash h_age_commitment = {0};
+      struct TALER_AgeCommitmentHash h_age_commitment;
+      bool no_hac;
       struct GNUNET_JSON_Specification spec[] = {
         GNUNET_JSON_spec_fixed_auto ("coin_sig",
                                      &sig),
@@ -529,7 +533,8 @@ TALER_EXCHANGE_verify_coin_history (
                                      h_denom_pub),
         GNUNET_JSON_spec_mark_optional (
           GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
-                                       &h_age_commitment)),
+                                       &h_age_commitment),
+          &no_hac),
         TALER_JSON_spec_amount_any ("melt_fee",
                                     &fee),
         GNUNET_JSON_spec_end ()
@@ -566,8 +571,9 @@ TALER_EXCHANGE_verify_coin_history (
             &fee,
             &rc,
             h_denom_pub,
-            TALER_AgeCommitmentHash_isNullOrZero (&h_age_commitment) ?
-            NULL : &h_age_commitment,
+            no_hac
+            ? NULL
+            : &h_age_commitment,
             coin_pub,
             &sig))
       {
diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c
index 947a4256..67f595bf 100644
--- a/src/lib/exchange_api_deposit.c
+++ b/src/lib/exchange_api_deposit.c
@@ -333,7 +333,8 @@ handle_deposit_finished (void *cls,
                                      &dh->exchange_pub),
         GNUNET_JSON_spec_mark_optional (
           GNUNET_JSON_spec_string ("transaction_base_url",
-                                   &dr.details.success.transaction_base_url)),
+                                   &dr.details.success.transaction_base_url),
+          NULL),
         GNUNET_JSON_spec_timestamp ("exchange_timestamp",
                                     &dh->exchange_timestamp),
         GNUNET_JSON_spec_end ()
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index feab4ac4..6528c56d 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -750,7 +750,8 @@ decode_keys_json (const json_t *resp_obj,
                              &currency),
     GNUNET_JSON_spec_mark_optional (
       TALER_JSON_spec_amount_any ("wallet_balance_limit_without_kyc",
-                                  
&key_data->wallet_balance_limit_without_kyc)),
+                                  &key_data->wallet_balance_limit_without_kyc),
+      NULL),
     GNUNET_JSON_spec_end ()
   };
 
@@ -895,11 +896,13 @@ decode_keys_json (const json_t *resp_obj,
     struct GNUNET_JSON_Specification ext_spec[] = {
       GNUNET_JSON_spec_mark_optional (
         GNUNET_JSON_spec_json ("extensions",
-                               &extensions)),
+                               &extensions),
+        NULL),
       GNUNET_JSON_spec_mark_optional (
         GNUNET_JSON_spec_fixed_auto (
           "extensions_sig",
-          &extensions_sig)),
+          &extensions_sig),
+        NULL),
       GNUNET_JSON_spec_end ()
     };
 
diff --git a/src/lib/exchange_api_link.c b/src/lib/exchange_api_link.c
index 5840cac6..ddc763c3 100644
--- a/src/lib/exchange_api_link.c
+++ b/src/lib/exchange_api_link.c
@@ -97,6 +97,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
   union TALER_DenominationBlindingKeyP bks;
   struct TALER_ExchangeWithdrawValues alg_values;
   struct TALER_CsNonce nonce;
+  bool no_nonce;
   uint32_t coin_idx;
   struct GNUNET_JSON_Specification spec[] = {
     TALER_JSON_spec_denom_pub ("denom_pub",
@@ -111,7 +112,8 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
                              &coin_idx),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("cs_nonce",
-                                   &nonce)),
+                                   &nonce),
+      &no_nonce),
     GNUNET_JSON_spec_end ()
   };
   struct TALER_TransferSecretP secret;
@@ -119,9 +121,6 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
   struct TALER_CoinPubHashP c_hash;
 
   /* parse reply */
-  memset (&nonce,
-          0,
-          sizeof (nonce));
   if (GNUNET_OK !=
       GNUNET_JSON_parse (json,
                          spec,
@@ -180,7 +179,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
   }
   if (TALER_DENOMINATION_CS == alg_values.cipher)
   {
-    if (GNUNET_is_zero (&nonce))
+    if (no_nonce)
     {
       GNUNET_break_op (0);
       GNUNET_JSON_parse_free (spec);
diff --git a/src/lib/exchange_api_purse_create_with_deposit.c 
b/src/lib/exchange_api_purse_create_with_deposit.c
index d8f86de0..f5871fa3 100644
--- a/src/lib/exchange_api_purse_create_with_deposit.c
+++ b/src/lib/exchange_api_purse_create_with_deposit.c
@@ -259,7 +259,7 @@ TALER_EXCHANGE_purse_create_with_deposit (
   struct TALER_ContractDiffiePublicP contract_pub;
   char arg_str[sizeof (pch->purse_pub) * 2 + 32];
   char *url;
-  uint32_t min_age;
+  uint32_t min_age = 0;
 
   pch = GNUNET_new (struct TALER_EXCHANGE_PurseCreateDepositHandle);
   pch->exchange = exchange;
@@ -272,7 +272,8 @@ TALER_EXCHANGE_purse_create_with_deposit (
                                   &pch->purse_value_after_fees),
       GNUNET_JSON_spec_mark_optional (
         GNUNET_JSON_spec_uint32 ("minimum_age",
-                                 &min_age)),
+                                 &min_age),
+        NULL),
       GNUNET_JSON_spec_end ()
     };
 
diff --git a/src/lib/exchange_api_refund.c b/src/lib/exchange_api_refund.c
index 6369a5bd..004661b0 100644
--- a/src/lib/exchange_api_refund.c
+++ b/src/lib/exchange_api_refund.c
@@ -231,7 +231,8 @@ verify_conflict_history_ok (struct 
TALER_EXCHANGE_RefundHandle *rh,
       struct TALER_Amount deposit_fee;
       struct TALER_MerchantWireHashP h_wire;
       struct TALER_PrivateContractHashP h_contract_terms;
-      struct TALER_AgeCommitmentHash h_age_commitment = {{{0}}};
+      struct TALER_AgeCommitmentHash h_age_commitment;
+      bool no_hac;
       // struct TALER_ExtensionContractHashP h_extensions; // FIXME!
       struct TALER_DenominationHashP h_denom_pub;
       struct GNUNET_TIME_Timestamp wallet_timestamp;
@@ -249,7 +250,8 @@ verify_conflict_history_ok (struct 
TALER_EXCHANGE_RefundHandle *rh,
                                      &h_denom_pub),
         GNUNET_JSON_spec_mark_optional (
           GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
-                                       &h_age_commitment)),
+                                       &h_age_commitment),
+          &no_hac),
         GNUNET_JSON_spec_timestamp ("timestamp",
                                     &wallet_timestamp),
         GNUNET_JSON_spec_timestamp ("refund_deadline",
@@ -275,8 +277,10 @@ verify_conflict_history_ok (struct 
TALER_EXCHANGE_RefundHandle *rh,
                                        &deposit_fee,
                                        &h_wire,
                                        &h_contract_terms,
-                                       &h_age_commitment,
-                                       NULL /* h_extensions! */,
+                                       no_hac
+                                       ? NULL
+                                       : &h_age_commitment,
+                                       NULL /* FIXME-OEC: h_extensions! */,
                                        &h_denom_pub,
                                        wallet_timestamp,
                                        &merchant_pub,
diff --git a/src/testing/testing_api_cmd_auditor_deposit_confirmation.c 
b/src/testing/testing_api_cmd_auditor_deposit_confirmation.c
index beeeb551..d99b1293 100644
--- a/src/testing/testing_api_cmd_auditor_deposit_confirmation.c
+++ b/src/testing/testing_api_cmd_auditor_deposit_confirmation.c
@@ -291,7 +291,8 @@ deposit_confirmation_run (void *cls,
                                   &timestamp),
       GNUNET_JSON_spec_mark_optional (
         GNUNET_JSON_spec_timestamp ("refund_deadline",
-                                    &refund_deadline)),
+                                    &refund_deadline),
+        NULL),
       GNUNET_JSON_spec_end ()
     };
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]