exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

test_exchangedb.c (92931B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014-2025 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file exchangedb/test_exchangedb.c
     18  * @brief test cases for DB interaction functions
     19  * @author Sree Harsha Totakura
     20  * @author Christian Grothoff
     21  * @author Marcello Stanisci
     22  * @author Özgür Kesim
     23  */
     24 #include "taler/platform.h"
     25 #include "taler/taler_exchangedb_lib.h"
     26 #include "taler/taler_json_lib.h"
     27 #include "taler/taler_exchangedb_plugin.h"
     28 
     29 /**
     30  * Global result from the testcase.
     31  */
     32 static int result;
     33 
     34 /**
     35  * Report line of error if @a cond is true, and jump to label "drop".
     36  */
     37 #define FAILIF(cond)                            \
     38         do {                                          \
     39           if (! (cond)) { break;}                     \
     40           GNUNET_break (0);                           \
     41           goto drop;                                  \
     42         } while (0)
     43 
     44 
     45 /**
     46  * Initializes @a ptr with random data.
     47  */
     48 #define RND_BLK(ptr)                                                    \
     49         GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, \
     50                                     sizeof (*ptr))
     51 
     52 /**
     53  * Initializes @a ptr with zeros.
     54  */
     55 #define ZR_BLK(ptr) \
     56         memset (ptr, 0, sizeof (*ptr))
     57 
     58 
     59 /**
     60  * Currency we use.  Must match test-exchange-db-*.conf.
     61  */
     62 #define CURRENCY "EUR"
     63 
     64 /**
     65  * Database plugin under test.
     66  */
     67 static struct TALER_EXCHANGEDB_Plugin *plugin;
     68 
     69 
     70 /**
     71  * Callback that should never be called.
     72  */
     73 static void
     74 dead_prepare_cb (void *cls,
     75                  uint64_t rowid,
     76                  const char *wire_method,
     77                  const char *buf,
     78                  size_t buf_size)
     79 {
     80   (void) cls;
     81   (void) rowid;
     82   (void) wire_method;
     83   (void) buf;
     84   (void) buf_size;
     85   GNUNET_assert (0);
     86 }
     87 
     88 
     89 /**
     90  * Callback that is called with wire prepare data
     91  * and then marks it as finished.
     92  */
     93 static void
     94 mark_prepare_cb (void *cls,
     95                  uint64_t rowid,
     96                  const char *wire_method,
     97                  const char *buf,
     98                  size_t buf_size)
     99 {
    100   (void) cls;
    101   GNUNET_assert (11 == buf_size);
    102   GNUNET_assert (0 == strcasecmp (wire_method,
    103                                   "testcase"));
    104   GNUNET_assert (0 == memcmp (buf,
    105                               "hello world",
    106                               buf_size));
    107   GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    108                 plugin->wire_prepare_data_mark_finished (plugin->cls,
    109                                                          rowid));
    110 }
    111 
    112 
    113 /**
    114  * Simple check that config retrieval and setting for extensions work
    115  */
    116 static enum GNUNET_GenericReturnValue
    117 test_extension_manifest (void)
    118 {
    119   char *manifest;
    120 
    121   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    122           plugin->get_extension_manifest (plugin->cls,
    123                                           "fnord",
    124                                           &manifest));
    125 
    126   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    127           plugin->set_extension_manifest (plugin->cls,
    128                                           "fnord",
    129                                           "bar"));
    130   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    131           plugin->get_extension_manifest (plugin->cls,
    132                                           "fnord",
    133                                           &manifest));
    134 
    135   FAILIF (0 != strcmp ("bar", manifest));
    136   GNUNET_free (manifest);
    137 
    138   /* let's do this again! */
    139   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    140           plugin->set_extension_manifest (plugin->cls,
    141                                           "fnord",
    142                                           "buzz"));
    143 
    144   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    145           plugin->get_extension_manifest (plugin->cls,
    146                                           "fnord",
    147                                           &manifest));
    148 
    149   FAILIF (0 != strcmp ("buzz", manifest));
    150   GNUNET_free (manifest);
    151 
    152   /* let's do this again, with NULL */
    153   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    154           plugin->set_extension_manifest (plugin->cls,
    155                                           "fnord",
    156                                           NULL));
    157 
    158   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    159           plugin->get_extension_manifest (plugin->cls,
    160                                           "fnord",
    161                                           &manifest));
    162 
    163   FAILIF (NULL != manifest);
    164 
    165   return GNUNET_OK;
    166 drop:
    167   return GNUNET_SYSERR;
    168 }
    169 
    170 
    171 /**
    172  * Test API relating to persisting the wire plugins preparation data.
    173  *
    174  * @return #GNUNET_OK on success
    175  */
    176 static enum GNUNET_GenericReturnValue
    177 test_wire_prepare (void)
    178 {
    179   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    180           plugin->wire_prepare_data_get (plugin->cls,
    181                                          0,
    182                                          1,
    183                                          &dead_prepare_cb,
    184                                          NULL));
    185   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    186           plugin->wire_prepare_data_insert (plugin->cls,
    187                                             "testcase",
    188                                             "hello world",
    189                                             11));
    190   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    191           plugin->wire_prepare_data_get (plugin->cls,
    192                                          0,
    193                                          1,
    194                                          &mark_prepare_cb,
    195                                          NULL));
    196   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    197           plugin->wire_prepare_data_get (plugin->cls,
    198                                          0,
    199                                          1,
    200                                          &dead_prepare_cb,
    201                                          NULL));
    202   return GNUNET_OK;
    203 drop:
    204   return GNUNET_SYSERR;
    205 }
    206 
    207 
    208 /**
    209  * Checks if the given reserve has the given amount of balance and expiry
    210  *
    211  * @param pub the public key of the reserve
    212  * @param value balance value
    213  * @param fraction balance fraction
    214  * @param currency currency of the reserve
    215  * @return #GNUNET_OK if the given reserve has the same balance and expiration
    216  *           as the given parameters; #GNUNET_SYSERR if not
    217  */
    218 static enum GNUNET_GenericReturnValue
    219 check_reserve (const struct TALER_ReservePublicKeyP *pub,
    220                uint64_t value,
    221                uint32_t fraction,
    222                const char *currency)
    223 {
    224   struct TALER_EXCHANGEDB_Reserve reserve;
    225 
    226   reserve.pub = *pub;
    227   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    228           plugin->reserves_get (plugin->cls,
    229                                 &reserve));
    230   FAILIF (value != reserve.balance.value);
    231   FAILIF (fraction != reserve.balance.fraction);
    232   FAILIF (0 != strcmp (currency,
    233                        reserve.balance.currency));
    234   return GNUNET_OK;
    235 drop:
    236   return GNUNET_SYSERR;
    237 }
    238 
    239 
    240 struct DenomKeyPair
    241 {
    242   struct TALER_DenominationPrivateKey priv;
    243   struct TALER_DenominationPublicKey pub;
    244 };
    245 
    246 
    247 /**
    248  * Destroy a denomination key pair.  The key is not necessarily removed from the DB.
    249  *
    250  * @param dkp the key pair to destroy
    251  */
    252 static void
    253 destroy_denom_key_pair (struct DenomKeyPair *dkp)
    254 {
    255   TALER_denom_pub_free (&dkp->pub);
    256   TALER_denom_priv_free (&dkp->priv);
    257   GNUNET_free (dkp);
    258 }
    259 
    260 
    261 /**
    262  * Create a denomination key pair by registering the denomination in the DB.
    263  *
    264  * @param size the size of the denomination key
    265  * @param now time to use for key generation, legal expiration will be 3h later.
    266  * @param fees fees to use
    267  * @return the denominaiton key pair; NULL upon error
    268  */
    269 static struct DenomKeyPair *
    270 create_denom_key_pair (unsigned int size,
    271                        struct GNUNET_TIME_Timestamp now,
    272                        const struct TALER_Amount *value,
    273                        const struct TALER_DenomFeeSet *fees)
    274 {
    275   struct DenomKeyPair *dkp;
    276   struct TALER_EXCHANGEDB_DenominationKey dki;
    277   struct TALER_EXCHANGEDB_DenominationKeyInformation issue2;
    278 
    279   dkp = GNUNET_new (struct DenomKeyPair);
    280   GNUNET_assert (GNUNET_OK ==
    281                  TALER_denom_priv_create (&dkp->priv,
    282                                           &dkp->pub,
    283                                           GNUNET_CRYPTO_BSA_RSA,
    284                                           size));
    285   /* Using memset() as fields like master key and signature
    286      are not properly initialized for this test. */
    287   memset (&dki,
    288           0,
    289           sizeof (struct TALER_EXCHANGEDB_DenominationKey));
    290   dki.denom_pub = dkp->pub;
    291   dki.issue.start = now;
    292   dki.issue.expire_withdraw
    293     = GNUNET_TIME_absolute_to_timestamp (
    294         GNUNET_TIME_absolute_add (
    295           now.abs_time,
    296           GNUNET_TIME_UNIT_HOURS));
    297   dki.issue.expire_deposit
    298     = GNUNET_TIME_absolute_to_timestamp (
    299         GNUNET_TIME_absolute_add (
    300           now.abs_time,
    301           GNUNET_TIME_relative_multiply (
    302             GNUNET_TIME_UNIT_HOURS, 2)));
    303   dki.issue.expire_legal
    304     = GNUNET_TIME_absolute_to_timestamp (
    305         GNUNET_TIME_absolute_add (
    306           now.abs_time,
    307           GNUNET_TIME_relative_multiply (
    308             GNUNET_TIME_UNIT_HOURS, 3)));
    309   dki.issue.value = *value;
    310   dki.issue.fees = *fees;
    311   TALER_denom_pub_hash (&dkp->pub,
    312                         &dki.issue.denom_hash);
    313   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    314       plugin->insert_denomination_info (plugin->cls,
    315                                         &dki.denom_pub,
    316                                         &dki.issue))
    317   {
    318     GNUNET_break (0);
    319     destroy_denom_key_pair (dkp);
    320     return NULL;
    321   }
    322   memset (&issue2, 0, sizeof (issue2));
    323   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    324       plugin->get_denomination_info (plugin->cls,
    325                                      &dki.issue.denom_hash,
    326                                      NULL,
    327                                      &issue2))
    328   {
    329     GNUNET_break (0);
    330     destroy_denom_key_pair (dkp);
    331     return NULL;
    332   }
    333   if (0 != GNUNET_memcmp (&dki.issue,
    334                           &issue2))
    335   {
    336     GNUNET_break (0);
    337     destroy_denom_key_pair (dkp);
    338     return NULL;
    339   }
    340   return dkp;
    341 }
    342 
    343 
    344 static struct TALER_Amount global_amount;
    345 static struct TALER_Amount global_value;
    346 static struct TALER_DenomFeeSet global_fees;
    347 static struct TALER_Amount fee_closing;
    348 
    349 
    350 /**
    351  * Number of newly minted coins to use in the test.
    352  */
    353 #define MELT_NEW_COINS 5
    354 
    355 /**
    356  * Which index was 'randomly' chosen for the reveal for the test?
    357  */
    358 #define MELT_NOREVEAL_INDEX 1
    359 
    360 /**
    361  * How big do we make the RSA keys?
    362  */
    363 #define RSA_KEY_SIZE 1024
    364 
    365 static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;
    366 
    367 static struct TALER_TransferPrivateKeyP tprivs[TALER_CNC_KAPPA];
    368 
    369 static struct TALER_TransferPublicKeyP tpub;
    370 
    371 
    372 /**
    373  * Function called with information about a refresh order.  This
    374  * one should not be called in a successful test.
    375  *
    376  * @param cls closure
    377  * @param rowid unique serial ID for the row in our database
    378  * @param num_freshcoins size of the @a rrcs array
    379  * @param rrcs array of @a num_freshcoins information about coins to be created
    380  */
    381 static void
    382 never_called_cb (void *cls,
    383                  uint32_t num_freshcoins,
    384                  const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs)
    385 {
    386   (void) cls;
    387   (void) num_freshcoins;
    388   (void) rrcs;
    389   GNUNET_assert (0); /* should never be called! */
    390 }
    391 
    392 
    393 /**
    394  * Function called with information about a refresh order.
    395  * Checks that the response matches what we expect to see.
    396  *
    397  * @param cls closure
    398  * @param rowid unique serial ID for the row in our database
    399  * @param num_freshcoins size of the @a rrcs array
    400  * @param rrcs array of @a num_freshcoins information about coins to be created
    401  */
    402 static void
    403 check_refresh_reveal_cb (
    404   void *cls,
    405   uint32_t num_freshcoins,
    406   const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs)
    407 {
    408   (void) cls;
    409   /* compare the refresh commit coin arrays */
    410   for (unsigned int cnt = 0; cnt < num_freshcoins; cnt++)
    411   {
    412     const struct TALER_EXCHANGEDB_RefreshRevealedCoin *acoin =
    413       &revealed_coins[cnt];
    414     const struct TALER_EXCHANGEDB_RefreshRevealedCoin *bcoin = &rrcs[cnt];
    415 
    416     GNUNET_assert (0 ==
    417                    TALER_blinded_planchet_cmp (&acoin->blinded_planchet,
    418                                                &bcoin->blinded_planchet));
    419     GNUNET_assert (0 ==
    420                    GNUNET_memcmp (&acoin->h_denom_pub,
    421                                   &bcoin->h_denom_pub));
    422   }
    423 }
    424 
    425 
    426 /**
    427  * Counter used in auditor-related db functions. Used to count
    428  * expected rows.
    429  */
    430 static unsigned int auditor_row_cnt;
    431 
    432 
    433 /**
    434  * Function called with details about coins that were melted,
    435  * with the goal of auditing the refresh's execution.
    436  *
    437  *
    438  * @param cls closure
    439  * @param rowid unique serial ID for the refresh session in our DB
    440  * @param denom_pub denomination of the @a coin_pub
    441  * @param h_age_commitment hash of age commitment that went into the minting, may be NULL
    442  * @param coin_pub public key of the coin
    443  * @param coin_sig signature from the coin
    444  * @param amount_with_fee amount that was deposited including fee
    445  * @param num_freshcoins how many coins were issued
    446  * @param noreveal_index which index was picked by the exchange in cut-and-choose
    447  * @param rc what is the session hash
    448  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
    449  */
    450 static enum GNUNET_GenericReturnValue
    451 audit_refresh_session_cb (
    452   void *cls,
    453   uint64_t rowid,
    454   const struct TALER_DenominationPublicKey *denom_pub,
    455   const struct TALER_AgeCommitmentHashP *h_age_commitment,
    456   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    457   const struct TALER_CoinSpendSignatureP *coin_sig,
    458   const struct TALER_Amount *amount_with_fee,
    459   uint32_t noreveal_index,
    460   const struct TALER_RefreshCommitmentP *rc)
    461 {
    462   (void) cls;
    463   (void) rowid;
    464   (void) denom_pub;
    465   (void) coin_pub;
    466   (void) coin_sig;
    467   (void) amount_with_fee;
    468   (void) noreveal_index;
    469   (void) rc;
    470   (void) h_age_commitment;
    471   auditor_row_cnt++;
    472   return GNUNET_OK;
    473 }
    474 
    475 
    476 /**
    477  * Denomination keys used for fresh coins in melt test.
    478  */
    479 static struct DenomKeyPair **new_dkp;
    480 
    481 
    482 /**
    483  * Function called with the session hashes and transfer secret
    484  * information for a given coin.
    485  *
    486  * @param cls closure
    487  * @param transfer_pub public transfer key for the session
    488  * @param ldl link data for @a transfer_pub
    489  */
    490 static void
    491 handle_link_data_cb (void *cls,
    492                      const struct TALER_TransferPublicKeyP *transfer_pub,
    493                      const struct TALER_EXCHANGEDB_LinkList *ldl)
    494 {
    495   (void) cls;
    496   (void) transfer_pub;
    497   for (const struct TALER_EXCHANGEDB_LinkList *ldlp = ldl;
    498        NULL != ldlp;
    499        ldlp = ldlp->next)
    500   {
    501     bool found;
    502 
    503     found = false;
    504     for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
    505     {
    506       if ( (0 ==
    507             TALER_denom_pub_cmp (&ldlp->denom_pub,
    508                                  &new_dkp[cnt]->pub)) &&
    509            (0 ==
    510             TALER_blinded_denom_sig_cmp (&ldlp->ev_sig,
    511                                          &revealed_coins[cnt].coin_sig)) )
    512       {
    513         found = true;
    514         break;
    515       }
    516     }
    517     GNUNET_assert (GNUNET_NO != found);
    518   }
    519 }
    520 
    521 
    522 /**
    523  * Callback that should never be called.
    524  */
    525 static void
    526 cb_wt_never (void *cls,
    527              uint64_t serial_id,
    528              const struct TALER_MerchantPublicKeyP *merchant_pub,
    529              const struct TALER_FullPayto account_payto_uri,
    530              const struct TALER_FullPaytoHashP *h_payto,
    531              struct GNUNET_TIME_Timestamp exec_time,
    532              const struct TALER_PrivateContractHashP *h_contract_terms,
    533              const struct TALER_DenominationPublicKey *denom_pub,
    534              const struct TALER_CoinSpendPublicKeyP *coin_pub,
    535              const struct TALER_Amount *coin_value,
    536              const struct TALER_Amount *coin_fee)
    537 {
    538   (void) cls;
    539   (void) serial_id;
    540   (void) merchant_pub;
    541   (void) account_payto_uri;
    542   (void) h_payto;
    543   (void) exec_time;
    544   (void) h_contract_terms;
    545   (void) denom_pub;
    546   (void) coin_pub;
    547   (void) coin_value;
    548   (void) coin_fee;
    549   GNUNET_assert (0); /* this statement should be unreachable */
    550 }
    551 
    552 
    553 static struct TALER_MerchantPublicKeyP merchant_pub_wt;
    554 static struct TALER_MerchantWireHashP h_wire_wt;
    555 static struct TALER_PrivateContractHashP h_contract_terms_wt;
    556 static struct TALER_CoinSpendPublicKeyP coin_pub_wt;
    557 static struct TALER_Amount coin_value_wt;
    558 static struct TALER_Amount coin_fee_wt;
    559 static struct TALER_Amount transfer_value_wt;
    560 static struct GNUNET_TIME_Timestamp wire_out_date;
    561 static struct TALER_WireTransferIdentifierRawP wire_out_wtid;
    562 
    563 
    564 /**
    565  * Callback that should be called with the WT data.
    566  */
    567 static void
    568 cb_wt_check (void *cls,
    569              uint64_t rowid,
    570              const struct TALER_MerchantPublicKeyP *merchant_pub,
    571              const struct TALER_FullPayto account_payto_uri,
    572              const struct TALER_FullPaytoHashP *h_payto,
    573              struct GNUNET_TIME_Timestamp exec_time,
    574              const struct TALER_PrivateContractHashP *h_contract_terms,
    575              const struct TALER_DenominationPublicKey *denom_pub,
    576              const struct TALER_CoinSpendPublicKeyP *coin_pub,
    577              const struct TALER_Amount *coin_value,
    578              const struct TALER_Amount *coin_fee)
    579 {
    580   (void) rowid;
    581   (void) denom_pub;
    582   (void) h_payto;
    583   GNUNET_assert (cls == &cb_wt_never);
    584   GNUNET_assert (0 == GNUNET_memcmp (merchant_pub,
    585                                      &merchant_pub_wt));
    586   GNUNET_assert (0 == strcmp (account_payto_uri.full_payto,
    587                               "payto://iban/DE67830654080004822650?receiver-name=Test"));
    588   GNUNET_assert (GNUNET_TIME_timestamp_cmp (exec_time,
    589                                             ==,
    590                                             wire_out_date));
    591   GNUNET_assert (0 == GNUNET_memcmp (h_contract_terms,
    592                                      &h_contract_terms_wt));
    593   GNUNET_assert (0 == GNUNET_memcmp (coin_pub,
    594                                      &coin_pub_wt));
    595   GNUNET_assert (0 == TALER_amount_cmp (coin_value,
    596                                         &coin_value_wt));
    597   GNUNET_assert (0 == TALER_amount_cmp (coin_fee,
    598                                         &coin_fee_wt));
    599 }
    600 
    601 
    602 /**
    603  * Here we store the hash of the payto URI.
    604  */
    605 static struct TALER_FullPaytoHashP global_wire_target_h_payto;
    606 
    607 
    608 /**
    609  * Callback for #select_coin_deposits_above_serial_id ()
    610  *
    611  * @param cls closure
    612  * @param rowid unique serial ID for the deposit in our DB
    613  * @param exchange_timestamp when did the deposit happen
    614  * @param deposit deposit details
    615  * @param denom_pub denomination of the @a coin_pub
    616  * @param done flag set if the deposit was already executed (or not)
    617  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
    618  */
    619 static enum GNUNET_GenericReturnValue
    620 audit_deposit_cb (void *cls,
    621                   uint64_t rowid,
    622                   struct GNUNET_TIME_Timestamp exchange_timestamp,
    623                   const struct TALER_EXCHANGEDB_Deposit *deposit,
    624                   const struct TALER_DenominationPublicKey *denom_pub,
    625                   bool done)
    626 {
    627   (void) cls;
    628   (void) rowid;
    629   (void) exchange_timestamp;
    630   (void) deposit;
    631   (void) denom_pub;
    632   (void) done;
    633   auditor_row_cnt++;
    634   return GNUNET_OK;
    635 }
    636 
    637 
    638 /**
    639  * Function called with details about coins that were refunding,
    640  * with the goal of auditing the refund's execution.
    641  *
    642  * @param cls closure
    643  * @param rowid unique serial ID for the refund in our DB
    644  * @param denom_pub denomination of the @a coin_pub
    645  * @param coin_pub public key of the coin
    646  * @param merchant_pub public key of the merchant
    647  * @param merchant_sig signature of the merchant
    648  * @param h_contract_terms hash of the proposal data in
    649  *                        the contract between merchant and customer
    650  * @param rtransaction_id refund transaction ID chosen by the merchant
    651  * @param full_refund the deposit
    652  * @param amount_with_fee amount that was deposited including fee
    653  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
    654  */
    655 static enum GNUNET_GenericReturnValue
    656 audit_refund_cb (void *cls,
    657                  uint64_t rowid,
    658                  const struct TALER_DenominationPublicKey *denom_pub,
    659                  const struct TALER_CoinSpendPublicKeyP *coin_pub,
    660                  const struct TALER_MerchantPublicKeyP *merchant_pub,
    661                  const struct TALER_MerchantSignatureP *merchant_sig,
    662                  const struct TALER_PrivateContractHashP *h_contract_terms,
    663                  uint64_t rtransaction_id,
    664                  bool full_refund,
    665                  const struct TALER_Amount *amount_with_fee)
    666 {
    667   (void) cls;
    668   (void) rowid;
    669   (void) denom_pub;
    670   (void) coin_pub;
    671   (void) merchant_pub;
    672   (void) merchant_sig;
    673   (void) h_contract_terms;
    674   (void) rtransaction_id;
    675   (void) amount_with_fee;
    676   (void) full_refund;
    677   auditor_row_cnt++;
    678   return GNUNET_OK;
    679 }
    680 
    681 
    682 /**
    683  * Function called with details about incoming wire transfers.
    684  *
    685  * @param cls closure
    686  * @param rowid unique serial ID for the refresh session in our DB
    687  * @param reserve_pub public key of the reserve (also the WTID)
    688  * @param credit amount that was received
    689  * @param sender_account_details information about the sender's bank account
    690  * @param wire_reference unique reference identifying the wire transfer
    691  * @param execution_date when did we receive the funds
    692  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
    693  */
    694 static enum GNUNET_GenericReturnValue
    695 audit_reserve_in_cb (void *cls,
    696                      uint64_t rowid,
    697                      const struct TALER_ReservePublicKeyP *reserve_pub,
    698                      const struct TALER_Amount *credit,
    699                      const struct TALER_FullPayto sender_account_details,
    700                      uint64_t wire_reference,
    701                      struct GNUNET_TIME_Timestamp execution_date)
    702 {
    703   (void) cls;
    704   (void) rowid;
    705   (void) reserve_pub;
    706   (void) credit;
    707   (void) sender_account_details;
    708   (void) wire_reference;
    709   (void) execution_date;
    710   auditor_row_cnt++;
    711   return GNUNET_OK;
    712 }
    713 
    714 
    715 /**
    716  * Function called with details about withdraw operations.
    717  *
    718  * @param cls closure
    719  * @param rowid unique serial ID for the refresh session in our DB
    720  * @param num_evs number of elements in @e h_blind_evs
    721  * @param h_blind_evs array @e num_evs of blinded hashes of the coin's public keys
    722  * @param denom_serials array @e num_evs of serial ids of denominations
    723  * @param h_planchets running hash over all hashes of blinded planchets in the original withdraw request
    724  * @param blinding_seed seed provided during withdraw, for CS denominations; might be NULL
    725  * @param age_proof_required true if the withdraw request required an age proof.
    726  * @param max_age if @e age_proof_required is true, the maximum age that was set on the coins.
    727  * @param noreveal_index if @e age_proof_required is true, the index that was returned by the exchange for the reveal phase.
    728  * @param reserve_pub public key of the reserve
    729  * @param reserve_sig signature over the withdraw operation
    730  * @param execution_date when did the wallet withdraw the coin
    731  * @param amount_with_fee amount that was withdrawn
    732  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
    733  */
    734 static enum GNUNET_GenericReturnValue
    735 audit_reserve_out_cb (void *cls,
    736                       uint64_t rowid,
    737                       size_t num_evs,
    738                       const struct TALER_BlindedCoinHashP *h_blind_evs,
    739                       const uint64_t *denom_serials,
    740                       const struct TALER_HashBlindedPlanchetsP *h_planchets,
    741                       const struct TALER_BlindingMasterSeedP *blinding_seed,
    742                       bool age_proof_required,
    743                       uint8_t max_age,
    744                       uint8_t noreveal_index,
    745                       const struct TALER_ReservePublicKeyP *reserve_pub,
    746                       const struct TALER_ReserveSignatureP *reserve_sig,
    747                       struct GNUNET_TIME_Timestamp execution_date,
    748                       const struct TALER_Amount *amount_with_fee)
    749 {
    750   (void) cls;
    751   (void) rowid;
    752   (void) h_blind_evs;
    753   (void) h_planchets;
    754   (void) blinding_seed;
    755   (void) denom_serials;
    756   (void) reserve_pub;
    757   (void) reserve_sig;
    758   (void) execution_date;
    759   (void) amount_with_fee;
    760   auditor_row_cnt++;
    761   return GNUNET_OK;
    762 }
    763 
    764 
    765 /**
    766  * Test garbage collection.
    767  *
    768  * @return #GNUNET_OK on success
    769  */
    770 static enum GNUNET_GenericReturnValue
    771 test_gc (void)
    772 {
    773   struct DenomKeyPair *dkp;
    774   struct GNUNET_TIME_Timestamp now;
    775   struct GNUNET_TIME_Timestamp past;
    776   struct TALER_EXCHANGEDB_DenominationKeyInformation issue2;
    777   struct TALER_DenominationHashP denom_hash;
    778 
    779   now = GNUNET_TIME_timestamp_get ();
    780   past = GNUNET_TIME_absolute_to_timestamp (
    781     GNUNET_TIME_absolute_subtract (now.abs_time,
    782                                    GNUNET_TIME_relative_multiply (
    783                                      GNUNET_TIME_UNIT_HOURS,
    784                                      4)));
    785   dkp = create_denom_key_pair (RSA_KEY_SIZE,
    786                                past,
    787                                &global_value,
    788                                &global_fees);
    789   GNUNET_assert (NULL != dkp);
    790   if (GNUNET_OK !=
    791       plugin->gc (plugin->cls))
    792   {
    793     GNUNET_break (0);
    794     destroy_denom_key_pair (dkp);
    795     return GNUNET_SYSERR;
    796   }
    797   TALER_denom_pub_hash (&dkp->pub,
    798                         &denom_hash);
    799 
    800   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    801       plugin->get_denomination_info (plugin->cls,
    802                                      &denom_hash,
    803                                      NULL,
    804                                      &issue2))
    805   {
    806     GNUNET_break (0);
    807     destroy_denom_key_pair (dkp);
    808     return GNUNET_SYSERR;
    809   }
    810   destroy_denom_key_pair (dkp);
    811   return GNUNET_OK;
    812 }
    813 
    814 
    815 /**
    816  * Test wire fee storage.
    817  *
    818  * @return #GNUNET_OK on success
    819  */
    820 static enum GNUNET_GenericReturnValue
    821 test_wire_fees (void)
    822 {
    823   struct GNUNET_TIME_Timestamp start_date;
    824   struct GNUNET_TIME_Timestamp end_date;
    825   struct TALER_WireFeeSet fees;
    826   struct TALER_MasterSignatureP master_sig;
    827   struct GNUNET_TIME_Timestamp sd;
    828   struct GNUNET_TIME_Timestamp ed;
    829   struct TALER_WireFeeSet fees2;
    830   struct TALER_MasterSignatureP ms;
    831   uint64_t rowid;
    832 
    833   start_date = GNUNET_TIME_timestamp_get ();
    834   end_date = GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_MINUTES);
    835   GNUNET_assert (GNUNET_OK ==
    836                  TALER_string_to_amount (CURRENCY ":1.424242",
    837                                          &fees.wire));
    838   GNUNET_assert (GNUNET_OK ==
    839                  TALER_string_to_amount (CURRENCY ":2.424242",
    840                                          &fees.closing));
    841   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
    842                               &master_sig,
    843                               sizeof (master_sig));
    844   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    845       plugin->insert_wire_fee (plugin->cls,
    846                                "wire-method",
    847                                start_date,
    848                                end_date,
    849                                &fees,
    850                                &master_sig))
    851   {
    852     GNUNET_break (0);
    853     return GNUNET_SYSERR;
    854   }
    855   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    856       plugin->insert_wire_fee (plugin->cls,
    857                                "wire-method",
    858                                start_date,
    859                                end_date,
    860                                &fees,
    861                                &master_sig))
    862   {
    863     GNUNET_break (0);
    864     return GNUNET_SYSERR;
    865   }
    866   /* This must fail as 'end_date' is NOT in the
    867      half-open interval [start_date,end_date) */
    868   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    869       plugin->get_wire_fee (plugin->cls,
    870                             "wire-method",
    871                             end_date,
    872                             &rowid,
    873                             &sd,
    874                             &ed,
    875                             &fees2,
    876                             &ms))
    877   {
    878     GNUNET_break (0);
    879     return GNUNET_SYSERR;
    880   }
    881   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    882       plugin->get_wire_fee (plugin->cls,
    883                             "wire-method",
    884                             start_date,
    885                             &rowid,
    886                             &sd,
    887                             &ed,
    888                             &fees2,
    889                             &ms))
    890   {
    891     GNUNET_break (0);
    892     return GNUNET_SYSERR;
    893   }
    894   if ( (GNUNET_TIME_timestamp_cmp (sd,
    895                                    !=,
    896                                    start_date)) ||
    897        (GNUNET_TIME_timestamp_cmp (ed,
    898                                    !=,
    899                                    end_date)) ||
    900        (0 != TALER_wire_fee_set_cmp (&fees,
    901                                      &fees2)) ||
    902        (0 != GNUNET_memcmp (&ms,
    903                             &master_sig)) )
    904   {
    905     GNUNET_break (0);
    906     return GNUNET_SYSERR;
    907   }
    908   return GNUNET_OK;
    909 }
    910 
    911 
    912 static struct TALER_Amount wire_out_amount;
    913 
    914 
    915 /**
    916  * Callback with data about an executed wire transfer.
    917  *
    918  * @param cls closure
    919  * @param rowid identifier of the respective row in the database
    920  * @param date timestamp of the wire transfer (roughly)
    921  * @param wtid wire transfer subject
    922  * @param wire wire transfer details of the receiver
    923  * @param amount amount that was wired
    924  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration
    925  */
    926 static enum GNUNET_GenericReturnValue
    927 audit_wire_cb (void *cls,
    928                uint64_t rowid,
    929                struct GNUNET_TIME_Timestamp date,
    930                const struct TALER_WireTransferIdentifierRawP *wtid,
    931                const struct TALER_FullPayto payto_uri,
    932                const struct TALER_Amount *amount)
    933 {
    934   (void) cls;
    935   (void) rowid;
    936   (void) payto_uri;
    937   auditor_row_cnt++;
    938   GNUNET_assert (0 ==
    939                  TALER_amount_cmp (amount,
    940                                    &wire_out_amount));
    941   GNUNET_assert (0 ==
    942                  GNUNET_memcmp (wtid,
    943                                 &wire_out_wtid));
    944   GNUNET_assert (GNUNET_TIME_timestamp_cmp (date,
    945                                             ==,
    946                                             wire_out_date));
    947   return GNUNET_OK;
    948 }
    949 
    950 
    951 /**
    952  * Test API relating to wire_out handling.
    953  *
    954  * @param bd batch deposit to test
    955  * @return #GNUNET_OK on success
    956  */
    957 static enum GNUNET_GenericReturnValue
    958 test_wire_out (const struct TALER_EXCHANGEDB_BatchDeposit *bd)
    959 {
    960   const struct TALER_EXCHANGEDB_CoinDepositInformation *deposit = &bd->cdis[0];
    961   struct TALER_FullPaytoHashP h_payto;
    962 
    963   GNUNET_assert (0 < bd->num_cdis);
    964   TALER_full_payto_hash (bd->receiver_wire_account,
    965                          &h_payto);
    966   auditor_row_cnt = 0;
    967   memset (&wire_out_wtid,
    968           41,
    969           sizeof (wire_out_wtid));
    970   wire_out_date = GNUNET_TIME_timestamp_get ();
    971   GNUNET_assert (GNUNET_OK ==
    972                  TALER_string_to_amount (CURRENCY ":1",
    973                                          &wire_out_amount));
    974 
    975   /* we will transiently violate the wtid constraint on
    976      the aggregation table, so we need to start the special
    977      transaction where this is allowed... */
    978   FAILIF (GNUNET_OK !=
    979           plugin->start_deferred_wire_out (plugin->cls));
    980 
    981   /* setup values for wire transfer aggregation data */
    982   merchant_pub_wt = bd->merchant_pub;
    983   h_contract_terms_wt = bd->h_contract_terms;
    984   coin_pub_wt = deposit->coin.coin_pub;
    985 
    986   coin_value_wt = deposit->amount_with_fee;
    987   coin_fee_wt = global_fees.deposit;
    988   GNUNET_assert (0 <
    989                  TALER_amount_subtract (&transfer_value_wt,
    990                                         &coin_value_wt,
    991                                         &coin_fee_wt));
    992   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    993           plugin->lookup_wire_transfer (plugin->cls,
    994                                         &wire_out_wtid,
    995                                         &cb_wt_never,
    996                                         NULL));
    997 
    998   {
    999     struct TALER_PrivateContractHashP h_contract_terms_wt2 =
   1000       h_contract_terms_wt;
   1001     bool pending;
   1002     struct TALER_WireTransferIdentifierRawP wtid2;
   1003     struct TALER_Amount coin_contribution2;
   1004     struct TALER_Amount coin_fee2;
   1005     struct GNUNET_TIME_Timestamp execution_time2;
   1006     struct TALER_EXCHANGEDB_KycStatus kyc;
   1007     union TALER_AccountPublicKeyP account_pub;
   1008 
   1009     h_contract_terms_wt2.hash.bits[0]++;
   1010     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   1011             plugin->lookup_transfer_by_deposit (plugin->cls,
   1012                                                 &h_contract_terms_wt2,
   1013                                                 &h_wire_wt,
   1014                                                 &coin_pub_wt,
   1015                                                 &merchant_pub_wt,
   1016                                                 &pending,
   1017                                                 &wtid2,
   1018                                                 &execution_time2,
   1019                                                 &coin_contribution2,
   1020                                                 &coin_fee2,
   1021                                                 &kyc,
   1022                                                 &account_pub));
   1023   }
   1024   {
   1025     struct TALER_ReservePublicKeyP rpub;
   1026 
   1027     memset (&rpub,
   1028             44,
   1029             sizeof (rpub));
   1030     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1031             plugin->store_wire_transfer_out (plugin->cls,
   1032                                              wire_out_date,
   1033                                              &wire_out_wtid,
   1034                                              &h_payto,
   1035                                              "my-config-section",
   1036                                              &wire_out_amount));
   1037   }
   1038   /* And now the commit should still succeed! */
   1039   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   1040           plugin->commit (plugin->cls));
   1041 
   1042   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1043           plugin->lookup_wire_transfer (plugin->cls,
   1044                                         &wire_out_wtid,
   1045                                         &cb_wt_check,
   1046                                         &cb_wt_never));
   1047   {
   1048     bool pending;
   1049     struct TALER_WireTransferIdentifierRawP wtid2;
   1050     struct TALER_Amount coin_contribution2;
   1051     struct TALER_Amount coin_fee2;
   1052     struct GNUNET_TIME_Timestamp execution_time2;
   1053     struct TALER_EXCHANGEDB_KycStatus kyc;
   1054     union TALER_AccountPublicKeyP account_pub;
   1055 
   1056     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1057             plugin->lookup_transfer_by_deposit (plugin->cls,
   1058                                                 &h_contract_terms_wt,
   1059                                                 &h_wire_wt,
   1060                                                 &coin_pub_wt,
   1061                                                 &merchant_pub_wt,
   1062                                                 &pending,
   1063                                                 &wtid2,
   1064                                                 &execution_time2,
   1065                                                 &coin_contribution2,
   1066                                                 &coin_fee2,
   1067                                                 &kyc,
   1068                                                 &account_pub));
   1069     GNUNET_assert (0 == GNUNET_memcmp (&wtid2,
   1070                                        &wire_out_wtid));
   1071     GNUNET_assert (GNUNET_TIME_timestamp_cmp (execution_time2,
   1072                                               ==,
   1073                                               wire_out_date));
   1074     GNUNET_assert (0 == TALER_amount_cmp (&coin_contribution2,
   1075                                           &coin_value_wt));
   1076     GNUNET_assert (0 == TALER_amount_cmp (&coin_fee2,
   1077                                           &coin_fee_wt));
   1078   }
   1079   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1080           plugin->select_wire_out_above_serial_id (plugin->cls,
   1081                                                    0,
   1082                                                    &audit_wire_cb,
   1083                                                    NULL));
   1084   FAILIF (1 != auditor_row_cnt);
   1085 
   1086   return GNUNET_OK;
   1087 drop:
   1088   return GNUNET_SYSERR;
   1089 }
   1090 
   1091 
   1092 /**
   1093  * Function called about recoups the exchange has to perform.
   1094  *
   1095  * @param cls closure with the expected value for @a coin_blind
   1096  * @param rowid row identifier used to uniquely identify the recoup operation
   1097  * @param timestamp when did we receive the recoup request
   1098  * @param amount how much should be added back to the reserve
   1099  * @param reserve_pub public key of the reserve
   1100  * @param coin public information about the coin
   1101  * @param denom_pub denomination key of @a coin
   1102  * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_RECOUP
   1103  * @param coin_blind blinding factor used to blind the coin
   1104  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
   1105  */
   1106 static enum GNUNET_GenericReturnValue
   1107 recoup_cb (void *cls,
   1108            uint64_t rowid,
   1109            struct GNUNET_TIME_Timestamp timestamp,
   1110            const struct TALER_Amount *amount,
   1111            const struct TALER_ReservePublicKeyP *reserve_pub,
   1112            const struct TALER_CoinPublicInfo *coin,
   1113            const struct TALER_DenominationPublicKey *denom_pub,
   1114            const struct TALER_CoinSpendSignatureP *coin_sig,
   1115            const union GNUNET_CRYPTO_BlindingSecretP *coin_blind)
   1116 {
   1117   const union GNUNET_CRYPTO_BlindingSecretP *cb = cls;
   1118 
   1119   (void) rowid;
   1120   (void) timestamp;
   1121   (void) amount;
   1122   (void) reserve_pub;
   1123   (void) coin_sig;
   1124   (void) coin;
   1125   (void) denom_pub;
   1126   FAILIF (NULL == cb);
   1127   FAILIF (0 != GNUNET_memcmp (cb,
   1128                               coin_blind));
   1129   return GNUNET_OK;
   1130 drop:
   1131   return GNUNET_SYSERR;
   1132 }
   1133 
   1134 
   1135 /**
   1136  * Function called on batch deposits that may require a
   1137  * wire transfer.
   1138  *
   1139  * @param cls closure a `struct TALER_EXCHANGEDB_Deposit *`
   1140  * @param batch_deposit_serial_id where in the table are we
   1141  * @param total_amount value of all missing deposits, including fees
   1142  * @param wire_target_h_payto hash of the recipient account's payto URI
   1143  * @param deadline what was the earliest requested wire transfer deadline
   1144  */
   1145 static void
   1146 wire_missing_cb (
   1147   void *cls,
   1148   uint64_t batch_deposit_serial_id,
   1149   const struct TALER_Amount *total_amount,
   1150   const struct TALER_FullPaytoHashP *wire_target_h_payto,
   1151   struct GNUNET_TIME_Timestamp deadline)
   1152 {
   1153   const struct TALER_EXCHANGEDB_CoinDepositInformation *deposit = cls;
   1154 
   1155   (void) batch_deposit_serial_id;
   1156   (void) deadline;
   1157   (void) wire_target_h_payto;
   1158   if (0 ==
   1159       TALER_amount_cmp (total_amount,
   1160                         &deposit->amount_with_fee))
   1161     result = 8;
   1162 }
   1163 
   1164 
   1165 /**
   1166  * Callback invoked with information about refunds applicable
   1167  * to a particular coin.
   1168  *
   1169  * @param cls closure with the `struct TALER_EXCHANGEDB_Refund *` we expect to get
   1170  * @param amount_with_fee amount being refunded
   1171  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
   1172  */
   1173 static enum GNUNET_GenericReturnValue
   1174 check_refund_cb (void *cls,
   1175                  const struct TALER_Amount *amount_with_fee)
   1176 {
   1177   const struct TALER_EXCHANGEDB_Refund *refund = cls;
   1178 
   1179   if (0 != TALER_amount_cmp (amount_with_fee,
   1180                              &refund->details.refund_amount))
   1181   {
   1182     GNUNET_break (0);
   1183     result = 66;
   1184   }
   1185   return GNUNET_OK;
   1186 }
   1187 
   1188 
   1189 /**
   1190  * Main function that will be run by the scheduler.
   1191  *
   1192  * @param cls closure with config
   1193  */
   1194 static void
   1195 run (void *cls)
   1196 {
   1197   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   1198   struct TALER_CoinSpendSignatureP coin_sig;
   1199   struct GNUNET_TIME_Timestamp deadline;
   1200   union GNUNET_CRYPTO_BlindingSecretP coin_blind;
   1201   struct TALER_ReservePublicKeyP reserve_pub;
   1202   struct TALER_ReservePublicKeyP reserve_pub2;
   1203   struct TALER_ReservePublicKeyP reserve_pub3;
   1204   struct DenomKeyPair *dkp = NULL;
   1205   struct TALER_MasterSignatureP master_sig;
   1206   struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
   1207   struct TALER_EXCHANGEDB_ReserveHistory *rh = NULL;
   1208   struct TALER_EXCHANGEDB_ReserveHistory *rh_head;
   1209   struct TALER_EXCHANGEDB_BankTransfer *bt;
   1210   struct TALER_EXCHANGEDB_Withdraw withdraw;
   1211   struct TALER_HashBlindedPlanchetsP h_planchets;
   1212   struct TALER_EXCHANGEDB_CoinDepositInformation deposit;
   1213   struct TALER_EXCHANGEDB_BatchDeposit bd;
   1214   struct TALER_CoinSpendPublicKeyP cpub2;
   1215   struct TALER_MerchantPublicKeyP mpub2;
   1216   struct TALER_EXCHANGEDB_Refund refund;
   1217   const struct TALER_FullPayto sndr = {
   1218     (char *) "payto://x-taler-bank/localhost:8080/1?receiver-name=1"
   1219   };
   1220   const struct TALER_FullPayto rcvr = {
   1221     (char *) "payto://x-taler-bank/localhost:8080/2?receiver-name=1"
   1222   };
   1223   const uint32_t num_partitions = 10;
   1224   unsigned int matched;
   1225   enum GNUNET_DB_QueryStatus qs;
   1226   struct GNUNET_TIME_Timestamp now;
   1227   struct TALER_WireSaltP salt;
   1228   struct TALER_CoinPubHashP c_hash;
   1229   uint64_t known_coin_id;
   1230   uint64_t rrc_serial;
   1231   struct TALER_EXCHANGEDB_Refresh refresh;
   1232   struct TALER_DenominationPublicKey *new_denom_pubs = NULL;
   1233   uint64_t withdraw_serial_id;
   1234   uint64_t melt_serial_id;
   1235   struct TALER_PlanchetMasterSecretP ps;
   1236   union GNUNET_CRYPTO_BlindingSecretP bks;
   1237   struct TALER_Amount amount_with_fee;
   1238   const struct TALER_ExchangeBlindingValues *alg_values
   1239     = TALER_denom_ewv_rsa_singleton ();
   1240 
   1241   memset (&deposit,
   1242           0,
   1243           sizeof (deposit));
   1244   memset (&bd,
   1245           0,
   1246           sizeof (bd));
   1247   bd.receiver_wire_account = rcvr;
   1248   bd.cdis = &deposit;
   1249   bd.num_cdis = 1;
   1250   memset (&salt,
   1251           45,
   1252           sizeof (salt));
   1253   memset (&refresh,
   1254           0,
   1255           sizeof (refresh));
   1256   ZR_BLK (&cbc);
   1257   ZR_BLK (&withdraw);
   1258   if (NULL ==
   1259       (plugin = TALER_EXCHANGEDB_plugin_load (cfg,
   1260                                               true)))
   1261   {
   1262     result = 77;
   1263     return;
   1264   }
   1265   (void) plugin->drop_tables (plugin->cls);
   1266   if (GNUNET_OK !=
   1267       plugin->create_tables (plugin->cls,
   1268                              true,
   1269                              num_partitions))
   1270   {
   1271     result = 77;
   1272     goto cleanup;
   1273   }
   1274   plugin->preflight (plugin->cls);
   1275   FAILIF (GNUNET_OK !=
   1276           plugin->start (plugin->cls,
   1277                          "test-1"));
   1278 
   1279 
   1280   /* test DB is empty */
   1281   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   1282           plugin->select_recoup_above_serial_id (plugin->cls,
   1283                                                  0,
   1284                                                  &recoup_cb,
   1285                                                  NULL));
   1286 
   1287   /* simple extension check */
   1288   FAILIF (GNUNET_OK !=
   1289           test_extension_manifest ());
   1290 
   1291   RND_BLK (&reserve_pub);
   1292   GNUNET_assert (GNUNET_OK ==
   1293                  TALER_string_to_amount (CURRENCY ":1.000000",
   1294                                          &global_amount));
   1295   GNUNET_assert (GNUNET_OK ==
   1296                  TALER_string_to_amount (CURRENCY ":1.000010",
   1297                                          &global_value));
   1298   GNUNET_assert (GNUNET_OK ==
   1299                  TALER_string_to_amount (CURRENCY ":0.000010",
   1300                                          &global_fees.withdraw));
   1301   GNUNET_assert (GNUNET_OK ==
   1302                  TALER_string_to_amount (CURRENCY ":0.000010",
   1303                                          &global_fees.deposit));
   1304   GNUNET_assert (GNUNET_OK ==
   1305                  TALER_string_to_amount (CURRENCY ":0.000010",
   1306                                          &global_fees.refresh));
   1307   GNUNET_assert (GNUNET_OK ==
   1308                  TALER_string_to_amount (CURRENCY ":0.000010",
   1309                                          &global_fees.refund));
   1310   GNUNET_assert (GNUNET_OK ==
   1311                  TALER_string_to_amount (CURRENCY ":1.000010",
   1312                                          &amount_with_fee));
   1313   result = 4;
   1314   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   1315           plugin->commit (plugin->cls));
   1316   now = GNUNET_TIME_timestamp_get ();
   1317   {
   1318     struct TALER_EXCHANGEDB_ReserveInInfo reserve = {
   1319       .reserve_pub = &reserve_pub,
   1320       .balance = &global_value,
   1321       .execution_time = now,
   1322       .sender_account_details = sndr,
   1323       .exchange_account_name = "exchange-account-1",
   1324       .wire_reference = 4
   1325     };
   1326     enum GNUNET_DB_QueryStatus qsr;
   1327 
   1328     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1329             plugin->reserves_in_insert (plugin->cls,
   1330                                         &reserve,
   1331                                         1,
   1332                                         &qsr));
   1333     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1334             qsr);
   1335   }
   1336   FAILIF (GNUNET_OK !=
   1337           check_reserve (&reserve_pub,
   1338                          global_value.value,
   1339                          global_value.fraction,
   1340                          global_value.currency));
   1341   now = GNUNET_TIME_timestamp_get ();
   1342   RND_BLK (&reserve_pub2);
   1343   {
   1344     struct TALER_EXCHANGEDB_ReserveInInfo reserve = {
   1345       .reserve_pub = &reserve_pub2,
   1346       .balance = &global_value,
   1347       .execution_time = now,
   1348       .sender_account_details = sndr,
   1349       .exchange_account_name = "exchange-account-1",
   1350       .wire_reference = 5
   1351     };
   1352     enum GNUNET_DB_QueryStatus qsr;
   1353 
   1354     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1355             plugin->reserves_in_insert (plugin->cls,
   1356                                         &reserve,
   1357                                         1,
   1358                                         &qsr));
   1359     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1360             qsr);
   1361   }
   1362   FAILIF (GNUNET_OK !=
   1363           plugin->start (plugin->cls,
   1364                          "test-2"));
   1365   FAILIF (GNUNET_OK !=
   1366           check_reserve (&reserve_pub,
   1367                          global_value.value,
   1368                          global_value.fraction,
   1369                          global_value.currency));
   1370   FAILIF (GNUNET_OK !=
   1371           check_reserve (&reserve_pub2,
   1372                          global_value.value,
   1373                          global_value.fraction,
   1374                          global_value.currency));
   1375   result = 5;
   1376   now = GNUNET_TIME_timestamp_get ();
   1377   dkp = create_denom_key_pair (RSA_KEY_SIZE,
   1378                                now,
   1379                                &global_value,
   1380                                &global_fees);
   1381   GNUNET_assert (NULL != dkp);
   1382   TALER_denom_pub_hash (&dkp->pub,
   1383                         &cbc.denom_pub_hash);
   1384   RND_BLK (&cbc.reserve_sig);
   1385   RND_BLK (&ps);
   1386   TALER_planchet_blinding_secret_create (&ps,
   1387                                          alg_values,
   1388                                          &bks);
   1389   {
   1390     struct TALER_PlanchetDetail pd;
   1391     struct TALER_CoinSpendPublicKeyP coin_pub;
   1392 
   1393 
   1394     RND_BLK (&coin_pub);
   1395     GNUNET_assert (GNUNET_OK ==
   1396                    TALER_denom_blind (&dkp->pub,
   1397                                       &bks,
   1398                                       NULL,
   1399                                       NULL,
   1400                                       &coin_pub,
   1401                                       alg_values,
   1402                                       &c_hash,
   1403                                       &pd.blinded_planchet));
   1404     TALER_coin_ev_hash (&pd.blinded_planchet,
   1405                         &cbc.denom_pub_hash,
   1406                         &cbc.h_coin_envelope);
   1407 
   1408     GNUNET_assert (
   1409       GNUNET_OK ==
   1410       TALER_denom_sign_blinded (
   1411         &cbc.sig,
   1412         &dkp->priv,
   1413         false,
   1414         &pd.blinded_planchet));
   1415 
   1416     TALER_wallet_blinded_planchets_hash (
   1417       1,
   1418       &pd.blinded_planchet,
   1419       &cbc.denom_pub_hash,
   1420       &h_planchets);
   1421 
   1422     TALER_blinded_planchet_free (&pd.blinded_planchet);
   1423   }
   1424 
   1425   cbc.reserve_pub = reserve_pub;
   1426   cbc.amount_with_fee = global_value;
   1427   GNUNET_assert (GNUNET_OK ==
   1428                  TALER_amount_set_zero (CURRENCY,
   1429                                         &cbc.withdraw_fee));
   1430 
   1431   {
   1432     bool balance_ok;
   1433     bool age_ok;
   1434     bool idempotent;
   1435     uint16_t noreveal_index;
   1436     bool nonce_reuse;
   1437     uint16_t maximum_age;
   1438     uint32_t reserve_birthday;
   1439     uint64_t denom_serial = 1; /* bold assumption */
   1440     struct TALER_Amount reserve_balance;
   1441     struct TALER_BlindingMasterSeedP blinding_seed = {0};
   1442     struct GNUNET_CRYPTO_CSPublicRPairP cs_r_pubs = {0};
   1443     struct TALER_EXCHANGEDB_Withdraw withdraw_in = {
   1444       .amount_with_fee = global_value,
   1445       .age_proof_required = true,
   1446       .max_age = 0,
   1447       .noreveal_index = 42,
   1448       .reserve_pub = reserve_pub,
   1449       .reserve_sig = cbc.reserve_sig,
   1450       .h_planchets = h_planchets,
   1451       .no_blinding_seed = false,
   1452       .blinding_seed = blinding_seed,
   1453       .num_coins = 1,
   1454       .h_coin_evs = &cbc.h_coin_envelope,
   1455       .denom_sigs = &cbc.sig,
   1456       .denom_serials = &denom_serial,
   1457       .num_cs_r_pubs = 1,
   1458       .cs_r_pubs = &cs_r_pubs,
   1459     };
   1460     struct TALER_Amount zero_amount;
   1461 
   1462     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1463             plugin->do_withdraw (plugin->cls,
   1464                                  &withdraw_in,
   1465                                  &now,
   1466                                  &balance_ok,
   1467                                  &reserve_balance,
   1468                                  &age_ok,
   1469                                  &maximum_age,
   1470                                  &reserve_birthday,
   1471                                  &idempotent,
   1472                                  &noreveal_index,
   1473                                  &nonce_reuse));
   1474     GNUNET_assert (! idempotent);
   1475     GNUNET_assert (! nonce_reuse);
   1476     GNUNET_assert (balance_ok);
   1477 
   1478 
   1479     /**
   1480      * Set the amount in the withdraw to zero,
   1481      * to avoid triggering balance_ok issues for
   1482      * the conflict and nonce_reuse tests.
   1483      */
   1484     GNUNET_assert  (GNUNET_OK ==
   1485                     TALER_string_to_amount (CURRENCY ":0.000000",
   1486                                             &zero_amount));
   1487     withdraw_in.amount_with_fee = zero_amount;
   1488 
   1489     /**
   1490      * Change some values to trigger conflict
   1491      * due to h_planchet, not nonce.
   1492      */
   1493     withdraw_in.blinding_seed.key_data[0] = 1;
   1494     noreveal_index = -1;
   1495     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1496             plugin->do_withdraw (plugin->cls,
   1497                                  &withdraw_in,
   1498                                  &now,
   1499                                  &balance_ok,
   1500                                  &reserve_balance,
   1501                                  &age_ok,
   1502                                  &maximum_age,
   1503                                  &reserve_birthday,
   1504                                  &idempotent,
   1505                                  &noreveal_index,
   1506                                  &nonce_reuse));
   1507     GNUNET_assert (! nonce_reuse);
   1508     GNUNET_assert (idempotent);
   1509     GNUNET_assert (42 == noreveal_index);
   1510 
   1511     /**
   1512      * Make h_planchet unique again, but trigger
   1513      * conflict with blinding_seed.
   1514      */
   1515     withdraw_in.blinding_seed.key_data[0] = 0;
   1516     withdraw_in.h_planchets.hash.bits[0] += 1;
   1517     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1518             plugin->do_withdraw (plugin->cls,
   1519                                  &withdraw_in,
   1520                                  &now,
   1521                                  &balance_ok,
   1522                                  &reserve_balance,
   1523                                  &age_ok,
   1524                                  &maximum_age,
   1525                                  &reserve_birthday,
   1526                                  &idempotent,
   1527                                  &noreveal_index,
   1528                                  &nonce_reuse));
   1529     GNUNET_assert (! idempotent);
   1530     GNUNET_assert (nonce_reuse);
   1531   }
   1532 
   1533   FAILIF (GNUNET_OK !=
   1534           check_reserve (&reserve_pub,
   1535                          0,
   1536                          0,
   1537                          global_value.currency));
   1538   FAILIF (GNUNET_OK !=
   1539           check_reserve (&reserve_pub2,
   1540                          global_value.value,
   1541                          global_value.fraction,
   1542                          global_value.currency));
   1543   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1544           plugin->get_reserve_by_h_planchets (plugin->cls,
   1545                                               &h_planchets,
   1546                                               &reserve_pub3,
   1547                                               &withdraw_serial_id));
   1548   FAILIF (0 != GNUNET_memcmp (&reserve_pub,
   1549                               &reserve_pub3));
   1550   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1551           plugin->get_withdraw (plugin->cls,
   1552                                 &h_planchets,
   1553                                 &withdraw));
   1554   FAILIF (0 != GNUNET_memcmp (&withdraw.reserve_sig,
   1555                               &cbc.reserve_sig));
   1556   FAILIF (0 != GNUNET_memcmp (&withdraw.reserve_pub,
   1557                               &cbc.reserve_pub));
   1558   result = 6;
   1559 
   1560   {
   1561     struct TALER_DenominationSignature ds;
   1562 
   1563     GNUNET_assert (GNUNET_OK ==
   1564                    TALER_denom_sig_unblind (&ds,
   1565                                             &withdraw.denom_sigs[0],
   1566                                             &bks,
   1567                                             &c_hash,
   1568                                             alg_values,
   1569                                             &dkp->pub));
   1570     FAILIF (GNUNET_OK !=
   1571             TALER_denom_pub_verify (&dkp->pub,
   1572                                     &ds,
   1573                                     &c_hash));
   1574     TALER_denom_sig_free (&ds);
   1575   }
   1576 
   1577   RND_BLK (&coin_sig);
   1578   RND_BLK (&coin_blind);
   1579   RND_BLK (&deposit.coin.coin_pub);
   1580   TALER_denom_pub_hash (&dkp->pub,
   1581                         &deposit.coin.denom_pub_hash);
   1582   GNUNET_assert (GNUNET_OK ==
   1583                  TALER_denom_sig_unblind (&deposit.coin.denom_sig,
   1584                                           &cbc.sig,
   1585                                           &bks,
   1586                                           &c_hash,
   1587                                           alg_values,
   1588                                           &dkp->pub));
   1589   deadline = GNUNET_TIME_timestamp_get ();
   1590   {
   1591     struct TALER_DenominationHashP dph;
   1592     struct TALER_AgeCommitmentHashP agh;
   1593 
   1594     FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
   1595             plugin->ensure_coin_known (plugin->cls,
   1596                                        &deposit.coin,
   1597                                        &known_coin_id,
   1598                                        &dph,
   1599                                        &agh));
   1600   }
   1601   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   1602           plugin->commit (plugin->cls));
   1603   {
   1604     struct GNUNET_TIME_Timestamp deposit_timestamp
   1605       = GNUNET_TIME_timestamp_get ();
   1606     bool balance_ok;
   1607     uint32_t bad_balance_idx;
   1608     bool in_conflict;
   1609     struct TALER_FullPaytoHashP h_payto;
   1610 
   1611     RND_BLK (&h_payto);
   1612     bd.refund_deadline
   1613       = GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_MONTHS);
   1614     bd.wire_deadline
   1615       = GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_MONTHS);
   1616     deposit.amount_with_fee = global_value;
   1617     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1618             plugin->do_deposit (plugin->cls,
   1619                                 &bd,
   1620                                 &deposit_timestamp,
   1621                                 &balance_ok,
   1622                                 &bad_balance_idx,
   1623                                 &in_conflict));
   1624     FAILIF (! balance_ok);
   1625     FAILIF (in_conflict);
   1626   }
   1627 
   1628   {
   1629     bool not_found;
   1630     bool refund_ok;
   1631     bool gone;
   1632     bool conflict;
   1633 
   1634     refund.coin = deposit.coin;
   1635     refund.details.merchant_pub = bd.merchant_pub;
   1636     RND_BLK (&refund.details.merchant_sig);
   1637     refund.details.h_contract_terms = bd.h_contract_terms;
   1638     refund.details.rtransaction_id = 1;
   1639     refund.details.refund_amount = global_value;
   1640     refund.details.refund_fee = global_fees.refund;
   1641     RND_BLK (&refund.details.merchant_sig);
   1642     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1643             plugin->do_refund (plugin->cls,
   1644                                &refund,
   1645                                &global_fees.deposit,
   1646                                known_coin_id,
   1647                                &not_found,
   1648                                &refund_ok,
   1649                                &gone,
   1650                                &conflict));
   1651     FAILIF (not_found);
   1652     FAILIF (! refund_ok);
   1653     FAILIF (gone);
   1654     FAILIF (conflict);
   1655 
   1656     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1657             plugin->select_refunds_by_coin (plugin->cls,
   1658                                             &refund.coin.coin_pub,
   1659                                             &refund.details.merchant_pub,
   1660                                             &refund.details.h_contract_terms,
   1661                                             &check_refund_cb,
   1662                                             &refund));
   1663   }
   1664 
   1665 
   1666   /* test do_refresh */
   1667 #pragma message "add refresh test for new refresh"
   1668 #if 0
   1669   {
   1670     bool zombie_required = false;
   1671     bool balance_ok;
   1672     bool idempotent;
   1673     uint16_t idem_noreveal_index;
   1674     struct TALER_Amount insufficient_funds;
   1675     struct TALER_EXCHANGEDB_Refresh_v26 refresh_v26;
   1676 
   1677     refresh_v26.coin = deposit.coin;
   1678     RND_BLK (&refresh_v26.coin_sig);
   1679     RND_BLK (&refresh_v26.rc);
   1680     refresh_v26.amount_with_fee = global_value;
   1681     refresh_v26.noreveal_index = MELT_NOREVEAL_INDEX;
   1682     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1683             plugin->do_refresh (plugin->cls,
   1684                                 &refresh_v26,
   1685                                 NULL,
   1686                                 &idempotent,
   1687                                 &idem_noreveal_index,
   1688                                 &zombie_required,
   1689                                 &balance_ok,
   1690                                 &insufficient_funds));
   1691     FAILIF (! balance_ok);
   1692     FAILIF (zombie_required);
   1693   }
   1694 #endif
   1695 
   1696 
   1697   /* test do_melt */
   1698   {
   1699     bool zombie_required = false;
   1700     bool balance_ok;
   1701 
   1702     refresh.coin = deposit.coin;
   1703     RND_BLK (&refresh.coin_sig);
   1704     RND_BLK (&refresh.rc);
   1705     refresh.amount_with_fee = global_value;
   1706     refresh.noreveal_index = MELT_NOREVEAL_INDEX;
   1707     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1708             plugin->do_melt (plugin->cls,
   1709                              NULL,
   1710                              &refresh,
   1711                              known_coin_id,
   1712                              &zombie_required,
   1713                              &balance_ok));
   1714     FAILIF (! balance_ok);
   1715     FAILIF (zombie_required);
   1716   }
   1717 
   1718   /* test get_melt */
   1719   {
   1720     struct TALER_EXCHANGEDB_Melt ret_refresh_session;
   1721 
   1722     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1723             plugin->get_melt (plugin->cls,
   1724                               &refresh.rc,
   1725                               &ret_refresh_session,
   1726                               &melt_serial_id));
   1727     FAILIF (refresh.noreveal_index !=
   1728             ret_refresh_session.session.noreveal_index);
   1729     FAILIF (0 !=
   1730             TALER_amount_cmp (&refresh.amount_with_fee,
   1731                               &ret_refresh_session.session.amount_with_fee));
   1732     FAILIF (0 !=
   1733             TALER_amount_cmp (&global_fees.refresh,
   1734                               &ret_refresh_session.melt_fee));
   1735     FAILIF (0 !=
   1736             GNUNET_memcmp (&refresh.rc,
   1737                            &ret_refresh_session.session.rc));
   1738     FAILIF (0 != GNUNET_memcmp (&refresh.coin_sig,
   1739                                 &ret_refresh_session.session.coin_sig));
   1740     FAILIF (0 !=
   1741             GNUNET_memcmp (&refresh.coin.coin_pub,
   1742                            &ret_refresh_session.session.coin.coin_pub));
   1743     FAILIF (0 !=
   1744             GNUNET_memcmp (&refresh.coin.denom_pub_hash,
   1745                            &ret_refresh_session.session.coin.denom_pub_hash));
   1746   }
   1747 
   1748   {
   1749     /* test 'select_refreshes_above_serial_id' */
   1750     auditor_row_cnt = 0;
   1751     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1752             plugin->select_refreshes_above_serial_id (plugin->cls,
   1753                                                       0,
   1754                                                       &audit_refresh_session_cb,
   1755                                                       NULL));
   1756     FAILIF (1 != auditor_row_cnt);
   1757   }
   1758 
   1759   /* do refresh-reveal */
   1760   now = GNUNET_TIME_timestamp_get ();
   1761   {
   1762     new_dkp = GNUNET_new_array (MELT_NEW_COINS,
   1763                                 struct DenomKeyPair *);
   1764     new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
   1765                                        struct TALER_DenominationPublicKey);
   1766     revealed_coins
   1767       = GNUNET_new_array (MELT_NEW_COINS,
   1768                           struct TALER_EXCHANGEDB_RefreshRevealedCoin);
   1769     for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
   1770     {
   1771       struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
   1772       struct GNUNET_CRYPTO_BlindedMessage *rp;
   1773       struct GNUNET_CRYPTO_RsaBlindedMessage *rsa;
   1774       struct TALER_BlindedPlanchet *bp;
   1775 
   1776       new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
   1777                                             now,
   1778                                             &global_value,
   1779                                             &global_fees);
   1780       GNUNET_assert (NULL != new_dkp[cnt]);
   1781       new_denom_pubs[cnt] = new_dkp[cnt]->pub;
   1782       ccoin = &revealed_coins[cnt];
   1783       bp = &ccoin->blinded_planchet;
   1784       rp = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage);
   1785       bp->blinded_message = rp;
   1786       rp->cipher = GNUNET_CRYPTO_BSA_RSA;
   1787       rp->rc = 1;
   1788       rsa = &rp->details.rsa_blinded_message;
   1789       rsa->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
   1790         GNUNET_CRYPTO_QUALITY_WEAK,
   1791         (RSA_KEY_SIZE / 8) - 1);
   1792       rsa->blinded_msg = GNUNET_malloc (rsa->blinded_msg_size);
   1793       GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
   1794                                   rsa->blinded_msg,
   1795                                   rsa->blinded_msg_size);
   1796       TALER_denom_pub_hash (&new_dkp[cnt]->pub,
   1797                             &ccoin->h_denom_pub);
   1798       TALER_denom_ewv_copy (&ccoin->exchange_vals,
   1799                             alg_values);
   1800       TALER_coin_ev_hash (bp,
   1801                           &ccoin->h_denom_pub,
   1802                           &ccoin->coin_envelope_hash);
   1803       GNUNET_assert (GNUNET_OK ==
   1804                      TALER_denom_sign_blinded (&ccoin->coin_sig,
   1805                                                &new_dkp[cnt]->priv,
   1806                                                true,
   1807                                                bp));
   1808     }
   1809     RND_BLK (&tprivs);
   1810     RND_BLK (&tpub);
   1811     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   1812             plugin->get_refresh_reveal (plugin->cls,
   1813                                         &refresh.rc,
   1814                                         &never_called_cb,
   1815                                         NULL));
   1816     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1817             plugin->insert_refresh_reveal (plugin->cls,
   1818                                            melt_serial_id,
   1819                                            MELT_NEW_COINS,
   1820                                            revealed_coins,
   1821                                            TALER_CNC_KAPPA - 1,
   1822                                            tprivs,
   1823                                            &tpub));
   1824     {
   1825       struct TALER_BlindedCoinHashP h_coin_ev;
   1826       struct TALER_CoinSpendPublicKeyP ocp;
   1827       struct TALER_DenominationHashP denom_hash;
   1828 
   1829       TALER_denom_pub_hash (&new_denom_pubs[0],
   1830                             &denom_hash);
   1831       TALER_coin_ev_hash (&revealed_coins[0].blinded_planchet,
   1832                           &denom_hash,
   1833                           &h_coin_ev);
   1834       FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1835               plugin->get_old_coin_by_h_blind (plugin->cls,
   1836                                                &h_coin_ev,
   1837                                                &ocp,
   1838                                                &rrc_serial));
   1839       FAILIF (0 !=
   1840               GNUNET_memcmp (&ocp,
   1841                              &refresh.coin.coin_pub));
   1842     }
   1843     FAILIF (0 >=
   1844             plugin->get_refresh_reveal (plugin->cls,
   1845                                         &refresh.rc,
   1846                                         &check_refresh_reveal_cb,
   1847                                         NULL));
   1848     qs = plugin->get_link_data (plugin->cls,
   1849                                 &refresh.coin.coin_pub,
   1850                                 &handle_link_data_cb,
   1851                                 NULL);
   1852     FAILIF (0 >= qs);
   1853     {
   1854       /* Just to test fetching a coin with melt history */
   1855       struct TALER_EXCHANGEDB_TransactionList *tl;
   1856       uint64_t etag;
   1857       struct TALER_Amount balance;
   1858       struct TALER_DenominationHashP h_denom_pub;
   1859 
   1860       qs = plugin->get_coin_transactions (plugin->cls,
   1861                                           true,
   1862                                           &refresh.coin.coin_pub,
   1863                                           0,
   1864                                           0,
   1865                                           &etag,
   1866                                           &balance,
   1867                                           &h_denom_pub,
   1868                                           &tl);
   1869       FAILIF (0 >= qs);
   1870       FAILIF (NULL == tl);
   1871       plugin->free_coin_transaction_list (plugin->cls,
   1872                                           tl);
   1873     }
   1874   }
   1875 
   1876   /* do recoup-refresh */
   1877   {
   1878     struct GNUNET_TIME_Timestamp recoup_timestamp
   1879       = GNUNET_TIME_timestamp_get ();
   1880     union GNUNET_CRYPTO_BlindingSecretP coin_bks;
   1881     uint64_t new_known_coin_id;
   1882     struct TALER_CoinPublicInfo new_coin;
   1883     struct TALER_DenominationHashP dph;
   1884     struct TALER_AgeCommitmentHashP agh;
   1885     bool recoup_ok;
   1886     bool internal_failure;
   1887 
   1888     new_coin = deposit.coin; /* steal basic data */
   1889     RND_BLK (&new_coin.coin_pub);
   1890     FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
   1891             plugin->ensure_coin_known (plugin->cls,
   1892                                        &new_coin,
   1893                                        &new_known_coin_id,
   1894                                        &dph,
   1895                                        &agh));
   1896     RND_BLK (&coin_bks);
   1897     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1898             plugin->do_recoup_refresh (plugin->cls,
   1899                                        &deposit.coin.coin_pub,
   1900                                        rrc_serial,
   1901                                        &coin_bks,
   1902                                        &new_coin.coin_pub,
   1903                                        new_known_coin_id,
   1904                                        &coin_sig,
   1905                                        &recoup_timestamp,
   1906                                        &recoup_ok,
   1907                                        &internal_failure));
   1908     FAILIF (! recoup_ok);
   1909     FAILIF (internal_failure);
   1910   }
   1911 
   1912   /* do recoup */
   1913   {
   1914     struct TALER_EXCHANGEDB_Reserve pre_reserve;
   1915     struct TALER_EXCHANGEDB_Reserve post_reserve;
   1916     struct TALER_Amount delta;
   1917     bool recoup_ok;
   1918     bool internal_failure;
   1919     struct GNUNET_TIME_Timestamp recoup_timestamp
   1920       = GNUNET_TIME_timestamp_get ();
   1921 
   1922     pre_reserve.pub = reserve_pub;
   1923     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1924             plugin->reserves_get (plugin->cls,
   1925                                   &pre_reserve));
   1926     FAILIF (! TALER_amount_is_zero (&pre_reserve.balance));
   1927     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1928             plugin->do_recoup (plugin->cls,
   1929                                &reserve_pub,
   1930                                withdraw_serial_id,
   1931                                &coin_blind,
   1932                                &deposit.coin.coin_pub,
   1933                                known_coin_id,
   1934                                &coin_sig,
   1935                                &recoup_timestamp,
   1936                                &recoup_ok,
   1937                                &internal_failure));
   1938     FAILIF (internal_failure);
   1939     FAILIF (! recoup_ok);
   1940     post_reserve.pub = reserve_pub;
   1941     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1942             plugin->reserves_get (plugin->cls,
   1943                                   &post_reserve));
   1944     FAILIF (0 >=
   1945             TALER_amount_subtract (&delta,
   1946                                    &post_reserve.balance,
   1947                                    &pre_reserve.balance));
   1948     FAILIF (0 !=
   1949             TALER_amount_cmp (&delta,
   1950                               &global_value));
   1951   }
   1952 
   1953   FAILIF (GNUNET_OK !=
   1954           plugin->start (plugin->cls,
   1955                          "test-3"));
   1956 
   1957   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1958           plugin->select_recoup_above_serial_id (plugin->cls,
   1959                                                  0,
   1960                                                  &recoup_cb,
   1961                                                  &coin_blind));
   1962   /* Do reserve close */
   1963   now = GNUNET_TIME_timestamp_get ();
   1964   GNUNET_assert (GNUNET_OK ==
   1965                  TALER_string_to_amount (CURRENCY ":0.000010",
   1966                                          &fee_closing));
   1967   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1968           plugin->insert_reserve_closed (plugin->cls,
   1969                                          &reserve_pub2,
   1970                                          now,
   1971                                          sndr,
   1972                                          &wire_out_wtid,
   1973                                          &amount_with_fee,
   1974                                          &fee_closing,
   1975                                          0));
   1976   FAILIF (GNUNET_OK !=
   1977           check_reserve (&reserve_pub2,
   1978                          0,
   1979                          0,
   1980                          global_value.currency));
   1981   now = GNUNET_TIME_timestamp_get ();
   1982   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   1983           plugin->insert_reserve_closed (plugin->cls,
   1984                                          &reserve_pub,
   1985                                          now,
   1986                                          sndr,
   1987                                          &wire_out_wtid,
   1988                                          &global_value,
   1989                                          &fee_closing,
   1990                                          0));
   1991   FAILIF (GNUNET_OK !=
   1992           check_reserve (&reserve_pub,
   1993                          0,
   1994                          0,
   1995                          global_value.currency));
   1996   result = 7;
   1997   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   1998           plugin->commit (plugin->cls));
   1999 
   2000 
   2001   /* check reserve history */
   2002   {
   2003     struct TALER_Amount balance;
   2004     uint64_t etag_out;
   2005 
   2006     qs = plugin->get_reserve_history (plugin->cls,
   2007                                       &reserve_pub,
   2008                                       0,
   2009                                       0,
   2010                                       &etag_out,
   2011                                       &balance,
   2012                                       &rh);
   2013   }
   2014   FAILIF (0 > qs);
   2015   FAILIF (NULL == rh);
   2016   rh_head = rh;
   2017   {
   2018     unsigned int cnt;
   2019 
   2020     for (cnt = 0;
   2021          NULL != rh_head;
   2022          rh_head = rh_head->next, cnt++)
   2023     {
   2024       switch (rh_head->type)
   2025       {
   2026       case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE:
   2027         bt = rh_head->details.bank;
   2028         FAILIF (0 !=
   2029                 GNUNET_memcmp (&bt->reserve_pub,
   2030                                &reserve_pub));
   2031         /* this is the amount we transferred twice*/
   2032         FAILIF (1 != bt->amount.value);
   2033         FAILIF (1000 != bt->amount.fraction);
   2034         FAILIF (0 != strcmp (CURRENCY,
   2035                              bt->amount.currency));
   2036         FAILIF (NULL == bt->sender_account_details.full_payto);
   2037         break;
   2038       case TALER_EXCHANGEDB_RO_WITHDRAW_COINS:
   2039         {
   2040           struct TALER_EXCHANGEDB_Withdraw *rh_withdraw  =
   2041             rh_head->details.withdraw;
   2042           FAILIF (0 !=
   2043                   GNUNET_memcmp (&rh_withdraw->reserve_pub,
   2044                                  &reserve_pub));
   2045 #pragma message "maybe more tests!?"
   2046         }
   2047         break;
   2048       case TALER_EXCHANGEDB_RO_RECOUP_COIN:
   2049         {
   2050           struct TALER_EXCHANGEDB_Recoup *recoup = rh_head->details.recoup;
   2051 
   2052           FAILIF (0 !=
   2053                   GNUNET_memcmp (&recoup->coin_sig,
   2054                                  &coin_sig));
   2055           FAILIF (0 !=
   2056                   GNUNET_memcmp (&recoup->coin_blind,
   2057                                  &coin_blind));
   2058           FAILIF (0 !=
   2059                   GNUNET_memcmp (&recoup->reserve_pub,
   2060                                  &reserve_pub));
   2061           FAILIF (0 !=
   2062                   GNUNET_memcmp (&recoup->coin.coin_pub,
   2063                                  &deposit.coin.coin_pub));
   2064           FAILIF (0 !=
   2065                   TALER_amount_cmp (&recoup->value,
   2066                                     &global_value));
   2067         }
   2068         break;
   2069       case TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK:
   2070         {
   2071           struct TALER_EXCHANGEDB_ClosingTransfer *closing
   2072             = rh_head->details.closing;
   2073 
   2074           FAILIF (0 !=
   2075                   GNUNET_memcmp (&closing->reserve_pub,
   2076                                  &reserve_pub));
   2077           FAILIF (0 != TALER_amount_cmp (&closing->amount,
   2078                                          &amount_with_fee));
   2079           FAILIF (0 != TALER_amount_cmp (&closing->closing_fee,
   2080                                          &fee_closing));
   2081         }
   2082         break;
   2083       case TALER_EXCHANGEDB_RO_PURSE_MERGE:
   2084         {
   2085           /* FIXME: not yet tested */
   2086           break;
   2087         }
   2088       case TALER_EXCHANGEDB_RO_HISTORY_REQUEST:
   2089         {
   2090           /* FIXME: not yet tested */
   2091           break;
   2092         }
   2093       case TALER_EXCHANGEDB_RO_OPEN_REQUEST:
   2094         {
   2095           /* FIXME: not yet tested */
   2096           break;
   2097         }
   2098       case TALER_EXCHANGEDB_RO_CLOSE_REQUEST:
   2099         {
   2100           /* FIXME: not yet tested */
   2101           break;
   2102         }
   2103       }
   2104     }
   2105     GNUNET_assert (4 == cnt);
   2106     FAILIF (4 != cnt);
   2107   }
   2108 
   2109   auditor_row_cnt = 0;
   2110   FAILIF (0 >=
   2111           plugin->select_reserves_in_above_serial_id (plugin->cls,
   2112                                                       0,
   2113                                                       &audit_reserve_in_cb,
   2114                                                       NULL));
   2115   FAILIF (0 >=
   2116           plugin->select_withdrawals_above_serial_id (plugin->cls,
   2117                                                       0,
   2118                                                       &audit_reserve_out_cb,
   2119                                                       NULL));
   2120   FAILIF (3 != auditor_row_cnt);
   2121 
   2122 
   2123   auditor_row_cnt = 0;
   2124   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   2125           plugin->select_refunds_above_serial_id (plugin->cls,
   2126                                                   0,
   2127                                                   &audit_refund_cb,
   2128                                                   NULL));
   2129   FAILIF (1 != auditor_row_cnt);
   2130   {
   2131     uint64_t etag = 0;
   2132     struct TALER_Amount balance;
   2133     struct TALER_DenominationHashP h_denom_pub;
   2134     struct TALER_EXCHANGEDB_TransactionList *tl;
   2135 
   2136     qs = plugin->get_coin_transactions (plugin->cls,
   2137                                         true,
   2138                                         &refund.coin.coin_pub,
   2139                                         0,
   2140                                         0,
   2141                                         &etag,
   2142                                         &balance,
   2143                                         &h_denom_pub,
   2144                                         &tl);
   2145     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs);
   2146     GNUNET_assert (NULL != tl);
   2147     matched = 0;
   2148     for (struct TALER_EXCHANGEDB_TransactionList *tlp = tl;
   2149          NULL != tlp;
   2150          tlp = tlp->next)
   2151     {
   2152       switch (tlp->type)
   2153       {
   2154       case TALER_EXCHANGEDB_TT_DEPOSIT:
   2155         {
   2156           struct TALER_EXCHANGEDB_DepositListEntry *have = tlp->details.deposit;
   2157 
   2158           /* Note: we're not comparing the denomination keys, as there is
   2159              still the question of whether we should even bother exporting
   2160              them here. */
   2161           FAILIF (0 !=
   2162                   GNUNET_memcmp (&have->csig,
   2163                                  &deposit.csig));
   2164           FAILIF (0 !=
   2165                   GNUNET_memcmp (&have->merchant_pub,
   2166                                  &bd.merchant_pub));
   2167           FAILIF (0 !=
   2168                   GNUNET_memcmp (&have->h_contract_terms,
   2169                                  &bd.h_contract_terms));
   2170           FAILIF (0 !=
   2171                   GNUNET_memcmp (&have->wire_salt,
   2172                                  &bd.wire_salt));
   2173           FAILIF (GNUNET_TIME_timestamp_cmp (have->timestamp,
   2174                                              !=,
   2175                                              bd.wallet_timestamp));
   2176           FAILIF (GNUNET_TIME_timestamp_cmp (have->refund_deadline,
   2177                                              !=,
   2178                                              bd.refund_deadline));
   2179           FAILIF (GNUNET_TIME_timestamp_cmp (have->wire_deadline,
   2180                                              !=,
   2181                                              bd.wire_deadline));
   2182           FAILIF (0 != TALER_amount_cmp (&have->amount_with_fee,
   2183                                          &deposit.amount_with_fee));
   2184           matched |= 1;
   2185           break;
   2186         }
   2187       /* this coin pub was actually never melted... */
   2188       case TALER_EXCHANGEDB_TT_MELT:
   2189         FAILIF (0 !=
   2190                 GNUNET_memcmp (&refresh.rc,
   2191                                &tlp->details.melt->rc));
   2192         matched |= 2;
   2193         break;
   2194       case TALER_EXCHANGEDB_TT_REFUND:
   2195         {
   2196           struct TALER_EXCHANGEDB_RefundListEntry *have = tlp->details.refund;
   2197 
   2198           /* Note: we're not comparing the denomination keys, as there is
   2199              still the question of whether we should even bother exporting
   2200              them here. */
   2201           FAILIF (0 != GNUNET_memcmp (&have->merchant_pub,
   2202                                       &refund.details.merchant_pub));
   2203           FAILIF (0 != GNUNET_memcmp (&have->merchant_sig,
   2204                                       &refund.details.merchant_sig));
   2205           FAILIF (0 != GNUNET_memcmp (&have->h_contract_terms,
   2206                                       &refund.details.h_contract_terms));
   2207           FAILIF (have->rtransaction_id != refund.details.rtransaction_id);
   2208           FAILIF (0 != TALER_amount_cmp (&have->refund_amount,
   2209                                          &refund.details.refund_amount));
   2210           FAILIF (0 != TALER_amount_cmp (&have->refund_fee,
   2211                                          &refund.details.refund_fee));
   2212           matched |= 4;
   2213           break;
   2214         }
   2215       case TALER_EXCHANGEDB_TT_RECOUP:
   2216         {
   2217           struct TALER_EXCHANGEDB_RecoupListEntry *recoup =
   2218             tlp->details.recoup;
   2219 
   2220           FAILIF (0 != GNUNET_memcmp (&recoup->coin_sig,
   2221                                       &coin_sig));
   2222           FAILIF (0 != GNUNET_memcmp (&recoup->coin_blind,
   2223                                       &coin_blind));
   2224           FAILIF (0 != GNUNET_memcmp (&recoup->reserve_pub,
   2225                                       &reserve_pub));
   2226           FAILIF (0 != TALER_amount_cmp (&recoup->value,
   2227                                          &global_value));
   2228           matched |= 8;
   2229           break;
   2230         }
   2231       case TALER_EXCHANGEDB_TT_OLD_COIN_RECOUP:
   2232         /* FIXME: check fields better... */
   2233 #pragma \
   2234         message "TALER_EXCHANGEDB_TT_OLD_COIN_RECOUP case doesn't work right now"
   2235         matched |= 16;
   2236         break;
   2237       default:
   2238         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2239                     "Unexpected coin history transaction type: %d\n",
   2240                     tlp->type);
   2241         FAILIF (1);
   2242         break;
   2243       }
   2244     }
   2245     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2246                 "matched=%d, SKIPPING FAILIF(31 != matched) FOR NOW\n",
   2247                 matched);
   2248 #pragma message "skipping FAILIF(31 != matched) check for now"
   2249 #if 0
   2250     FAILIF (31 != matched);
   2251 #endif
   2252 
   2253     plugin->free_coin_transaction_list (plugin->cls,
   2254                                         tl);
   2255   }
   2256 
   2257   /* Tests for deposits+wire */
   2258   TALER_denom_sig_free (&deposit.coin.denom_sig);
   2259   memset (&deposit,
   2260           0,
   2261           sizeof (deposit));
   2262   RND_BLK (&deposit.coin.coin_pub);
   2263   TALER_denom_pub_hash (&dkp->pub,
   2264                         &deposit.coin.denom_pub_hash);
   2265   GNUNET_assert (GNUNET_OK ==
   2266                  TALER_denom_sig_unblind (&deposit.coin.denom_sig,
   2267                                           &cbc.sig,
   2268                                           &bks,
   2269                                           &c_hash,
   2270                                           alg_values,
   2271                                           &dkp->pub));
   2272   RND_BLK (&deposit.csig);
   2273   RND_BLK (&bd.merchant_pub);
   2274   RND_BLK (&bd.h_contract_terms);
   2275   RND_BLK (&bd.wire_salt);
   2276   bd.receiver_wire_account.full_payto =
   2277     (char *) "payto://iban/DE67830654080004822650?receiver-name=Test";
   2278   TALER_merchant_wire_signature_hash (
   2279     bd.receiver_wire_account,
   2280     &bd.wire_salt,
   2281     &h_wire_wt);
   2282   deposit.amount_with_fee = global_value;
   2283   bd.refund_deadline = deadline;
   2284   bd.wire_deadline = deadline;
   2285   result = 8;
   2286   FAILIF (GNUNET_OK !=
   2287           plugin->start (plugin->cls,
   2288                          "test-3"));
   2289   {
   2290     uint64_t known_coin_id2;
   2291     struct TALER_DenominationHashP dph;
   2292     struct TALER_AgeCommitmentHashP agh;
   2293 
   2294     FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
   2295             plugin->ensure_coin_known (plugin->cls,
   2296                                        &deposit.coin,
   2297                                        &known_coin_id2,
   2298                                        &dph,
   2299                                        &agh));
   2300   }
   2301   now = GNUNET_TIME_timestamp_get ();
   2302   {
   2303     struct GNUNET_TIME_Timestamp r;
   2304     struct TALER_Amount deposit_fee;
   2305     struct TALER_MerchantWireHashP h_wire;
   2306     bool balance_ok;
   2307     uint32_t bad_idx;
   2308     bool ctr_conflict;
   2309 
   2310     TALER_full_payto_hash (bd.receiver_wire_account,
   2311                            &bd.wire_target_h_payto);
   2312     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   2313             plugin->do_deposit (plugin->cls,
   2314                                 &bd,
   2315                                 &now,
   2316                                 &balance_ok,
   2317                                 &bad_idx,
   2318                                 &ctr_conflict));
   2319     TALER_merchant_wire_signature_hash (bd.receiver_wire_account,
   2320                                         &bd.wire_salt,
   2321                                         &h_wire);
   2322     FAILIF (1 !=
   2323             plugin->have_deposit2 (plugin->cls,
   2324                                    &bd.h_contract_terms,
   2325                                    &h_wire,
   2326                                    &deposit.coin.coin_pub,
   2327                                    &bd.merchant_pub,
   2328                                    bd.refund_deadline,
   2329                                    &deposit_fee,
   2330                                    &r));
   2331     FAILIF (GNUNET_TIME_timestamp_cmp (now,
   2332                                        !=,
   2333                                        r));
   2334   }
   2335   {
   2336     result = 66;
   2337     FAILIF (0 >=
   2338             plugin->select_batch_deposits_missing_wire (plugin->cls,
   2339                                                         0,
   2340                                                         &wire_missing_cb,
   2341                                                         &deposit));
   2342     FAILIF (8 != result);
   2343   }
   2344   auditor_row_cnt = 0;
   2345   FAILIF (0 >=
   2346           plugin->select_coin_deposits_above_serial_id (plugin->cls,
   2347                                                         0,
   2348                                                         &audit_deposit_cb,
   2349                                                         NULL));
   2350   FAILIF (0 == auditor_row_cnt);
   2351   result = 8;
   2352   sleep (2); /* give deposit time to be ready */
   2353   {
   2354     struct TALER_MerchantPublicKeyP merchant_pub2;
   2355     struct TALER_FullPayto payto_uri2;
   2356 
   2357     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   2358             plugin->get_ready_deposit (plugin->cls,
   2359                                        0,
   2360                                        INT32_MAX,
   2361                                        &merchant_pub2,
   2362                                        &payto_uri2));
   2363     FAILIF (0 != GNUNET_memcmp (&merchant_pub2,
   2364                                 &bd.merchant_pub));
   2365     FAILIF (0 != TALER_full_payto_cmp (payto_uri2,
   2366                                        bd.receiver_wire_account));
   2367     TALER_full_payto_hash (payto_uri2,
   2368                            &global_wire_target_h_payto);
   2369     GNUNET_free (payto_uri2.full_payto);
   2370   }
   2371 
   2372   {
   2373     struct TALER_Amount total;
   2374     struct TALER_WireTransferIdentifierRawP wtid;
   2375 
   2376     memset (&wtid,
   2377             41,
   2378             sizeof (wtid));
   2379     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   2380             plugin->aggregate (plugin->cls,
   2381                                &global_wire_target_h_payto,
   2382                                &bd.merchant_pub,
   2383                                &wtid,
   2384                                &total));
   2385   }
   2386   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   2387           plugin->commit (plugin->cls));
   2388   FAILIF (GNUNET_OK !=
   2389           plugin->start (plugin->cls,
   2390                          "test-3"));
   2391   {
   2392     struct TALER_WireTransferIdentifierRawP wtid;
   2393     struct TALER_Amount total;
   2394     struct TALER_WireTransferIdentifierRawP wtid2;
   2395     struct TALER_Amount total2;
   2396 
   2397     memset (&wtid,
   2398             42,
   2399             sizeof (wtid));
   2400     GNUNET_assert (GNUNET_OK ==
   2401                    TALER_string_to_amount (CURRENCY ":42",
   2402                                            &total));
   2403     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   2404             plugin->select_aggregation_transient (
   2405               plugin->cls,
   2406               &global_wire_target_h_payto,
   2407               &bd.merchant_pub,
   2408               "x-bank",
   2409               &wtid2,
   2410               &total2));
   2411     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   2412             plugin->create_aggregation_transient (
   2413               plugin->cls,
   2414               &global_wire_target_h_payto,
   2415               "x-bank",
   2416               &bd.merchant_pub,
   2417               &wtid,
   2418               0,
   2419               &total));
   2420     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   2421             plugin->select_aggregation_transient (
   2422               plugin->cls,
   2423               &global_wire_target_h_payto,
   2424               &bd.merchant_pub,
   2425               "x-bank",
   2426               &wtid2,
   2427               &total2));
   2428     FAILIF (0 !=
   2429             GNUNET_memcmp (&wtid2,
   2430                            &wtid));
   2431     FAILIF (0 !=
   2432             TALER_amount_cmp (&total2,
   2433                               &total));
   2434     GNUNET_assert (GNUNET_OK ==
   2435                    TALER_string_to_amount (CURRENCY ":43",
   2436                                            &total));
   2437     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   2438             plugin->update_aggregation_transient (
   2439               plugin->cls,
   2440               &global_wire_target_h_payto,
   2441               &wtid,
   2442               0,
   2443               &total));
   2444     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   2445             plugin->select_aggregation_transient (
   2446               plugin->cls,
   2447               &global_wire_target_h_payto,
   2448               &bd.merchant_pub,
   2449               "x-bank",
   2450               &wtid2,
   2451               &total2));
   2452     FAILIF (0 !=
   2453             GNUNET_memcmp (&wtid2,
   2454                            &wtid));
   2455     FAILIF (0 !=
   2456             TALER_amount_cmp (&total2,
   2457                               &total));
   2458     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   2459             plugin->delete_aggregation_transient (
   2460               plugin->cls,
   2461               &global_wire_target_h_payto,
   2462               &wtid));
   2463     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   2464             plugin->select_aggregation_transient (
   2465               plugin->cls,
   2466               &global_wire_target_h_payto,
   2467               &bd.merchant_pub,
   2468               "x-bank",
   2469               &wtid2,
   2470               &total2));
   2471   }
   2472   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   2473           plugin->commit (plugin->cls));
   2474 
   2475   result = 10;
   2476   FAILIF (GNUNET_OK !=
   2477           plugin->start (plugin->cls,
   2478                          "test-2"));
   2479   RND_BLK (&mpub2); /* should fail if merchant is different */
   2480   {
   2481     struct TALER_MerchantWireHashP h_wire;
   2482     struct GNUNET_TIME_Timestamp r;
   2483     struct TALER_Amount deposit_fee;
   2484 
   2485     TALER_merchant_wire_signature_hash (bd.receiver_wire_account,
   2486                                         &bd.wire_salt,
   2487                                         &h_wire);
   2488     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   2489             plugin->have_deposit2 (plugin->cls,
   2490                                    &bd.h_contract_terms,
   2491                                    &h_wire,
   2492                                    &deposit.coin.coin_pub,
   2493                                    &mpub2,
   2494                                    bd.refund_deadline,
   2495                                    &deposit_fee,
   2496                                    &r));
   2497     RND_BLK (&cpub2); /* should fail if coin is different */
   2498     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   2499             plugin->have_deposit2 (plugin->cls,
   2500                                    &bd.h_contract_terms,
   2501                                    &h_wire,
   2502                                    &cpub2,
   2503                                    &bd.merchant_pub,
   2504                                    bd.refund_deadline,
   2505                                    &deposit_fee,
   2506                                    &r));
   2507   }
   2508   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   2509           plugin->commit (plugin->cls));
   2510 
   2511 
   2512   /* test revocation */
   2513   FAILIF (GNUNET_OK !=
   2514           plugin->start (plugin->cls,
   2515                          "test-3b"));
   2516   RND_BLK (&master_sig);
   2517   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   2518           plugin->insert_denomination_revocation (plugin->cls,
   2519                                                   &cbc.denom_pub_hash,
   2520                                                   &master_sig));
   2521   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   2522           plugin->commit (plugin->cls));
   2523   plugin->preflight (plugin->cls);
   2524   FAILIF (GNUNET_OK !=
   2525           plugin->start (plugin->cls,
   2526                          "test-4"));
   2527   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
   2528           plugin->insert_denomination_revocation (plugin->cls,
   2529                                                   &cbc.denom_pub_hash,
   2530                                                   &master_sig));
   2531   plugin->rollback (plugin->cls);
   2532   plugin->preflight (plugin->cls);
   2533   FAILIF (GNUNET_OK !=
   2534           plugin->start (plugin->cls,
   2535                          "test-5"));
   2536   {
   2537     struct TALER_MasterSignatureP msig;
   2538     uint64_t rev_rowid;
   2539 
   2540     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
   2541             plugin->get_denomination_revocation (plugin->cls,
   2542                                                  &cbc.denom_pub_hash,
   2543                                                  &msig,
   2544                                                  &rev_rowid));
   2545     FAILIF (0 != GNUNET_memcmp (&msig,
   2546                                 &master_sig));
   2547   }
   2548 
   2549 
   2550   plugin->rollback (plugin->cls);
   2551   FAILIF (GNUNET_OK !=
   2552           test_wire_prepare ());
   2553   FAILIF (GNUNET_OK !=
   2554           test_wire_out (&bd));
   2555   FAILIF (GNUNET_OK !=
   2556           test_gc ());
   2557   FAILIF (GNUNET_OK !=
   2558           test_wire_fees ());
   2559 
   2560   plugin->preflight (plugin->cls);
   2561 
   2562   result = 0;
   2563 
   2564 drop:
   2565   if (0 != result)
   2566     plugin->rollback (plugin->cls);
   2567   if (NULL != rh)
   2568     plugin->free_reserve_history (plugin->cls,
   2569                                   rh);
   2570   rh = NULL;
   2571   GNUNET_break (GNUNET_OK ==
   2572                 plugin->drop_tables (plugin->cls));
   2573 cleanup:
   2574   if (NULL != dkp)
   2575     destroy_denom_key_pair (dkp);
   2576   if (NULL != revealed_coins)
   2577   {
   2578     for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
   2579     {
   2580       TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig);
   2581       TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet);
   2582     }
   2583     GNUNET_free (revealed_coins);
   2584     revealed_coins = NULL;
   2585   }
   2586   GNUNET_free (new_denom_pubs);
   2587   for (unsigned int cnt = 0;
   2588        (NULL != new_dkp) && (cnt < MELT_NEW_COINS) && (NULL != new_dkp[cnt]);
   2589        cnt++)
   2590     destroy_denom_key_pair (new_dkp[cnt]);
   2591   GNUNET_free (new_dkp);
   2592   TALER_denom_sig_free (&deposit.coin.denom_sig);
   2593   TALER_blinded_denom_sig_free (&cbc.sig);
   2594   TALER_blinded_denom_sig_free (withdraw.denom_sigs);
   2595   dkp = NULL;
   2596   TALER_EXCHANGEDB_plugin_unload (plugin);
   2597   plugin = NULL;
   2598 }
   2599 
   2600 
   2601 int
   2602 main (int argc,
   2603       char *const argv[])
   2604 {
   2605   const char *plugin_name;
   2606   char *config_filename;
   2607   char *testname;
   2608   struct GNUNET_CONFIGURATION_Handle *cfg;
   2609 
   2610   (void) argc;
   2611   result = -1;
   2612   if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
   2613   {
   2614     GNUNET_break (0);
   2615     return -1;
   2616   }
   2617   GNUNET_log_setup (argv[0],
   2618                     "INFO",
   2619                     NULL);
   2620   plugin_name++;
   2621   (void) GNUNET_asprintf (&testname,
   2622                           "test-exchange-db-%s",
   2623                           plugin_name);
   2624   (void) GNUNET_asprintf (&config_filename,
   2625                           "%s.conf",
   2626                           testname);
   2627   cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ());
   2628   if (GNUNET_OK !=
   2629       GNUNET_CONFIGURATION_parse (cfg,
   2630                                   config_filename))
   2631   {
   2632     GNUNET_break (0);
   2633     GNUNET_free (config_filename);
   2634     GNUNET_free (testname);
   2635     return 2;
   2636   }
   2637   GNUNET_SCHEDULER_run (&run,
   2638                         cfg);
   2639   GNUNET_CONFIGURATION_destroy (cfg);
   2640   GNUNET_free (config_filename);
   2641   GNUNET_free (testname);
   2642   return result;
   2643 }
   2644 
   2645 
   2646 /* end of test_exchangedb.c */