merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

taler-merchant-httpd_post-orders-ID-pay.c (154805B)


      1 /*
      2    This file is part of TALER
      3    (C) 2014-2025 Taler Systems SA
      4 
      5    TALER is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU Affero General Public License as
      7    published by the Free Software Foundation; either version 3,
      8    or (at your option) any later version.
      9 
     10    TALER is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public
     16    License along with TALER; see the file COPYING.  If not,
     17    see <http://www.gnu.org/licenses/>
     18  */
     19 
     20 /**
     21  * @file taler-merchant-httpd_post-orders-ID-pay.c
     22  * @brief handling of POST /orders/$ID/pay requests
     23  * @author Marcello Stanisci
     24  * @author Christian Grothoff
     25  * @author Florian Dold
     26  */
     27 #include "platform.h"
     28 #include <gnunet/gnunet_common.h>
     29 #include <gnunet/gnunet_db_lib.h>
     30 #include <gnunet/gnunet_json_lib.h>
     31 #include <gnunet/gnunet_time_lib.h>
     32 #include <jansson.h>
     33 #include <microhttpd.h>
     34 #include <stddef.h>
     35 #include <stdint.h>
     36 #include <string.h>
     37 #include <taler/taler_dbevents.h>
     38 #include <taler/taler_error_codes.h>
     39 #include <taler/taler_signatures.h>
     40 #include <taler/taler_json_lib.h>
     41 #include <taler/taler_exchange_service.h>
     42 #include "taler-merchant-httpd.h"
     43 #include "taler-merchant-httpd_exchanges.h"
     44 #include "taler-merchant-httpd_helper.h"
     45 #include "taler-merchant-httpd_post-orders-ID-pay.h"
     46 #include "taler-merchant-httpd_private-get-orders.h"
     47 #include "taler_merchant_util.h"
     48 #include "taler_merchantdb_plugin.h"
     49 
     50 #ifdef HAVE_DONAU_DONAU_SERVICE_H
     51 #include <donau/donau_service.h>
     52 #include <donau/donau_util.h>
     53 #include <donau/donau_json_lib.h>
     54 #endif
     55 
     56 /**
     57  * How often do we retry the (complex!) database transaction?
     58  */
     59 #define MAX_RETRIES 5
     60 
     61 /**
     62  * Maximum number of coins that we allow per transaction.
     63  * Note that the limit for each batch deposit request to
     64  * the exchange is lower, so we may break a very large
     65  * number of coins up into multiple smaller requests to
     66  * the exchange.
     67  */
     68 #define MAX_COIN_ALLOWED_COINS 1024
     69 
     70 /**
     71  * Maximum number of tokens that we allow as inputs per transaction
     72  */
     73 #define MAX_TOKEN_ALLOWED_INPUTs 64
     74 
     75 /**
     76  * Maximum number of tokens that we allow as outputs per transaction
     77  */
     78 #define MAX_TOKEN_ALLOWED_OUTPUTs 64
     79 
     80 /**
     81  * How often do we ask the exchange again about our
     82  * KYC status? Very rarely, as if the user actively
     83  * changes it, we should usually notice anyway.
     84  */
     85 #define KYC_RETRY_FREQUENCY GNUNET_TIME_UNIT_WEEKS
     86 
     87 /**
     88  * Information we keep for an individual call to the pay handler.
     89  */
     90 struct PayContext;
     91 
     92 
     93 /**
     94  * Different phases of processing the /pay request.
     95  */
     96 enum PayPhase
     97 {
     98   /**
     99    * Initial phase where the request is parsed.
    100    */
    101   PP_PARSE_PAY = 0,
    102 
    103   /**
    104    * Parse wallet data object from the pay request.
    105    */
    106   PP_PARSE_WALLET_DATA,
    107 
    108   /**
    109    * Check database state for the given order.
    110    */
    111   PP_CHECK_CONTRACT,
    112 
    113   /**
    114    * Validate provided tokens and token envelopes.
    115    */
    116   PP_VALIDATE_TOKENS,
    117 
    118   /**
    119    * Check if contract has been paid.
    120    */
    121   PP_CONTRACT_PAID,
    122 
    123   /**
    124    * Execute payment transaction.
    125    */
    126   PP_PAY_TRANSACTION,
    127 
    128   /**
    129    * Communicate with DONAU to generate a donation receipt from the donor BUDIs.
    130    */
    131   PP_REQUEST_DONATION_RECEIPT,
    132 
    133   /**
    134    * Process the donation receipt response from DONAU (save the donau_sigs to the db).
    135    */
    136   PP_FINAL_OUTPUT_TOKEN_PROCESSING,
    137 
    138   /**
    139    * Notify other processes about successful payment.
    140    */
    141   PP_PAYMENT_NOTIFICATION,
    142 
    143   /**
    144    * Create final success response.
    145    */
    146   PP_SUCCESS_RESPONSE,
    147 
    148   /**
    149    * Perform batch deposits with exchange(s).
    150    */
    151   PP_BATCH_DEPOSITS,
    152 
    153   /**
    154    * Return response in payment context.
    155    */
    156   PP_RETURN_RESPONSE,
    157 
    158   /**
    159    * An exchange denied a deposit, fail for
    160    * legal reasons.
    161    */
    162   PP_FAIL_LEGAL_REASONS,
    163 
    164   /**
    165    * Return #MHD_YES to end processing.
    166    */
    167   PP_END_YES,
    168 
    169   /**
    170    * Return #MHD_NO to end processing.
    171    */
    172   PP_END_NO
    173 };
    174 
    175 
    176 /**
    177  * Information kept during a pay request for each coin.
    178  */
    179 struct DepositConfirmation
    180 {
    181 
    182   /**
    183    * Reference to the main PayContext
    184    */
    185   struct PayContext *pc;
    186 
    187   /**
    188    * URL of the exchange that issued this coin.
    189    */
    190   char *exchange_url;
    191 
    192   /**
    193    * Details about the coin being deposited.
    194    */
    195   struct TALER_EXCHANGE_CoinDepositDetail cdd;
    196 
    197   /**
    198    * Fee charged by the exchange for the deposit operation of this coin.
    199    */
    200   struct TALER_Amount deposit_fee;
    201 
    202   /**
    203    * Fee charged by the exchange for the refund operation of this coin.
    204    */
    205   struct TALER_Amount refund_fee;
    206 
    207   /**
    208    * If a minimum age was required (i. e. pc->minimum_age is large enough),
    209    * this is the signature of the minimum age (as a single uint8_t), using the
    210    * private key to the corresponding age group.  Might be all zeroes for no
    211    * age attestation.
    212    */
    213   struct TALER_AgeAttestationP minimum_age_sig;
    214 
    215   /**
    216    * If a minimum age was required (i. e. pc->minimum_age is large enough),
    217    * this is the age commitment (i. e. age mask and vector of EdDSA public
    218    * keys, one per age group) that went into the mining of the coin.  The
    219    * SHA256 hash of the mask and the vector of public keys was bound to the
    220    * key.
    221    */
    222   struct TALER_AgeCommitment age_commitment;
    223 
    224   /**
    225    * Age mask in the denomination that defines the age groups.  Only
    226    * applicable, if minimum age was required.
    227    */
    228   struct TALER_AgeMask age_mask;
    229 
    230   /**
    231    * Offset of this coin into the `dc` array of all coins in the
    232    * @e pc.
    233    */
    234   unsigned int index;
    235 
    236   /**
    237    * true, if no field "age_commitment" was found in the JSON blob
    238    */
    239   bool no_age_commitment;
    240 
    241   /**
    242    * True, if no field "minimum_age_sig" was found in the JSON blob
    243    */
    244   bool no_minimum_age_sig;
    245 
    246   /**
    247    * true, if no field "h_age_commitment" was found in the JSON blob
    248    */
    249   bool no_h_age_commitment;
    250 
    251   /**
    252    * true if we found this coin in the database.
    253    */
    254   bool found_in_db;
    255 
    256   /**
    257    * true if we #deposit_paid_check() matched this coin in the database.
    258    */
    259   bool matched_in_db;
    260 
    261 };
    262 
    263 struct TokenUseConfirmation
    264 {
    265 
    266   /**
    267    * Signature on the deposit request made using the token use private key.
    268    */
    269   struct TALER_TokenUseSignatureP sig;
    270 
    271   /**
    272    * Token use public key. This key was blindly signed by the merchant during
    273    * the token issuance process.
    274    */
    275   struct TALER_TokenUsePublicKeyP pub;
    276 
    277   /**
    278    * Unblinded signature on the token use public key done by the merchant.
    279    */
    280   struct TALER_TokenIssueSignature unblinded_sig;
    281 
    282   /**
    283    * Hash of the token issue public key associated with this token.
    284    * Note this is set in the validate_tokens phase.
    285    */
    286   struct TALER_TokenIssuePublicKeyHashP h_issue;
    287 
    288   /**
    289    * true if we found this token in the database.
    290    */
    291   bool found_in_db;
    292 
    293 };
    294 
    295 
    296 /**
    297  * Information about a token envelope.
    298  */
    299 struct TokenEnvelope
    300 {
    301 
    302   /**
    303    * Blinded token use public keys waiting to be signed.
    304    */
    305   struct TALER_TokenEnvelope blinded_token;
    306 
    307 };
    308 
    309 
    310 /**
    311  * (Blindly) signed token to be returned to the wallet.
    312  */
    313 struct SignedOutputToken
    314 {
    315 
    316   /**
    317    * Index of the output token that produced
    318    * this blindly signed token.
    319    */
    320   unsigned int output_index;
    321 
    322   /**
    323    * Blinded token use public keys waiting to be signed.
    324    */
    325   struct TALER_BlindedTokenIssueSignature sig;
    326 
    327   /**
    328    * Hash of token issue public key.
    329    */
    330   struct TALER_TokenIssuePublicKeyHashP h_issue;
    331 
    332 };
    333 
    334 
    335 /**
    336  * Information kept during a pay request for each exchange.
    337  */
    338 struct ExchangeGroup
    339 {
    340 
    341   /**
    342    * Payment context this group is part of.
    343    */
    344   struct PayContext *pc;
    345 
    346   /**
    347    * Handle to the batch deposit operation we are performing for this
    348    * exchange, NULL after the operation is done.
    349    */
    350   struct TALER_EXCHANGE_BatchDepositHandle *bdh;
    351 
    352   /**
    353    * Handle for operation to lookup /keys (and auditors) from
    354    * the exchange used for this transaction; NULL if no operation is
    355    * pending.
    356    */
    357   struct TMH_EXCHANGES_KeysOperation *fo;
    358 
    359   /**
    360    * URL of the exchange that issued this coin. Aliases
    361    * the exchange URL of one of the coins, do not free!
    362    */
    363   const char *exchange_url;
    364 
    365   /**
    366    * Total deposit amount in this exchange group.
    367    */
    368   struct TALER_Amount total;
    369 
    370   /**
    371    * Wire fee that applies to this exchange for the
    372    * given payment context's wire method.
    373    */
    374   struct TALER_Amount wire_fee;
    375 
    376   /**
    377    * true if we already tried a forced /keys download.
    378    */
    379   bool tried_force_keys;
    380 
    381   /**
    382    * Did this exchange deny the transaction for legal reasons?
    383    */
    384   bool got_451;
    385 };
    386 
    387 
    388 /**
    389  * Information about donau, that can be fetched even
    390  * if the merhchant doesn't support donau
    391  */
    392 struct DonauData
    393 {
    394   /**
    395    * The user-selected Donau URL.
    396    */
    397   char *donau_url;
    398 
    399   /**
    400    * The donation year, as parsed from "year".
    401    */
    402   uint64_t donation_year;
    403 
    404   /**
    405    * The original BUDI key-pairs array from the donor
    406    * to be used for the receipt creation.
    407    */
    408   const json_t *budikeypairs;
    409 };
    410 
    411 /**
    412  * Information we keep for an individual call to the /pay handler.
    413  */
    414 struct PayContext
    415 {
    416 
    417   /**
    418    * Stored in a DLL.
    419    */
    420   struct PayContext *next;
    421 
    422   /**
    423    * Stored in a DLL.
    424    */
    425   struct PayContext *prev;
    426 
    427   /**
    428    * MHD connection to return to
    429    */
    430   struct MHD_Connection *connection;
    431 
    432   /**
    433    * Details about the client's request.
    434    */
    435   struct TMH_HandlerContext *hc;
    436 
    437   /**
    438    * Transaction ID given in @e root.
    439    */
    440   const char *order_id;
    441 
    442   /**
    443    * Response to return, NULL if we don't have one yet.
    444    */
    445   struct MHD_Response *response;
    446 
    447   /**
    448    * Array with @e output_tokens_len signed tokens returned in
    449    * the response to the wallet.
    450    */
    451   struct SignedOutputToken *output_tokens;
    452 
    453   /**
    454    * Number of output tokens to return in the response.
    455    * Length of the @e output_tokens array.
    456    */
    457   unsigned int output_tokens_len;
    458 
    459   /**
    460    * Counter used to generate the output index in append_output_token_sig().
    461    */
    462   unsigned int output_index_gen;
    463 
    464   /**
    465    * Counter used to generate the output index in append_output_token_sig().
    466    *
    467    * Counts the generated tokens _within_ the current output_index_gen.
    468    */
    469   unsigned int output_token_cnt;
    470 
    471   /**
    472    * HTTP status code to use for the reply, i.e 200 for "OK".
    473    * Special value UINT_MAX is used to indicate hard errors
    474    * (no reply, return #MHD_NO).
    475    */
    476   unsigned int response_code;
    477 
    478   /**
    479    * Payment processing phase we are in.
    480    */
    481   enum PayPhase phase;
    482 
    483   /**
    484    * #GNUNET_NO if the @e connection was not suspended,
    485    * #GNUNET_YES if the @e connection was suspended,
    486    * #GNUNET_SYSERR if @e connection was resumed to as
    487    * part of #MH_force_pc_resume during shutdown.
    488    */
    489   enum GNUNET_GenericReturnValue suspended;
    490 
    491   /**
    492    * Results from the phase_parse_pay()
    493    */
    494   struct
    495   {
    496 
    497     /**
    498      * Array with @e num_exchanges exchanges we are depositing
    499      * coins into.
    500      */
    501     struct ExchangeGroup **egs;
    502 
    503     /**
    504      * Array with @e coins_cnt coins we are despositing.
    505      */
    506     struct DepositConfirmation *dc;
    507 
    508     /**
    509      * Array with @e tokens_cnt input tokens passed to this request.
    510      */
    511     struct TokenUseConfirmation *tokens;
    512 
    513     /**
    514      * Optional session id given in @e root.
    515      * NULL if not given.
    516      */
    517     char *session_id;
    518 
    519     /**
    520      * Wallet data json object from the request. Containing additional
    521      * wallet data such as the selected choice_index.
    522      */
    523     const json_t *wallet_data;
    524 
    525     /**
    526      * Number of coins this payment is made of.  Length
    527      * of the @e dc array.
    528      */
    529     size_t coins_cnt;
    530 
    531     /**
    532      * Number of input tokens passed to this request.  Length
    533      * of the @e tokens array.
    534      */
    535     size_t tokens_cnt;
    536 
    537     /**
    538      * Number of exchanges involved in the payment. Length
    539      * of the @e eg array.
    540      */
    541     unsigned int num_exchanges;
    542 
    543   } parse_pay;
    544 
    545   /**
    546    * Results from the phase_wallet_data()
    547    */
    548   struct
    549   {
    550 
    551     /**
    552      * Array with @e token_envelopes_cnt (blinded) token envelopes.
    553      */
    554     struct TokenEnvelope *token_envelopes;
    555 
    556     /**
    557      * Index of selected choice in the @e contract_terms choices array.
    558      */
    559     int16_t choice_index;
    560 
    561     /**
    562      * Number of token envelopes passed to this request.
    563      * Length of the @e token_envelopes array.
    564      */
    565     size_t token_envelopes_cnt;
    566 
    567     /**
    568      * Hash of the canonicalized wallet data json object.
    569      */
    570     struct GNUNET_HashCode h_wallet_data;
    571 
    572     /**
    573      * Donau related information
    574      */
    575     struct DonauData donau;
    576 
    577     /**
    578      * Serial from the DB of the donau instance that we are using
    579      */
    580     uint64_t donau_instance_serial;
    581 
    582 #ifdef  HAVE_DONAU_DONAU_SERVICE_H
    583     /**
    584      * Number of the blinded key pairs @e bkps
    585      */
    586     unsigned int num_bkps;
    587 
    588     /**
    589      * Blinded key pairs received from the wallet
    590      */
    591     struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps;
    592 
    593     /**
    594      * The id of the charity as saved on the donau.
    595      */
    596     uint64_t charity_id;
    597 
    598     /**
    599      * Private key of the charity(related to the private key of the merchant).
    600      */
    601     struct DONAU_CharityPrivateKeyP charity_priv;
    602 
    603     /**
    604      * Maximum amount of donations that the charity can receive per year.
    605      */
    606     struct TALER_Amount charity_max_per_year;
    607 
    608     /**
    609      * Amount of donations that the charity has received so far this year.
    610      */
    611     struct TALER_Amount charity_receipts_to_date;
    612 
    613     /**
    614      * Donau keys, that we are using to get the information about the bkps.
    615      */
    616     struct DONAU_Keys *donau_keys;
    617 
    618     /**
    619      * Amount from BKPS
    620      */
    621     struct TALER_Amount donation_amount;
    622 #endif
    623 
    624   } parse_wallet_data;
    625 
    626   /**
    627    * Results from the phase_check_contract()
    628    */
    629   struct
    630   {
    631 
    632     /**
    633      * Hashed @e contract_terms.
    634      */
    635     struct TALER_PrivateContractHashP h_contract_terms;
    636 
    637     /**
    638      * Our contract (or NULL if not available).
    639      */
    640     json_t *contract_terms_json;
    641 
    642     /**
    643      * Parsed contract terms, NULL when parsing failed.
    644      */
    645     struct TALER_MERCHANT_Contract *contract_terms;
    646 
    647     /**
    648      * What wire method (of the @e mi) was selected by the wallet?
    649      * Set in #phase_parse_pay().
    650      */
    651     struct TMH_WireMethod *wm;
    652 
    653     /**
    654      * Set to the POS key, if applicable for this order.
    655      */
    656     char *pos_key;
    657 
    658     /**
    659      * Serial number of this order in the database (set once we did the lookup).
    660      */
    661     uint64_t order_serial;
    662 
    663     /**
    664      * Algorithm chosen for generating the confirmation code.
    665      */
    666     enum TALER_MerchantConfirmationAlgorithm pos_alg;
    667 
    668   } check_contract;
    669 
    670   /**
    671    * Results from the phase_validate_tokens()
    672    */
    673   struct
    674   {
    675 
    676     /**
    677      * Maximum fee the merchant is willing to pay, from @e root.
    678      * Note that IF the total fee of the exchange is higher, that is
    679      * acceptable to the merchant if the customer is willing to
    680      * pay the difference
    681      * (i.e. amount - max_fee <= actual_amount - actual_fee).
    682      */
    683     struct TALER_Amount max_fee;
    684 
    685     /**
    686      * Amount from @e root.  This is the amount the merchant expects
    687      * to make, minus @e max_fee.
    688      */
    689     struct TALER_Amount brutto;
    690 
    691     /**
    692      * Index of the donau output in the list of tokens.
    693      * Set to -1 if no donau output exists.
    694      */
    695     int donau_output_index;
    696 
    697   } validate_tokens;
    698 
    699   /**
    700    * Results from the phase_execute_pay_transaction()
    701    */
    702   struct
    703   {
    704 
    705     /**
    706      * Considering all the coins with the "found_in_db" flag
    707      * set, what is the total amount we were so far paid on
    708      * this contract?
    709      */
    710     struct TALER_Amount total_paid;
    711 
    712     /**
    713      * Considering all the coins with the "found_in_db" flag
    714      * set, what is the total amount we had to pay in deposit
    715      * fees so far on this contract?
    716      */
    717     struct TALER_Amount total_fees_paid;
    718 
    719     /**
    720      * Considering all the coins with the "found_in_db" flag
    721      * set, what is the total amount we already refunded?
    722      */
    723     struct TALER_Amount total_refunded;
    724 
    725     /**
    726      * Number of coin deposits pending.
    727      */
    728     unsigned int pending;
    729 
    730     /**
    731      * How often have we retried the 'main' transaction?
    732      */
    733     unsigned int retry_counter;
    734 
    735     /**
    736      * Set to true if the deposit currency of a coin
    737      * does not match the contract currency.
    738      */
    739     bool deposit_currency_mismatch;
    740 
    741     /**
    742      * Set to true if the database contains a (bogus)
    743      * refund for a different currency.
    744      */
    745     bool refund_currency_mismatch;
    746 
    747   } pay_transaction;
    748 
    749   /**
    750    * Results from the phase_batch_deposits()
    751    */
    752   struct
    753   {
    754 
    755     /**
    756      * Task called when the (suspended) processing for
    757      * the /pay request times out.
    758      * Happens when we don't get a response from the exchange.
    759      */
    760     struct GNUNET_SCHEDULER_Task *timeout_task;
    761 
    762     /**
    763      * Number of batch transactions pending.
    764      */
    765     unsigned int pending_at_eg;
    766 
    767     /**
    768      * Did any exchange deny a deposit for legal reasons?
    769      */
    770     bool got_451;
    771 
    772   } batch_deposits;
    773 
    774 #ifdef HAVE_DONAU_DONAU_SERVICE_H
    775   /**
    776    * Struct for #phase_request_donation_receipt()
    777    */
    778   struct
    779   {
    780     /**
    781      * Handler of the donau request
    782      */
    783     struct DONAU_BatchIssueReceiptHandle *birh;
    784 
    785   } donau_receipt;
    786 #endif
    787 };
    788 
    789 
    790 /**
    791  * Head of active pay context DLL.
    792  */
    793 static struct PayContext *pc_head;
    794 
    795 /**
    796  * Tail of active pay context DLL.
    797  */
    798 static struct PayContext *pc_tail;
    799 
    800 
    801 void
    802 TMH_force_pc_resume ()
    803 {
    804   for (struct PayContext *pc = pc_head;
    805        NULL != pc;
    806        pc = pc->next)
    807   {
    808     if (NULL != pc->batch_deposits.timeout_task)
    809     {
    810       GNUNET_SCHEDULER_cancel (pc->batch_deposits.timeout_task);
    811       pc->batch_deposits.timeout_task = NULL;
    812     }
    813     if (GNUNET_YES == pc->suspended)
    814     {
    815       pc->suspended = GNUNET_SYSERR;
    816       MHD_resume_connection (pc->connection);
    817     }
    818   }
    819 }
    820 
    821 
    822 /**
    823  * Resume payment processing.
    824  *
    825  * @param[in,out] pc payment process to resume
    826  */
    827 static void
    828 pay_resume (struct PayContext *pc)
    829 {
    830   GNUNET_assert (GNUNET_YES == pc->suspended);
    831   pc->suspended = GNUNET_NO;
    832   MHD_resume_connection (pc->connection);
    833   TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */
    834 }
    835 
    836 
    837 /**
    838  * Resume the given pay context and send the given response.
    839  * Stores the response in the @a pc and signals MHD to resume
    840  * the connection.  Also ensures MHD runs immediately.
    841  *
    842  * @param pc payment context
    843  * @param response_code response code to use
    844  * @param response response data to send back
    845  */
    846 static void
    847 resume_pay_with_response (struct PayContext *pc,
    848                           unsigned int response_code,
    849                           struct MHD_Response *response)
    850 {
    851   pc->response_code = response_code;
    852   pc->response = response;
    853   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    854               "Resuming /pay handling. HTTP status for our reply is %u.\n",
    855               response_code);
    856   for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
    857   {
    858     struct ExchangeGroup *eg = pc->parse_pay.egs[i];
    859 
    860     if (NULL != eg->fo)
    861     {
    862       TMH_EXCHANGES_keys4exchange_cancel (eg->fo);
    863       eg->fo = NULL;
    864       pc->batch_deposits.pending_at_eg--;
    865     }
    866     if (NULL != eg->bdh)
    867     {
    868       TALER_EXCHANGE_batch_deposit_cancel (eg->bdh);
    869       eg->bdh = NULL;
    870       pc->batch_deposits.pending_at_eg--;
    871     }
    872   }
    873   GNUNET_assert (0 == pc->batch_deposits.pending_at_eg);
    874   if (NULL != pc->batch_deposits.timeout_task)
    875   {
    876     GNUNET_SCHEDULER_cancel (pc->batch_deposits.timeout_task);
    877     pc->batch_deposits.timeout_task = NULL;
    878   }
    879   pc->phase = PP_RETURN_RESPONSE;
    880   pay_resume (pc);
    881 }
    882 
    883 
    884 /**
    885  * Resume payment processing with an error.
    886  *
    887  * @param pc operation to resume
    888  * @param ec taler error code to return
    889  * @param msg human readable error message
    890  */
    891 static void
    892 resume_pay_with_error (struct PayContext *pc,
    893                        enum TALER_ErrorCode ec,
    894                        const char *msg)
    895 {
    896   resume_pay_with_response (
    897     pc,
    898     TALER_ErrorCode_get_http_status_safe (ec),
    899     TALER_MHD_make_error (ec,
    900                           msg));
    901 }
    902 
    903 
    904 /**
    905  * Conclude payment processing for @a pc with the
    906  * given @a res MHD status code.
    907  *
    908  * @param[in,out] pc payment context for final state transition
    909  * @param res MHD return code to end with
    910  */
    911 static void
    912 pay_end (struct PayContext *pc,
    913          MHD_RESULT res)
    914 {
    915   pc->phase = (MHD_YES == res)
    916     ? PP_END_YES
    917     : PP_END_NO;
    918 }
    919 
    920 
    921 /**
    922  * Return response stored in @a pc.
    923  *
    924  * @param[in,out] pc payment context we are processing
    925  */
    926 static void
    927 phase_return_response (struct PayContext *pc)
    928 {
    929   GNUNET_assert (0 != pc->response_code);
    930   /* We are *done* processing the request, just queue the response (!) */
    931   if (UINT_MAX == pc->response_code)
    932   {
    933     GNUNET_break (0);
    934     pay_end (pc,
    935              MHD_NO); /* hard error */
    936     return;
    937   }
    938   pay_end (pc,
    939            MHD_queue_response (pc->connection,
    940                                pc->response_code,
    941                                pc->response));
    942 }
    943 
    944 
    945 /**
    946  * Return a response indicating failure for legal reasons.
    947  *
    948  * @param[in,out] pc payment context we are processing
    949  */
    950 static void
    951 phase_fail_for_legal_reasons (struct PayContext *pc)
    952 {
    953   json_t *exchanges;
    954 
    955   GNUNET_assert (0 == pc->pay_transaction.pending);
    956   GNUNET_assert (pc->batch_deposits.got_451);
    957   exchanges = json_array ();
    958   GNUNET_assert (NULL != exchanges);
    959   for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
    960   {
    961     struct ExchangeGroup *eg = pc->parse_pay.egs[i];
    962 
    963     GNUNET_assert (NULL == eg->fo);
    964     GNUNET_assert (NULL == eg->bdh);
    965     if (! eg->got_451)
    966       continue;
    967     GNUNET_assert (
    968       0 ==
    969       json_array_append_new (
    970         exchanges,
    971         json_string (eg->exchange_url)));
    972   }
    973   pay_end (pc,
    974            TALER_MHD_REPLY_JSON_PACK (
    975              pc->connection,
    976              MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
    977              GNUNET_JSON_pack_array_steal ("exchange_base_urls",
    978                                            exchanges)));
    979 }
    980 
    981 
    982 /**
    983  * Do database transaction for a completed batch deposit.
    984  *
    985  * @param eg group that completed
    986  * @param dr response from the server
    987  * @return transaction status
    988  */
    989 static enum GNUNET_DB_QueryStatus
    990 batch_deposit_transaction (const struct ExchangeGroup *eg,
    991                            const struct TALER_EXCHANGE_BatchDepositResult *dr)
    992 {
    993   const struct PayContext *pc = eg->pc;
    994   enum GNUNET_DB_QueryStatus qs;
    995   struct TALER_Amount total_without_fees;
    996   uint64_t b_dep_serial;
    997   uint32_t off = 0;
    998 
    999   GNUNET_assert (GNUNET_OK ==
   1000                  TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   1001                                         &total_without_fees));
   1002   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1003   {
   1004     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1005     struct TALER_Amount amount_without_fees;
   1006 
   1007     /* might want to group deposits by batch more explicitly ... */
   1008     if (0 != strcmp (eg->exchange_url,
   1009                      dc->exchange_url))
   1010       continue;
   1011     if (dc->found_in_db)
   1012       continue;
   1013     GNUNET_assert (0 <=
   1014                    TALER_amount_subtract (&amount_without_fees,
   1015                                           &dc->cdd.amount,
   1016                                           &dc->deposit_fee));
   1017     GNUNET_assert (0 <=
   1018                    TALER_amount_add (&total_without_fees,
   1019                                      &total_without_fees,
   1020                                      &amount_without_fees));
   1021   }
   1022   qs = TMH_db->insert_deposit_confirmation (
   1023     TMH_db->cls,
   1024     pc->hc->instance->settings.id,
   1025     dr->details.ok.deposit_timestamp,
   1026     &pc->check_contract.h_contract_terms,
   1027     eg->exchange_url,
   1028     pc->check_contract.contract_terms->wire_deadline,
   1029     &total_without_fees,
   1030     &eg->wire_fee,
   1031     &pc->check_contract.wm->h_wire,
   1032     dr->details.ok.exchange_sig,
   1033     dr->details.ok.exchange_pub,
   1034     &b_dep_serial);
   1035   if (qs <= 0)
   1036     return qs; /* Entire batch already known or failure, we're done */
   1037 
   1038   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1039   {
   1040     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1041 
   1042     /* might want to group deposits by batch more explicitly ... */
   1043     if (0 != strcmp (eg->exchange_url,
   1044                      dc->exchange_url))
   1045       continue;
   1046     if (dc->found_in_db)
   1047       continue;
   1048     /* FIXME-#9457: We might want to check if the order was fully paid concurrently
   1049        by some other wallet here, and if so, issue an auto-refund. Right now,
   1050        it is possible to over-pay if two wallets literally make a concurrent
   1051        payment, as the earlier check for 'paid' is not in the same transaction
   1052        scope as this 'insert' operation. */
   1053     qs = TMH_db->insert_deposit (
   1054       TMH_db->cls,
   1055       off++, /* might want to group deposits by batch more explicitly ... */
   1056       b_dep_serial,
   1057       &dc->cdd.coin_pub,
   1058       &dc->cdd.coin_sig,
   1059       &dc->cdd.amount,
   1060       &dc->deposit_fee,
   1061       &dc->refund_fee,
   1062       GNUNET_TIME_absolute_add (
   1063         pc->check_contract.contract_terms->wire_deadline.abs_time,
   1064         GNUNET_TIME_randomize (GNUNET_TIME_UNIT_MINUTES)));
   1065     if (qs < 0)
   1066       return qs;
   1067     GNUNET_break (qs > 0);
   1068   }
   1069   return qs;
   1070 }
   1071 
   1072 
   1073 /**
   1074  * Handle case where the batch deposit completed
   1075  * with a status of #MHD_HTTP_OK.
   1076  *
   1077  * @param eg group that completed
   1078  * @param dr response from the server
   1079  */
   1080 static void
   1081 handle_batch_deposit_ok (struct ExchangeGroup *eg,
   1082                          const struct TALER_EXCHANGE_BatchDepositResult *dr)
   1083 {
   1084   struct PayContext *pc = eg->pc;
   1085   enum GNUNET_DB_QueryStatus qs
   1086     = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
   1087 
   1088   /* store result to DB */
   1089   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1090               "Storing successful payment %s (%s) at instance `%s'\n",
   1091               pc->hc->infix,
   1092               GNUNET_h2s (&pc->check_contract.h_contract_terms.hash),
   1093               pc->hc->instance->settings.id);
   1094   for (unsigned int r = 0; r<MAX_RETRIES; r++)
   1095   {
   1096     TMH_db->preflight (TMH_db->cls);
   1097     if (GNUNET_OK !=
   1098         TMH_db->start (TMH_db->cls,
   1099                        "batch-deposit-insert-confirmation"))
   1100     {
   1101       resume_pay_with_response (
   1102         pc,
   1103         MHD_HTTP_INTERNAL_SERVER_ERROR,
   1104         TALER_MHD_MAKE_JSON_PACK (
   1105           TALER_JSON_pack_ec (
   1106             TALER_EC_GENERIC_DB_START_FAILED),
   1107           TMH_pack_exchange_reply (&dr->hr)));
   1108       return;
   1109     }
   1110     qs = batch_deposit_transaction (eg,
   1111                                     dr);
   1112     if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   1113     {
   1114       TMH_db->rollback (TMH_db->cls);
   1115       continue;
   1116     }
   1117     if (GNUNET_DB_STATUS_HARD_ERROR == qs)
   1118     {
   1119       GNUNET_break (0);
   1120       resume_pay_with_error (pc,
   1121                              TALER_EC_GENERIC_DB_COMMIT_FAILED,
   1122                              "batch_deposit_transaction");
   1123     }
   1124     qs = TMH_db->commit (TMH_db->cls);
   1125     if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   1126     {
   1127       TMH_db->rollback (TMH_db->cls);
   1128       continue;
   1129     }
   1130     if (GNUNET_DB_STATUS_HARD_ERROR == qs)
   1131     {
   1132       GNUNET_break (0);
   1133       resume_pay_with_error (pc,
   1134                              TALER_EC_GENERIC_DB_COMMIT_FAILED,
   1135                              "insert_deposit");
   1136     }
   1137     break; /* DB transaction succeeded */
   1138   }
   1139   if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   1140   {
   1141     resume_pay_with_error (pc,
   1142                            TALER_EC_GENERIC_DB_SOFT_FAILURE,
   1143                            "insert_deposit");
   1144     return;
   1145   }
   1146 
   1147   /* Transaction is done, mark affected coins as complete as well. */
   1148   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1149   {
   1150     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1151 
   1152     if (0 != strcmp (eg->exchange_url,
   1153                      pc->parse_pay.dc[i].exchange_url))
   1154       continue;
   1155     if (dc->found_in_db)
   1156       continue;
   1157     dc->found_in_db = true;     /* well, at least NOW it'd be true ;-) */
   1158     pc->pay_transaction.pending--;
   1159   }
   1160 }
   1161 
   1162 
   1163 /**
   1164  * Notify taler-merchant-kyccheck that we got a KYC
   1165  * rule violation notification and should start to
   1166  * check our KYC status.
   1167  *
   1168  * @param eg exchange group we were notified for
   1169  */
   1170 static void
   1171 notify_kyc_required (const struct ExchangeGroup *eg)
   1172 {
   1173   struct GNUNET_DB_EventHeaderP es = {
   1174     .size = htons (sizeof (es)),
   1175     .type = htons (TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_RULE_TRIGGERED)
   1176   };
   1177   char *hws;
   1178   char *extra;
   1179 
   1180   hws = GNUNET_STRINGS_data_to_string_alloc (
   1181     &eg->pc->check_contract.contract_terms->h_wire,
   1182     sizeof (eg->pc->check_contract.contract_terms->h_wire));
   1183   GNUNET_asprintf (&extra,
   1184                    "%s %s",
   1185                    hws,
   1186                    eg->exchange_url);
   1187   GNUNET_free (hws);
   1188   TMH_db->event_notify (TMH_db->cls,
   1189                         &es,
   1190                         extra,
   1191                         strlen (extra) + 1);
   1192   GNUNET_free (extra);
   1193 }
   1194 
   1195 
   1196 /**
   1197  * Callback to handle a batch deposit permission's response.
   1198  *
   1199  * @param cls a `struct ExchangeGroup`
   1200  * @param dr HTTP response code details
   1201  */
   1202 static void
   1203 batch_deposit_cb (
   1204   void *cls,
   1205   const struct TALER_EXCHANGE_BatchDepositResult *dr)
   1206 {
   1207   struct ExchangeGroup *eg = cls;
   1208   struct PayContext *pc = eg->pc;
   1209 
   1210   eg->bdh = NULL;
   1211   pc->batch_deposits.pending_at_eg--;
   1212   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1213               "Batch deposit completed with status %u\n",
   1214               dr->hr.http_status);
   1215   GNUNET_assert (GNUNET_YES == pc->suspended);
   1216   switch (dr->hr.http_status)
   1217   {
   1218   case MHD_HTTP_OK:
   1219     handle_batch_deposit_ok (eg,
   1220                              dr);
   1221     if (0 == pc->batch_deposits.pending_at_eg)
   1222     {
   1223       pc->phase = PP_PAY_TRANSACTION;
   1224       pay_resume (pc);
   1225     }
   1226     return;
   1227   case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
   1228     notify_kyc_required (eg);
   1229     eg->got_451 = true;
   1230     pc->batch_deposits.got_451 = true;
   1231     /* update pc->pay_transaction.pending */
   1232     for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1233     {
   1234       struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1235 
   1236       if (0 != strcmp (eg->exchange_url,
   1237                        pc->parse_pay.dc[i].exchange_url))
   1238         continue;
   1239       if (dc->found_in_db)
   1240         continue;
   1241       pc->pay_transaction.pending--;
   1242     }
   1243     if (0 == pc->batch_deposits.pending_at_eg)
   1244     {
   1245       pc->phase = PP_PAY_TRANSACTION;
   1246       pay_resume (pc);
   1247     }
   1248     return;
   1249   default:
   1250     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1251                 "Deposit operation failed with HTTP code %u/%d\n",
   1252                 dr->hr.http_status,
   1253                 (int) dr->hr.ec);
   1254     /* Transaction failed */
   1255     if (5 == dr->hr.http_status / 100)
   1256     {
   1257       /* internal server error at exchange */
   1258       resume_pay_with_response (pc,
   1259                                 MHD_HTTP_BAD_GATEWAY,
   1260                                 TALER_MHD_MAKE_JSON_PACK (
   1261                                   TALER_JSON_pack_ec (
   1262                                     TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS),
   1263                                   TMH_pack_exchange_reply (&dr->hr)));
   1264       return;
   1265     }
   1266     if (NULL == dr->hr.reply)
   1267     {
   1268       /* We can't do anything meaningful here, the exchange did something wrong */
   1269       resume_pay_with_response (
   1270         pc,
   1271         MHD_HTTP_BAD_GATEWAY,
   1272         TALER_MHD_MAKE_JSON_PACK (
   1273           TALER_JSON_pack_ec (
   1274             TALER_EC_MERCHANT_GENERIC_EXCHANGE_REPLY_MALFORMED),
   1275           TMH_pack_exchange_reply (&dr->hr)));
   1276       return;
   1277     }
   1278 
   1279     /* Forward error, adding the "exchange_url" for which the
   1280        error was being generated */
   1281     if (TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS == dr->hr.ec)
   1282     {
   1283       resume_pay_with_response (
   1284         pc,
   1285         MHD_HTTP_CONFLICT,
   1286         TALER_MHD_MAKE_JSON_PACK (
   1287           TALER_JSON_pack_ec (
   1288             TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS),
   1289           TMH_pack_exchange_reply (&dr->hr),
   1290           GNUNET_JSON_pack_string ("exchange_url",
   1291                                    eg->exchange_url)));
   1292       return;
   1293     }
   1294     resume_pay_with_response (
   1295       pc,
   1296       MHD_HTTP_BAD_GATEWAY,
   1297       TALER_MHD_MAKE_JSON_PACK (
   1298         TALER_JSON_pack_ec (
   1299           TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS),
   1300         TMH_pack_exchange_reply (&dr->hr),
   1301         GNUNET_JSON_pack_string ("exchange_url",
   1302                                  eg->exchange_url)));
   1303     return;
   1304   } /* end switch */
   1305 }
   1306 
   1307 
   1308 /**
   1309  * Force re-downloading keys for @a eg.
   1310  *
   1311  * @param[in,out] eg group to re-download keys for
   1312  */
   1313 static void
   1314 force_keys (struct ExchangeGroup *eg);
   1315 
   1316 
   1317 /**
   1318  * Function called with the result of our exchange keys lookup.
   1319  *
   1320  * @param cls the `struct ExchangeGroup`
   1321  * @param keys the keys of the exchange
   1322  * @param exchange representation of the exchange
   1323  */
   1324 static void
   1325 process_pay_with_keys (
   1326   void *cls,
   1327   struct TALER_EXCHANGE_Keys *keys,
   1328   struct TMH_Exchange *exchange)
   1329 {
   1330   struct ExchangeGroup *eg = cls;
   1331   struct PayContext *pc = eg->pc;
   1332   struct TMH_HandlerContext *hc = pc->hc;
   1333   unsigned int group_size;
   1334   struct TALER_Amount max_amount;
   1335   enum TMH_ExchangeStatus es;
   1336 
   1337   eg->fo = NULL;
   1338   pc->batch_deposits.pending_at_eg--;
   1339   GNUNET_SCHEDULER_begin_async_scope (&hc->async_scope_id);
   1340   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1341               "Processing payment with keys from exchange %s\n",
   1342               eg->exchange_url);
   1343   GNUNET_assert (GNUNET_YES == pc->suspended);
   1344   if (NULL == keys)
   1345   {
   1346     GNUNET_break_op (0);
   1347     resume_pay_with_error (
   1348       pc,
   1349       TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT,
   1350       NULL);
   1351     return;
   1352   }
   1353   if (! TMH_EXCHANGES_is_below_limit (keys,
   1354                                       TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION,
   1355                                       &eg->total))
   1356   {
   1357     GNUNET_break_op (0);
   1358     resume_pay_with_error (
   1359       pc,
   1360       TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION,
   1361       eg->exchange_url);
   1362     return;
   1363   }
   1364 
   1365   max_amount = eg->total;
   1366   es = TMH_exchange_check_debit (
   1367     pc->hc->instance->settings.id,
   1368     exchange,
   1369     pc->check_contract.wm,
   1370     &max_amount);
   1371   if ( (TMH_ES_OK != es) &&
   1372        (TMH_ES_RETRY_OK != es) )
   1373   {
   1374     if (eg->tried_force_keys ||
   1375         (0 == (TMH_ES_RETRY_OK & es)) )
   1376     {
   1377       GNUNET_break_op (0);
   1378       resume_pay_with_error (
   1379         pc,
   1380         TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED,
   1381         NULL);
   1382       return;
   1383     }
   1384     force_keys (eg);
   1385     return;
   1386   }
   1387   if (-1 ==
   1388       TALER_amount_cmp (&max_amount,
   1389                         &eg->total))
   1390   {
   1391     /* max_amount < eg->total */
   1392     GNUNET_break_op (0);
   1393     resume_pay_with_error (
   1394       pc,
   1395       TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION,
   1396       eg->exchange_url);
   1397     return;
   1398   }
   1399 
   1400   if (GNUNET_OK !=
   1401       TMH_EXCHANGES_lookup_wire_fee (exchange,
   1402                                      pc->check_contract.wm->wire_method,
   1403                                      &eg->wire_fee))
   1404   {
   1405     if (eg->tried_force_keys)
   1406     {
   1407       GNUNET_break_op (0);
   1408       resume_pay_with_error (
   1409         pc,
   1410         TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED,
   1411         pc->check_contract.wm->wire_method);
   1412       return;
   1413     }
   1414     force_keys (eg);
   1415     return;
   1416   }
   1417   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1418               "Got wire data for %s\n",
   1419               eg->exchange_url);
   1420 
   1421   /* Initiate /batch-deposit operation for all coins of
   1422      the current exchange (!) */
   1423   group_size = 0;
   1424   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1425   {
   1426     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1427     const struct TALER_EXCHANGE_DenomPublicKey *denom_details;
   1428     bool is_age_restricted_denom = false;
   1429 
   1430     if (0 != strcmp (eg->exchange_url,
   1431                      pc->parse_pay.dc[i].exchange_url))
   1432       continue;
   1433     if (dc->found_in_db)
   1434       continue;
   1435 
   1436     denom_details
   1437       = TALER_EXCHANGE_get_denomination_key_by_hash (keys,
   1438                                                      &dc->cdd.h_denom_pub);
   1439     if (NULL == denom_details)
   1440     {
   1441       if (eg->tried_force_keys)
   1442       {
   1443         GNUNET_break_op (0);
   1444         resume_pay_with_response (
   1445           pc,
   1446           MHD_HTTP_BAD_REQUEST,
   1447           TALER_MHD_MAKE_JSON_PACK (
   1448             TALER_JSON_pack_ec (
   1449               TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND),
   1450             GNUNET_JSON_pack_data_auto ("h_denom_pub",
   1451                                         &dc->cdd.h_denom_pub),
   1452             GNUNET_JSON_pack_allow_null (
   1453               GNUNET_JSON_pack_object_steal (
   1454                 "exchange_keys",
   1455                 TALER_EXCHANGE_keys_to_json (keys)))));
   1456         return;
   1457       }
   1458       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1459                   "Missing denomination %s from exchange %s, updating keys\n",
   1460                   GNUNET_h2s (&dc->cdd.h_denom_pub.hash),
   1461                   eg->exchange_url);
   1462       force_keys (eg);
   1463       return;
   1464     }
   1465     dc->deposit_fee = denom_details->fees.deposit;
   1466     dc->refund_fee = denom_details->fees.refund;
   1467 
   1468     if (GNUNET_TIME_absolute_is_past (
   1469           denom_details->expire_deposit.abs_time))
   1470     {
   1471       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1472                   "Denomination key offered by client has expired for deposits\n");
   1473       resume_pay_with_response (
   1474         pc,
   1475         MHD_HTTP_GONE,
   1476         TALER_MHD_MAKE_JSON_PACK (
   1477           TALER_JSON_pack_ec (
   1478             TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED),
   1479           GNUNET_JSON_pack_data_auto ("h_denom_pub",
   1480                                       &denom_details->h_key)));
   1481       return;
   1482     }
   1483 
   1484     /* Now that we have the details about the denomination, we can verify age
   1485      * restriction requirements, if applicable. Note that denominations with an
   1486      * age_mask equal to zero always pass the age verification.  */
   1487     is_age_restricted_denom = (0 != denom_details->key.age_mask.bits);
   1488 
   1489     if (is_age_restricted_denom &&
   1490         (0 < pc->check_contract.contract_terms->minimum_age))
   1491     {
   1492       /* Minimum age given and restricted coin provided: We need to verify the
   1493        * minimum age */
   1494       unsigned int code = 0;
   1495 
   1496       if (dc->no_age_commitment)
   1497       {
   1498         GNUNET_break_op (0);
   1499         code = TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_MISSING;
   1500         goto AGE_FAIL;
   1501       }
   1502       dc->age_commitment.mask = denom_details->key.age_mask;
   1503       if (((int) (dc->age_commitment.num + 1)) !=
   1504           __builtin_popcount (dc->age_commitment.mask.bits))
   1505       {
   1506         GNUNET_break_op (0);
   1507         code =
   1508           TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_SIZE_MISMATCH;
   1509         goto AGE_FAIL;
   1510       }
   1511       if (GNUNET_OK !=
   1512           TALER_age_commitment_verify (
   1513             &dc->age_commitment,
   1514             pc->check_contract.contract_terms->minimum_age,
   1515             &dc->minimum_age_sig))
   1516         code = TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_VERIFICATION_FAILED;
   1517 AGE_FAIL:
   1518       if (0 < code)
   1519       {
   1520         GNUNET_break_op (0);
   1521         TALER_age_commitment_free (&dc->age_commitment);
   1522         resume_pay_with_response (
   1523           pc,
   1524           MHD_HTTP_BAD_REQUEST,
   1525           TALER_MHD_MAKE_JSON_PACK (
   1526             TALER_JSON_pack_ec (code),
   1527             GNUNET_JSON_pack_data_auto ("h_denom_pub",
   1528                                         &denom_details->h_key)));
   1529         return;
   1530       }
   1531 
   1532       /* Age restriction successfully verified!
   1533        * Calculate the hash of the age commitment. */
   1534       TALER_age_commitment_hash (&dc->age_commitment,
   1535                                  &dc->cdd.h_age_commitment);
   1536       TALER_age_commitment_free (&dc->age_commitment);
   1537     }
   1538     else if (is_age_restricted_denom &&
   1539              dc->no_h_age_commitment)
   1540     {
   1541       /* The contract did not ask for a minimum_age but the client paid
   1542        * with a coin that has age restriction enabled.  We lack the hash
   1543        * of the age commitment in this case in order to verify the coin
   1544        * and to deposit it with the exchange. */
   1545       GNUNET_break_op (0);
   1546       resume_pay_with_response (
   1547         pc,
   1548         MHD_HTTP_BAD_REQUEST,
   1549         TALER_MHD_MAKE_JSON_PACK (
   1550           TALER_JSON_pack_ec (
   1551             TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_HASH_MISSING),
   1552           GNUNET_JSON_pack_data_auto ("h_denom_pub",
   1553                                       &denom_details->h_key)));
   1554       return;
   1555     }
   1556     group_size++;
   1557   }
   1558 
   1559   if (0 == group_size)
   1560   {
   1561     GNUNET_break (0);
   1562     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1563                 "Group size zero, %u batch transactions remain pending\n",
   1564                 pc->batch_deposits.pending_at_eg);
   1565     if (0 == pc->batch_deposits.pending_at_eg)
   1566     {
   1567       pc->phase = PP_PAY_TRANSACTION;
   1568       pay_resume (pc);
   1569       return;
   1570     }
   1571     return;
   1572   }
   1573   if (group_size > TALER_MAX_COINS)
   1574     group_size = TALER_MAX_COINS;
   1575   {
   1576     struct TALER_EXCHANGE_CoinDepositDetail cdds[group_size];
   1577     struct TALER_EXCHANGE_DepositContractDetail dcd = {
   1578       .wire_deadline = pc->check_contract.contract_terms->wire_deadline,
   1579       .merchant_payto_uri = pc->check_contract.wm->payto_uri,
   1580       .wire_salt = pc->check_contract.wm->wire_salt,
   1581       .h_contract_terms = pc->check_contract.h_contract_terms,
   1582       .wallet_data_hash = pc->parse_wallet_data.h_wallet_data,
   1583       .wallet_timestamp = pc->check_contract.contract_terms->timestamp,
   1584       .merchant_pub = hc->instance->merchant_pub,
   1585       .refund_deadline = pc->check_contract.contract_terms->refund_deadline
   1586     };
   1587     enum TALER_ErrorCode ec;
   1588     size_t off = 0;
   1589 
   1590     TALER_merchant_contract_sign (&pc->check_contract.h_contract_terms,
   1591                                   &pc->hc->instance->merchant_priv,
   1592                                   &dcd.merchant_sig);
   1593     for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1594     {
   1595       struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1596 
   1597       if (dc->found_in_db)
   1598         continue;
   1599       if (0 != strcmp (dc->exchange_url,
   1600                        eg->exchange_url))
   1601         continue;
   1602       cdds[off++] = dc->cdd;
   1603       if (off >= group_size)
   1604         break;
   1605     }
   1606     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1607                 "Initiating batch deposit with %u coins\n",
   1608                 group_size);
   1609     /* Note: the coin signatures over the wallet_data_hash are
   1610        checked inside of this call */
   1611     eg->bdh = TALER_EXCHANGE_batch_deposit (
   1612       TMH_curl_ctx,
   1613       eg->exchange_url,
   1614       keys,
   1615       &dcd,
   1616       group_size,
   1617       cdds,
   1618       &batch_deposit_cb,
   1619       eg,
   1620       &ec);
   1621     if (NULL == eg->bdh)
   1622     {
   1623       /* Signature was invalid or some other constraint was not satisfied.  If
   1624          the exchange was unavailable, we'd get that information in the
   1625          callback. */
   1626       GNUNET_break_op (0);
   1627       resume_pay_with_response (
   1628         pc,
   1629         TALER_ErrorCode_get_http_status_safe (ec),
   1630         TALER_MHD_MAKE_JSON_PACK (
   1631           TALER_JSON_pack_ec (ec),
   1632           GNUNET_JSON_pack_string ("exchange_url",
   1633                                    eg->exchange_url)));
   1634       return;
   1635     }
   1636     pc->batch_deposits.pending_at_eg++;
   1637     if (TMH_force_audit)
   1638       TALER_EXCHANGE_batch_deposit_force_dc (eg->bdh);
   1639   }
   1640 }
   1641 
   1642 
   1643 static void
   1644 force_keys (struct ExchangeGroup *eg)
   1645 {
   1646   struct PayContext *pc = eg->pc;
   1647 
   1648   eg->tried_force_keys = true;
   1649   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1650               "Forcing /keys download (once)\n");
   1651   eg->fo = TMH_EXCHANGES_keys4exchange (
   1652     eg->exchange_url,
   1653     true,
   1654     &process_pay_with_keys,
   1655     eg);
   1656   if (NULL == eg->fo)
   1657   {
   1658     GNUNET_break_op (0);
   1659     resume_pay_with_error (pc,
   1660                            TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNTRUSTED,
   1661                            eg->exchange_url);
   1662     return;
   1663   }
   1664   pc->batch_deposits.pending_at_eg++;
   1665 }
   1666 
   1667 
   1668 /**
   1669  * Handle a timeout for the processing of the pay request.
   1670  *
   1671  * @param cls our `struct PayContext`
   1672  */
   1673 static void
   1674 handle_pay_timeout (void *cls)
   1675 {
   1676   struct PayContext *pc = cls;
   1677 
   1678   pc->batch_deposits.timeout_task = NULL;
   1679   GNUNET_assert (GNUNET_YES == pc->suspended);
   1680   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1681               "Resuming pay with error after timeout\n");
   1682   resume_pay_with_error (pc,
   1683                          TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT,
   1684                          NULL);
   1685 }
   1686 
   1687 
   1688 /**
   1689  * Compute the timeout for a /pay request based on the number of coins
   1690  * involved.
   1691  *
   1692  * @param num_coins number of coins
   1693  * @returns timeout for the /pay request
   1694  */
   1695 static struct GNUNET_TIME_Relative
   1696 get_pay_timeout (unsigned int num_coins)
   1697 {
   1698   struct GNUNET_TIME_Relative t;
   1699 
   1700   /* FIXME-Performance-Optimization: Do some benchmarking to come up with a
   1701    * better timeout.  We've increased this value so the wallet integration
   1702    * test passes again on my (Florian) machine.
   1703    */
   1704   t = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
   1705                                      15 * (1 + (num_coins / 5)));
   1706 
   1707   return t;
   1708 }
   1709 
   1710 
   1711 /**
   1712  * Start batch deposits for all exchanges involved
   1713  * in this payment.
   1714  *
   1715  * @param[in,out] pc payment context we are processing
   1716  */
   1717 static void
   1718 phase_batch_deposits (struct PayContext *pc)
   1719 {
   1720   for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
   1721   {
   1722     struct ExchangeGroup *eg = pc->parse_pay.egs[i];
   1723     bool have_coins = false;
   1724 
   1725     for (size_t j = 0; j<pc->parse_pay.coins_cnt; j++)
   1726     {
   1727       struct DepositConfirmation *dc = &pc->parse_pay.dc[j];
   1728 
   1729       if (0 != strcmp (eg->exchange_url,
   1730                        dc->exchange_url))
   1731         continue;
   1732       if (dc->found_in_db)
   1733         continue;
   1734       have_coins = true;
   1735       break;
   1736     }
   1737     if (! have_coins)
   1738       continue; /* no coins left to deposit at this exchange */
   1739     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1740                 "Getting /keys for %s\n",
   1741                 eg->exchange_url);
   1742     eg->fo = TMH_EXCHANGES_keys4exchange (
   1743       eg->exchange_url,
   1744       false,
   1745       &process_pay_with_keys,
   1746       eg);
   1747     if (NULL == eg->fo)
   1748     {
   1749       GNUNET_break_op (0);
   1750       pay_end (pc,
   1751                TALER_MHD_reply_with_error (
   1752                  pc->connection,
   1753                  MHD_HTTP_BAD_REQUEST,
   1754                  TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNTRUSTED,
   1755                  eg->exchange_url));
   1756       return;
   1757     }
   1758     pc->batch_deposits.pending_at_eg++;
   1759   }
   1760   if (0 == pc->batch_deposits.pending_at_eg)
   1761   {
   1762     pc->phase = PP_PAY_TRANSACTION;
   1763     pay_resume (pc);
   1764     return;
   1765   }
   1766   /* Suspend while we interact with the exchange */
   1767   MHD_suspend_connection (pc->connection);
   1768   pc->suspended = GNUNET_YES;
   1769   GNUNET_assert (NULL == pc->batch_deposits.timeout_task);
   1770   pc->batch_deposits.timeout_task
   1771     = GNUNET_SCHEDULER_add_delayed (get_pay_timeout (pc->parse_pay.coins_cnt),
   1772                                     &handle_pay_timeout,
   1773                                     pc);
   1774 }
   1775 
   1776 
   1777 /**
   1778  * Build JSON array of blindly signed token envelopes,
   1779  * to be used in the response to the wallet.
   1780  *
   1781  * @param[in,out] pc payment context to use
   1782  */
   1783 static json_t *
   1784 build_token_sigs (struct PayContext *pc)
   1785 {
   1786   json_t *token_sigs;
   1787 
   1788   if (0 == pc->output_tokens_len)
   1789     return NULL;
   1790   token_sigs = json_array ();
   1791   GNUNET_assert (NULL != token_sigs);
   1792   for (unsigned int i = 0; i < pc->output_tokens_len; i++)
   1793   {
   1794     GNUNET_assert (0 ==
   1795                    json_array_append_new (
   1796                      token_sigs,
   1797                      GNUNET_JSON_PACK (
   1798                        GNUNET_JSON_pack_blinded_sig (
   1799                          "blind_sig",
   1800                          pc->output_tokens[i].sig.signature)
   1801                        )));
   1802   }
   1803   return token_sigs;
   1804 }
   1805 
   1806 
   1807 /**
   1808  * Generate response (payment successful)
   1809  *
   1810  * @param[in,out] pc payment context where the payment was successful
   1811  */
   1812 static void
   1813 phase_success_response (struct PayContext *pc)
   1814 {
   1815   struct TALER_MerchantSignatureP sig;
   1816   char *pos_confirmation;
   1817 
   1818   /* Sign on our end (as the payment did go through, even if it may
   1819      have been refunded already) */
   1820   TALER_merchant_pay_sign (&pc->check_contract.h_contract_terms,
   1821                            &pc->hc->instance->merchant_priv,
   1822                            &sig);
   1823   /* Build the response */
   1824   pos_confirmation = (NULL == pc->check_contract.pos_key)
   1825     ? NULL
   1826     : TALER_build_pos_confirmation (pc->check_contract.pos_key,
   1827                                     pc->check_contract.pos_alg,
   1828                                     &pc->validate_tokens.brutto,
   1829                                     pc->check_contract.contract_terms->timestamp
   1830                                     );
   1831   pay_end (pc,
   1832            TALER_MHD_REPLY_JSON_PACK (
   1833              pc->connection,
   1834              MHD_HTTP_OK,
   1835              GNUNET_JSON_pack_allow_null (
   1836                GNUNET_JSON_pack_string ("pos_confirmation",
   1837                                         pos_confirmation)),
   1838              GNUNET_JSON_pack_allow_null (
   1839                GNUNET_JSON_pack_array_steal ("token_sigs",
   1840                                              build_token_sigs (pc))),
   1841              GNUNET_JSON_pack_data_auto ("sig",
   1842                                          &sig)));
   1843   GNUNET_free (pos_confirmation);
   1844 }
   1845 
   1846 
   1847 /**
   1848  * Use database to notify other clients about the
   1849  * payment being completed.
   1850  *
   1851  * @param[in,out] pc context to trigger notification for
   1852  */
   1853 static void
   1854 phase_payment_notification (struct PayContext *pc)
   1855 {
   1856   {
   1857     struct TMH_OrderPayEventP pay_eh = {
   1858       .header.size = htons (sizeof (pay_eh)),
   1859       .header.type = htons (TALER_DBEVENT_MERCHANT_ORDER_PAID),
   1860       .merchant_pub = pc->hc->instance->merchant_pub
   1861     };
   1862 
   1863     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1864                 "Notifying clients about payment of order %s\n",
   1865                 pc->order_id);
   1866     GNUNET_CRYPTO_hash (pc->order_id,
   1867                         strlen (pc->order_id),
   1868                         &pay_eh.h_order_id);
   1869     TMH_db->event_notify (TMH_db->cls,
   1870                           &pay_eh.header,
   1871                           NULL,
   1872                           0);
   1873   }
   1874   if ( (NULL != pc->parse_pay.session_id) &&
   1875        (NULL != pc->check_contract.contract_terms->fulfillment_url) )
   1876   {
   1877     struct TMH_SessionEventP session_eh = {
   1878       .header.size = htons (sizeof (session_eh)),
   1879       .header.type = htons (TALER_DBEVENT_MERCHANT_SESSION_CAPTURED),
   1880       .merchant_pub = pc->hc->instance->merchant_pub
   1881     };
   1882 
   1883     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1884                 "Notifying clients about session change to %s for %s\n",
   1885                 pc->parse_pay.session_id,
   1886                 pc->check_contract.contract_terms->fulfillment_url);
   1887     GNUNET_CRYPTO_hash (pc->parse_pay.session_id,
   1888                         strlen (pc->parse_pay.session_id),
   1889                         &session_eh.h_session_id);
   1890     GNUNET_CRYPTO_hash (pc->check_contract.contract_terms->fulfillment_url,
   1891                         strlen (pc->check_contract.contract_terms->
   1892                                 fulfillment_url),
   1893                         &session_eh.h_fulfillment_url);
   1894     TMH_db->event_notify (TMH_db->cls,
   1895                           &session_eh.header,
   1896                           NULL,
   1897                           0);
   1898   }
   1899   pc->phase = PP_SUCCESS_RESPONSE;
   1900 }
   1901 
   1902 
   1903 /**
   1904  * Phase to write all outputs to our database so we do
   1905  * not re-request them in case the client re-plays the
   1906  * request.
   1907  *
   1908  * @param[in,out] pc payment context
   1909  */
   1910 static void
   1911 phase_final_output_token_processing (struct PayContext *pc)
   1912 {
   1913   if (0 == pc->output_tokens_len)
   1914   {
   1915     pc->phase++;
   1916     return;
   1917   }
   1918   for (unsigned int retry = 0; retry < MAX_RETRIES; retry++)
   1919   {
   1920     enum GNUNET_DB_QueryStatus qs;
   1921 
   1922     TMH_db->preflight (TMH_db->cls);
   1923     if (GNUNET_OK !=
   1924         TMH_db->start (TMH_db->cls,
   1925                        "insert_order_blinded_sigs"))
   1926     {
   1927       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1928                   "start insert_order_blinded_sigs_failed");
   1929       pc->phase++;
   1930       return;
   1931     }
   1932 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   1933     if (pc->parse_wallet_data.num_bkps > 0)
   1934     {
   1935       qs = TMH_db->update_donau_instance_receipts_amount (
   1936         TMH_db->cls,
   1937         &pc->parse_wallet_data.donau_instance_serial,
   1938         &pc->parse_wallet_data.charity_receipts_to_date);
   1939       switch (qs)
   1940       {
   1941       case GNUNET_DB_STATUS_HARD_ERROR:
   1942         TMH_db->rollback (TMH_db->cls);
   1943         GNUNET_break (0);
   1944         return;
   1945       case GNUNET_DB_STATUS_SOFT_ERROR:
   1946         TMH_db->rollback (TMH_db->cls);
   1947         continue;
   1948       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   1949         /* weird for an update */
   1950         GNUNET_break (0);
   1951         break;
   1952       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   1953         break;
   1954       }
   1955     }
   1956 #endif
   1957     for (unsigned int i = 0;
   1958          i < pc->output_tokens_len;
   1959          i++)
   1960     {
   1961       qs = TMH_db->insert_order_blinded_sigs (
   1962         TMH_db->cls,
   1963         pc->order_id,
   1964         i,
   1965         &pc->output_tokens[i].h_issue.hash,
   1966         pc->output_tokens[i].sig.signature);
   1967 
   1968       switch (qs)
   1969       {
   1970       case GNUNET_DB_STATUS_HARD_ERROR:
   1971         TMH_db->rollback (TMH_db->cls);
   1972         pc->phase++;
   1973         return;
   1974       case GNUNET_DB_STATUS_SOFT_ERROR:
   1975         TMH_db->rollback (TMH_db->cls);
   1976         goto OUTER;
   1977       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   1978         /* weird for an update */
   1979         GNUNET_break (0);
   1980         break;
   1981       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   1982         break;
   1983       }
   1984     } /* for i */
   1985     qs = TMH_db->commit (TMH_db->cls);
   1986     switch (qs)
   1987     {
   1988     case GNUNET_DB_STATUS_HARD_ERROR:
   1989       TMH_db->rollback (TMH_db->cls);
   1990       pc->phase++;
   1991       return;
   1992     case GNUNET_DB_STATUS_SOFT_ERROR:
   1993       TMH_db->rollback (TMH_db->cls);
   1994       continue;
   1995     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   1996       pc->phase++;
   1997       return; /* success */
   1998     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   1999       pc->phase++;
   2000       return; /* success */
   2001     }
   2002     GNUNET_break (0);
   2003     pc->phase++;
   2004     return; /* strange */
   2005 OUTER:
   2006   } /* for retry */
   2007   TMH_db->rollback (TMH_db->cls);
   2008   pc->phase++;
   2009   /* We continue anyway, as there is not much we can
   2010      do here: the Donau *did* issue us the receipts;
   2011      also, we'll eventually ask the Donau for the
   2012      balance and get the correct one. Plus, we were
   2013      paid by the client, so it's technically all still
   2014      OK. If the request fails anyway, the wallet will
   2015      most likely replay the request and then hopefully
   2016      we will succeed the next time */
   2017 }
   2018 
   2019 
   2020 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   2021 
   2022 /**
   2023  * Add donation receipt outputs to the output_tokens.
   2024  *
   2025  * Note that under the current (odd, bad) libdonau
   2026  * API *we* are responsible for freeing blinded_sigs,
   2027  * so we truly own that array!
   2028  *
   2029  * @param[in,out] pc payment context
   2030  * @param num_blinded_sigs number of signatures received
   2031  * @param blinded_sigs blinded signatures from Donau
   2032  * @return #GNUNET_OK on success,
   2033  *         #GNUNET_SYSERR on failure (state machine was
   2034  *          in that case already advanced)
   2035  */
   2036 static enum GNUNET_GenericReturnValue
   2037 add_donation_receipt_outputs (
   2038   struct PayContext *pc,
   2039   size_t num_blinded_sigs,
   2040   struct DONAU_BlindedDonationUnitSignature *blinded_sigs)
   2041 {
   2042   int donau_output_index = pc->validate_tokens.donau_output_index;
   2043 
   2044   GNUNET_assert (pc->parse_wallet_data.num_bkps ==
   2045                  num_blinded_sigs);
   2046 
   2047   GNUNET_assert (donau_output_index >= 0);
   2048 
   2049   for (unsigned int i = 0; i<pc->output_tokens_len; i++)
   2050   {
   2051     struct SignedOutputToken *sot
   2052       = &pc->output_tokens[i];
   2053 
   2054     /* Only look at actual donau tokens. */
   2055     if (sot->output_index != donau_output_index)
   2056       continue;
   2057 
   2058     sot->sig.signature = GNUNET_CRYPTO_blind_sig_incref (blinded_sigs[i].
   2059                                                          blinded_sig);
   2060     sot->h_issue.hash = pc->parse_wallet_data.bkps[i].h_donation_unit_pub.hash;
   2061   }
   2062   return GNUNET_OK;
   2063 }
   2064 
   2065 
   2066 /**
   2067  * Callback to handle the result of a batch issue request.
   2068  *
   2069  * @param cls our `struct PayContext`
   2070  * @param resp the response from Donau
   2071  */
   2072 static void
   2073 merchant_donau_issue_receipt_cb (
   2074   void *cls,
   2075   const struct DONAU_BatchIssueResponse *resp)
   2076 {
   2077   struct PayContext *pc = cls;
   2078   /* Donau replies asynchronously, so we expect the PayContext
   2079    * to be suspended. */
   2080   GNUNET_assert (GNUNET_YES == pc->suspended);
   2081   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2082               "Donau responded with status=%u, ec=%u",
   2083               resp->hr.http_status,
   2084               resp->hr.ec);
   2085   switch (resp->hr.http_status)
   2086   {
   2087   case 0:
   2088     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2089                 "Donau batch issue request from merchant-httpd failed (http_status==0)");
   2090     resume_pay_with_error (pc,
   2091                            TALER_EC_MERCHANT_GENERIC_DONAU_INVALID_RESPONSE,
   2092                            resp->hr.hint);
   2093     return;
   2094   case MHD_HTTP_OK:
   2095   case MHD_HTTP_CREATED:
   2096     if (TALER_EC_NONE != resp->hr.ec)
   2097     {
   2098       /* Most probably, it is just some small flaw from
   2099        * donau so no point in failing, yet we have to display it */
   2100       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2101                   "Donau signalled error %u despite HTTP %u",
   2102                   resp->hr.ec,
   2103                   resp->hr.http_status);
   2104     }
   2105     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2106                 "Donau accepted donation receipts with total_issued=%s",
   2107                 TALER_amount2s (&resp->details.ok.issued_amount));
   2108     if (GNUNET_OK !=
   2109         add_donation_receipt_outputs (pc,
   2110                                       resp->details.ok.num_blinded_sigs,
   2111                                       resp->details.ok.blinded_sigs))
   2112       return; /* state machine was already advanced */
   2113     pc->phase = PP_FINAL_OUTPUT_TOKEN_PROCESSING;
   2114     pay_resume (pc);
   2115     return;
   2116 
   2117   case MHD_HTTP_BAD_REQUEST:
   2118   case MHD_HTTP_FORBIDDEN:
   2119   case MHD_HTTP_NOT_FOUND:
   2120   case MHD_HTTP_INTERNAL_SERVER_ERROR:
   2121   default: /* make sure that everything except 200/201 will end up here*/
   2122     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2123                 "Donau replied with HTTP %u (ec=%u)",
   2124                 resp->hr.http_status,
   2125                 resp->hr.ec);
   2126     resume_pay_with_error (pc,
   2127                            TALER_EC_MERCHANT_GENERIC_DONAU_INVALID_RESPONSE,
   2128                            resp->hr.hint);
   2129     return;
   2130   }
   2131 }
   2132 
   2133 
   2134 /**
   2135  * Parse a bkp encoded in JSON.
   2136  *
   2137  * @param[out] bkp where to return the result
   2138  * @param bkp_key_obj json to parse
   2139  * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if @a bkp_key_obj
   2140  * is malformed.
   2141  */
   2142 static enum GNUNET_GenericReturnValue
   2143 merchant_parse_json_bkp (struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkp,
   2144                          const json_t *bkp_key_obj)
   2145 {
   2146   struct GNUNET_JSON_Specification spec[] = {
   2147     GNUNET_JSON_spec_fixed_auto ("h_donation_unit_pub",
   2148                                  &bkp->h_donation_unit_pub),
   2149     DONAU_JSON_spec_blinded_donation_identifier ("blinded_udi",
   2150                                                  &bkp->blinded_udi),
   2151     GNUNET_JSON_spec_end ()
   2152   };
   2153 
   2154   if (GNUNET_OK !=
   2155       GNUNET_JSON_parse (bkp_key_obj,
   2156                          spec,
   2157                          NULL,
   2158                          NULL))
   2159   {
   2160     GNUNET_break_op (0);
   2161     return GNUNET_SYSERR;
   2162   }
   2163   return GNUNET_OK;
   2164 }
   2165 
   2166 
   2167 /**
   2168  * Generate a donation signature for the bkp and charity.
   2169  *
   2170  * @param[in,out] pc payment context containing the charity and bkps
   2171  */
   2172 static void
   2173 phase_request_donation_receipt (struct PayContext *pc)
   2174 {
   2175   if ( (NULL == pc->parse_wallet_data.donau.donau_url) ||
   2176        (0 == pc->parse_wallet_data.num_bkps) )
   2177   {
   2178     pc->phase++;
   2179     return;
   2180   }
   2181   pc->donau_receipt.birh =
   2182     DONAU_charity_issue_receipt (
   2183       TMH_curl_ctx,
   2184       pc->parse_wallet_data.donau.donau_url,
   2185       &pc->parse_wallet_data.charity_priv,
   2186       pc->parse_wallet_data.charity_id,
   2187       pc->parse_wallet_data.donau.donation_year,
   2188       pc->parse_wallet_data.num_bkps,
   2189       pc->parse_wallet_data.bkps,
   2190       &merchant_donau_issue_receipt_cb,
   2191       pc);
   2192   if (NULL == pc->donau_receipt.birh)
   2193   {
   2194     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2195                 "Failed to create Donau receipt request");
   2196     pay_end (pc,
   2197              TALER_MHD_reply_with_error (pc->connection,
   2198                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
   2199                                          TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR,
   2200                                          "Donau request creation error"));
   2201     return;
   2202   }
   2203   MHD_suspend_connection (pc->connection);
   2204   pc->suspended = GNUNET_YES;
   2205 }
   2206 
   2207 
   2208 #endif
   2209 
   2210 
   2211 /**
   2212  * Function called with information about a coin that was deposited.
   2213  *
   2214  * @param cls closure
   2215  * @param exchange_url exchange where @a coin_pub was deposited
   2216  * @param coin_pub public key of the coin
   2217  * @param amount_with_fee amount the exchange will deposit for this coin
   2218  * @param deposit_fee fee the exchange will charge for this coin
   2219  * @param refund_fee fee the exchange will charge for refunding this coin
   2220  */
   2221 static void
   2222 check_coin_paid (void *cls,
   2223                  const char *exchange_url,
   2224                  const struct TALER_CoinSpendPublicKeyP *coin_pub,
   2225                  const struct TALER_Amount *amount_with_fee,
   2226                  const struct TALER_Amount *deposit_fee,
   2227                  const struct TALER_Amount *refund_fee)
   2228 {
   2229   struct PayContext *pc = cls;
   2230 
   2231   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2232   {
   2233     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   2234 
   2235     if (dc->found_in_db)
   2236       continue; /* processed earlier, skip "expensive" memcmp() */
   2237     /* Get matching coin from results*/
   2238     if ( (0 != GNUNET_memcmp (coin_pub,
   2239                               &dc->cdd.coin_pub)) ||
   2240          (0 !=
   2241           strcmp (exchange_url,
   2242                   dc->exchange_url)) ||
   2243          (GNUNET_OK !=
   2244           TALER_amount_cmp_currency (amount_with_fee,
   2245                                      &dc->cdd.amount)) ||
   2246          (0 != TALER_amount_cmp (amount_with_fee,
   2247                                  &dc->cdd.amount)) )
   2248       continue; /* does not match, skip */
   2249     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2250                 "Deposit of coin `%s' already in our DB.\n",
   2251                 TALER_B2S (coin_pub));
   2252     if ( (GNUNET_OK !=
   2253           TALER_amount_cmp_currency (&pc->pay_transaction.total_paid,
   2254                                      amount_with_fee)) ||
   2255          (GNUNET_OK !=
   2256           TALER_amount_cmp_currency (&pc->pay_transaction.total_fees_paid,
   2257                                      deposit_fee)) )
   2258     {
   2259       GNUNET_break_op (0);
   2260       pc->pay_transaction.deposit_currency_mismatch = true;
   2261       break;
   2262     }
   2263     GNUNET_assert (0 <=
   2264                    TALER_amount_add (&pc->pay_transaction.total_paid,
   2265                                      &pc->pay_transaction.total_paid,
   2266                                      amount_with_fee));
   2267     GNUNET_assert (0 <=
   2268                    TALER_amount_add (&pc->pay_transaction.total_fees_paid,
   2269                                      &pc->pay_transaction.total_fees_paid,
   2270                                      deposit_fee));
   2271     dc->deposit_fee = *deposit_fee;
   2272     dc->refund_fee = *refund_fee;
   2273     dc->cdd.amount = *amount_with_fee;
   2274     dc->found_in_db = true;
   2275     pc->pay_transaction.pending--;
   2276   }
   2277 }
   2278 
   2279 
   2280 /**
   2281  * Function called with information about a refund.  Check if this coin was
   2282  * claimed by the wallet for the transaction, and if so add the refunded
   2283  * amount to the pc's "total_refunded" amount.
   2284  *
   2285  * @param cls closure with a `struct PayContext`
   2286  * @param coin_pub public coin from which the refund comes from
   2287  * @param refund_amount refund amount which is being taken from @a coin_pub
   2288  */
   2289 static void
   2290 check_coin_refunded (void *cls,
   2291                      const struct TALER_CoinSpendPublicKeyP *coin_pub,
   2292                      const struct TALER_Amount *refund_amount)
   2293 {
   2294   struct PayContext *pc = cls;
   2295 
   2296   /* We look at refunds here that apply to the coins
   2297      that the customer is currently trying to pay us with.
   2298 
   2299      Such refunds are not "normal" refunds, but abort-pay refunds, which are
   2300      given in the case that the wallet aborts the payment.
   2301      In the case the wallet then decides to complete the payment *after* doing
   2302      an abort-pay refund (an unusual but possible case), we need
   2303      to make sure that existing refunds are accounted for. */
   2304 
   2305   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2306   {
   2307     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   2308 
   2309     /* Get matching coins from results.  */
   2310     if (0 != GNUNET_memcmp (coin_pub,
   2311                             &dc->cdd.coin_pub))
   2312       continue;
   2313     if (GNUNET_OK !=
   2314         TALER_amount_cmp_currency (&pc->pay_transaction.total_refunded,
   2315                                    refund_amount))
   2316     {
   2317       GNUNET_break (0);
   2318       pc->pay_transaction.refund_currency_mismatch = true;
   2319       break;
   2320     }
   2321     GNUNET_assert (0 <=
   2322                    TALER_amount_add (&pc->pay_transaction.total_refunded,
   2323                                      &pc->pay_transaction.total_refunded,
   2324                                      refund_amount));
   2325     break;
   2326   }
   2327 }
   2328 
   2329 
   2330 /**
   2331  * Check whether the amount paid is sufficient to cover the price.
   2332  *
   2333  * @param pc payment context to check
   2334  * @return true if the payment is sufficient, false if it is
   2335  *         insufficient
   2336  */
   2337 static bool
   2338 check_payment_sufficient (struct PayContext *pc)
   2339 {
   2340   struct TALER_Amount acc_fee;
   2341   struct TALER_Amount acc_amount;
   2342   struct TALER_Amount final_amount;
   2343   struct TALER_Amount total_wire_fee;
   2344   struct TALER_Amount total_needed;
   2345 
   2346   if (0 == pc->parse_pay.coins_cnt)
   2347     return TALER_amount_is_zero (&pc->validate_tokens.brutto);
   2348   GNUNET_assert (GNUNET_OK ==
   2349                  TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2350                                         &total_wire_fee));
   2351   for (unsigned int i = 0; i < pc->parse_pay.num_exchanges; i++)
   2352   {
   2353     if (GNUNET_OK !=
   2354         TALER_amount_cmp_currency (&total_wire_fee,
   2355                                    &pc->parse_pay.egs[i]->wire_fee))
   2356     {
   2357       GNUNET_break_op (0);
   2358       pay_end (pc,
   2359                TALER_MHD_reply_with_error (pc->connection,
   2360                                            MHD_HTTP_BAD_REQUEST,
   2361                                            TALER_EC_GENERIC_CURRENCY_MISMATCH,
   2362                                            total_wire_fee.currency));
   2363       return false;
   2364     }
   2365     if (0 >
   2366         TALER_amount_add (&total_wire_fee,
   2367                           &total_wire_fee,
   2368                           &pc->parse_pay.egs[i]->wire_fee))
   2369     {
   2370       GNUNET_break (0);
   2371       pay_end (pc,
   2372                TALER_MHD_reply_with_error (
   2373                  pc->connection,
   2374                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   2375                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED,
   2376                  "could not add exchange wire fee to total"));
   2377       return false;
   2378     }
   2379   }
   2380 
   2381   /**
   2382    * This loops calculates what are the deposit fee / total
   2383    * amount with fee / and wire fee, for all the coins.
   2384    */
   2385   GNUNET_assert (GNUNET_OK ==
   2386                  TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2387                                         &acc_fee));
   2388   GNUNET_assert (GNUNET_OK ==
   2389                  TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2390                                         &acc_amount));
   2391   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2392   {
   2393     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   2394 
   2395     GNUNET_assert (dc->found_in_db);
   2396     if ( (GNUNET_OK !=
   2397           TALER_amount_cmp_currency (&acc_fee,
   2398                                      &dc->deposit_fee)) ||
   2399          (GNUNET_OK !=
   2400           TALER_amount_cmp_currency (&acc_amount,
   2401                                      &dc->cdd.amount)) )
   2402     {
   2403       GNUNET_break_op (0);
   2404       pay_end (pc,
   2405                TALER_MHD_reply_with_error (
   2406                  pc->connection,
   2407                  MHD_HTTP_BAD_REQUEST,
   2408                  TALER_EC_GENERIC_CURRENCY_MISMATCH,
   2409                  dc->deposit_fee.currency));
   2410       return false;
   2411     }
   2412     if ( (0 >
   2413           TALER_amount_add (&acc_fee,
   2414                             &dc->deposit_fee,
   2415                             &acc_fee)) ||
   2416          (0 >
   2417           TALER_amount_add (&acc_amount,
   2418                             &dc->cdd.amount,
   2419                             &acc_amount)) )
   2420     {
   2421       GNUNET_break (0);
   2422       /* Overflow in these amounts? Very strange. */
   2423       pay_end (pc,
   2424                TALER_MHD_reply_with_error (
   2425                  pc->connection,
   2426                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   2427                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   2428                  "Overflow adding up amounts"));
   2429       return false;
   2430     }
   2431     if (1 ==
   2432         TALER_amount_cmp (&dc->deposit_fee,
   2433                           &dc->cdd.amount))
   2434     {
   2435       GNUNET_break_op (0);
   2436       pay_end (pc,
   2437                TALER_MHD_reply_with_error (
   2438                  pc->connection,
   2439                  MHD_HTTP_BAD_REQUEST,
   2440                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_FEES_EXCEED_PAYMENT,
   2441                  "Deposit fees exceed coin's contribution"));
   2442       return false;
   2443     }
   2444   } /* end deposit loop */
   2445 
   2446   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2447               "Amount received from wallet: %s\n",
   2448               TALER_amount2s (&acc_amount));
   2449   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2450               "Deposit fee for all coins: %s\n",
   2451               TALER_amount2s (&acc_fee));
   2452   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2453               "Total wire fee: %s\n",
   2454               TALER_amount2s (&total_wire_fee));
   2455   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2456               "Deposit fee limit for merchant: %s\n",
   2457               TALER_amount2s (&pc->validate_tokens.max_fee));
   2458   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2459               "Total refunded amount: %s\n",
   2460               TALER_amount2s (&pc->pay_transaction.total_refunded));
   2461 
   2462   /* Now compare exchange wire fee compared to what we are willing to pay */
   2463   if (GNUNET_YES !=
   2464       TALER_amount_cmp_currency (&total_wire_fee,
   2465                                  &acc_fee))
   2466   {
   2467     GNUNET_break (0);
   2468     pay_end (pc,
   2469              TALER_MHD_reply_with_error (
   2470                pc->connection,
   2471                MHD_HTTP_BAD_REQUEST,
   2472                TALER_EC_GENERIC_CURRENCY_MISMATCH,
   2473                total_wire_fee.currency));
   2474     return false;
   2475   }
   2476 
   2477   /* add wire fee to the total fees */
   2478   if (0 >
   2479       TALER_amount_add (&acc_fee,
   2480                         &acc_fee,
   2481                         &total_wire_fee))
   2482   {
   2483     GNUNET_break (0);
   2484     pay_end (pc,
   2485              TALER_MHD_reply_with_error (
   2486                pc->connection,
   2487                MHD_HTTP_INTERNAL_SERVER_ERROR,
   2488                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   2489                "Overflow adding up amounts"));
   2490     return false;
   2491   }
   2492   if (-1 == TALER_amount_cmp (&pc->validate_tokens.max_fee,
   2493                               &acc_fee))
   2494   {
   2495     /**
   2496      * Sum of fees of *all* the different exchanges of all the coins are
   2497      * higher than the fixed limit that the merchant is willing to pay.  The
   2498      * difference must be paid by the customer.
   2499      */
   2500     struct TALER_Amount excess_fee;
   2501 
   2502     /* compute fee amount to be covered by customer */
   2503     GNUNET_assert (TALER_AAR_RESULT_POSITIVE ==
   2504                    TALER_amount_subtract (&excess_fee,
   2505                                           &acc_fee,
   2506                                           &pc->validate_tokens.max_fee));
   2507     /* add that to the total */
   2508     if (0 >
   2509         TALER_amount_add (&total_needed,
   2510                           &excess_fee,
   2511                           &pc->validate_tokens.brutto))
   2512     {
   2513       GNUNET_break (0);
   2514       pay_end (pc,
   2515                TALER_MHD_reply_with_error (
   2516                  pc->connection,
   2517                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   2518                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   2519                  "Overflow adding up amounts"));
   2520       return false;
   2521     }
   2522   }
   2523   else
   2524   {
   2525     /* Fees are fully covered by the merchant, all we require
   2526        is that the total payment is not below the contract's amount */
   2527     total_needed = pc->validate_tokens.brutto;
   2528   }
   2529 
   2530   /* Do not count refunds towards the payment */
   2531   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2532               "Subtracting total refunds from paid amount: %s\n",
   2533               TALER_amount2s (&pc->pay_transaction.total_refunded));
   2534   if (0 >
   2535       TALER_amount_subtract (&final_amount,
   2536                              &acc_amount,
   2537                              &pc->pay_transaction.total_refunded))
   2538   {
   2539     GNUNET_break (0);
   2540     pay_end (pc,
   2541              TALER_MHD_reply_with_error (
   2542                pc->connection,
   2543                MHD_HTTP_INTERNAL_SERVER_ERROR,
   2544                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDS_EXCEED_PAYMENTS,
   2545                "refunded amount exceeds total payments"));
   2546     return false;
   2547   }
   2548 
   2549   if (-1 == TALER_amount_cmp (&final_amount,
   2550                               &total_needed))
   2551   {
   2552     /* acc_amount < total_needed */
   2553     if (-1 < TALER_amount_cmp (&acc_amount,
   2554                                &total_needed))
   2555     {
   2556       GNUNET_break_op (0);
   2557       pay_end (pc,
   2558                TALER_MHD_reply_with_error (
   2559                  pc->connection,
   2560                  MHD_HTTP_PAYMENT_REQUIRED,
   2561                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDED,
   2562                  "contract not paid up due to refunds"));
   2563       return false;
   2564     }
   2565     if (-1 < TALER_amount_cmp (&acc_amount,
   2566                                &pc->validate_tokens.brutto))
   2567     {
   2568       GNUNET_break_op (0);
   2569       pay_end (pc,
   2570                TALER_MHD_reply_with_error (
   2571                  pc->connection,
   2572                  MHD_HTTP_BAD_REQUEST,
   2573                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_DUE_TO_FEES,
   2574                  "contract not paid up due to fees (client may have calculated them badly)"));
   2575       return false;
   2576     }
   2577     GNUNET_break_op (0);
   2578     pay_end (pc,
   2579              TALER_MHD_reply_with_error (
   2580                pc->connection,
   2581                MHD_HTTP_BAD_REQUEST,
   2582                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_PAYMENT_INSUFFICIENT,
   2583                "payment insufficient"));
   2584     return false;
   2585   }
   2586   return true;
   2587 }
   2588 
   2589 
   2590 /**
   2591  * Execute the DB transaction.  If required (from
   2592  * soft/serialization errors), the transaction can be
   2593  * restarted here.
   2594  *
   2595  * @param[in,out] pc payment context to transact
   2596  */
   2597 static void
   2598 phase_execute_pay_transaction (struct PayContext *pc)
   2599 {
   2600   struct TMH_HandlerContext *hc = pc->hc;
   2601   const char *instance_id = hc->instance->settings.id;
   2602 
   2603   if (pc->batch_deposits.got_451)
   2604   {
   2605     pc->phase = PP_FAIL_LEGAL_REASONS;
   2606     return;
   2607   }
   2608   /* Avoid re-trying transactions on soft errors forever! */
   2609   if (pc->pay_transaction.retry_counter++ > MAX_RETRIES)
   2610   {
   2611     GNUNET_break (0);
   2612     pay_end (pc,
   2613              TALER_MHD_reply_with_error (pc->connection,
   2614                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
   2615                                          TALER_EC_GENERIC_DB_SOFT_FAILURE,
   2616                                          NULL));
   2617     return;
   2618   }
   2619 
   2620   /* Initialize some amount accumulators
   2621      (used in check_coin_paid(), check_coin_refunded()
   2622      and check_payment_sufficient()). */
   2623   GNUNET_break (GNUNET_OK ==
   2624                 TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2625                                        &pc->pay_transaction.total_paid));
   2626   GNUNET_break (GNUNET_OK ==
   2627                 TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2628                                        &pc->pay_transaction.total_fees_paid));
   2629   GNUNET_break (GNUNET_OK ==
   2630                 TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2631                                        &pc->pay_transaction.total_refunded));
   2632   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2633     pc->parse_pay.dc[i].found_in_db = false;
   2634   pc->pay_transaction.pending = pc->parse_pay.coins_cnt;
   2635 
   2636   /* First, try to see if we have all we need already done */
   2637   TMH_db->preflight (TMH_db->cls);
   2638   if (GNUNET_OK !=
   2639       TMH_db->start (TMH_db->cls,
   2640                      "run pay"))
   2641   {
   2642     GNUNET_break (0);
   2643     pay_end (pc,
   2644              TALER_MHD_reply_with_error (pc->connection,
   2645                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
   2646                                          TALER_EC_GENERIC_DB_START_FAILED,
   2647                                          NULL));
   2648     return;
   2649   }
   2650 
   2651   for (size_t i = 0; i<pc->parse_pay.tokens_cnt; i++)
   2652   {
   2653     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   2654     enum GNUNET_DB_QueryStatus qs;
   2655 
   2656     /* Insert used token into database, the unique constraint will
   2657        case an error if this token was used before. */
   2658     qs = TMH_db->insert_spent_token (TMH_db->cls,
   2659                                      &pc->check_contract.h_contract_terms,
   2660                                      &tuc->h_issue,
   2661                                      &tuc->pub,
   2662                                      &tuc->sig,
   2663                                      &tuc->unblinded_sig);
   2664 
   2665     switch (qs)
   2666     {
   2667     case GNUNET_DB_STATUS_SOFT_ERROR:
   2668       TMH_db->rollback (TMH_db->cls);
   2669       return; /* do it again */
   2670     case GNUNET_DB_STATUS_HARD_ERROR:
   2671       /* Always report on hard error as well to enable diagnostics */
   2672       TMH_db->rollback (TMH_db->cls);
   2673       pay_end (pc,
   2674                TALER_MHD_reply_with_error (pc->connection,
   2675                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   2676                                            TALER_EC_GENERIC_DB_STORE_FAILED,
   2677                                            "insert used token"));
   2678       return;
   2679     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   2680       /* UNIQUE constraint violation, meaning this token was already used. */
   2681       TMH_db->rollback (TMH_db->cls);
   2682       pay_end (pc,
   2683                TALER_MHD_reply_with_error (pc->connection,
   2684                                            MHD_HTTP_CONFLICT,
   2685                                            TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_INVALID,
   2686                                            NULL));
   2687       return;
   2688     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   2689       /* Good, proceed! */
   2690       break;
   2691     }
   2692   } /* for all tokens */
   2693 
   2694   {
   2695     enum GNUNET_DB_QueryStatus qs;
   2696 
   2697     /* Check if some of these coins already succeeded for _this_ contract.  */
   2698     qs = TMH_db->lookup_deposits (TMH_db->cls,
   2699                                   instance_id,
   2700                                   &pc->check_contract.h_contract_terms,
   2701                                   &check_coin_paid,
   2702                                   pc);
   2703     if (0 > qs)
   2704     {
   2705       TMH_db->rollback (TMH_db->cls);
   2706       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   2707         return; /* do it again */
   2708       /* Always report on hard error as well to enable diagnostics */
   2709       GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   2710       pay_end (pc,
   2711                TALER_MHD_reply_with_error (pc->connection,
   2712                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   2713                                            TALER_EC_GENERIC_DB_FETCH_FAILED,
   2714                                            "lookup deposits"));
   2715       return;
   2716     }
   2717     if (pc->pay_transaction.deposit_currency_mismatch)
   2718     {
   2719       TMH_db->rollback (TMH_db->cls);
   2720       GNUNET_break_op (0);
   2721       pay_end (pc,
   2722                TALER_MHD_reply_with_error (pc->connection,
   2723                                            MHD_HTTP_BAD_REQUEST,
   2724                                            TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH,
   2725                                            pc->validate_tokens.brutto.currency))
   2726       ;
   2727       return;
   2728     }
   2729   }
   2730 
   2731   {
   2732     enum GNUNET_DB_QueryStatus qs;
   2733 
   2734     /* Check if we refunded some of the coins */
   2735     qs = TMH_db->lookup_refunds (TMH_db->cls,
   2736                                  instance_id,
   2737                                  &pc->check_contract.h_contract_terms,
   2738                                  &check_coin_refunded,
   2739                                  pc);
   2740     if (0 > qs)
   2741     {
   2742       TMH_db->rollback (TMH_db->cls);
   2743       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   2744         return; /* do it again */
   2745       /* Always report on hard error as well to enable diagnostics */
   2746       GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   2747       pay_end (pc,
   2748                TALER_MHD_reply_with_error (pc->connection,
   2749                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   2750                                            TALER_EC_GENERIC_DB_FETCH_FAILED,
   2751                                            "lookup refunds"));
   2752       return;
   2753     }
   2754     if (pc->pay_transaction.refund_currency_mismatch)
   2755     {
   2756       TMH_db->rollback (TMH_db->cls);
   2757       pay_end (pc,
   2758                TALER_MHD_reply_with_error (pc->connection,
   2759                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   2760                                            TALER_EC_GENERIC_DB_FETCH_FAILED,
   2761                                            "refund currency in database does not match order currency"));
   2762       return;
   2763     }
   2764   }
   2765 
   2766   /* Check if there are coins that still need to be processed */
   2767   if (0 != pc->pay_transaction.pending)
   2768   {
   2769     /* we made no DB changes, so we can just rollback */
   2770     TMH_db->rollback (TMH_db->cls);
   2771     /* Ok, we need to first go to the network to process more coins.
   2772        We that interaction in *tiny* transactions (hence the rollback
   2773        above). */
   2774     pc->phase = PP_BATCH_DEPOSITS;
   2775     return;
   2776   }
   2777 
   2778   /* 0 == pc->pay_transaction.pending: all coins processed, let's see if that was enough */
   2779   if (! check_payment_sufficient (pc))
   2780   {
   2781     /* check_payment_sufficient() will have queued an error already.
   2782        We need to still abort the transaction. */
   2783     TMH_db->rollback (TMH_db->cls);
   2784     return;
   2785   }
   2786   /* Payment succeeded, save in database */
   2787   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2788               "Order `%s' (%s) was fully paid\n",
   2789               pc->order_id,
   2790               GNUNET_h2s (&pc->check_contract.h_contract_terms.hash));
   2791   {
   2792     enum GNUNET_DB_QueryStatus qs;
   2793 
   2794     qs = TMH_db->mark_contract_paid (TMH_db->cls,
   2795                                      instance_id,
   2796                                      &pc->check_contract.h_contract_terms,
   2797                                      pc->parse_pay.session_id,
   2798                                      pc->parse_wallet_data.choice_index);
   2799     if (qs < 0)
   2800     {
   2801       TMH_db->rollback (TMH_db->cls);
   2802       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   2803         return; /* do it again */
   2804       GNUNET_break (0);
   2805       pay_end (pc,
   2806                TALER_MHD_reply_with_error (pc->connection,
   2807                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   2808                                            TALER_EC_GENERIC_DB_STORE_FAILED,
   2809                                            "mark contract paid"));
   2810       return;
   2811     }
   2812   }
   2813 
   2814 
   2815   {
   2816     const struct TALER_MERCHANT_ContractChoice *choice =
   2817       &pc->check_contract.contract_terms->details.v1
   2818       .choices[pc->parse_wallet_data.choice_index];
   2819 
   2820     for (size_t i = 0; i<pc->output_tokens_len; i++)
   2821     {
   2822       unsigned int output_index;
   2823       enum TALER_MERCHANT_ContractOutputType type;
   2824 
   2825       output_index = pc->output_tokens[i].output_index;
   2826       GNUNET_assert (output_index < choice->outputs_len);
   2827       type = choice->outputs[output_index].type;
   2828 
   2829       switch (type)
   2830       {
   2831       case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   2832         /* Well, good luck getting here */
   2833         GNUNET_break (0);
   2834         pay_end (pc,
   2835                  TALER_MHD_reply_with_error (pc->connection,
   2836                                              MHD_HTTP_INTERNAL_SERVER_ERROR,
   2837                                              TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   2838                                              "invalid output type"));
   2839         break;
   2840       case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   2841         /* We skip output tokens of donation receipts here, as they are handled in the
   2842          * phase_final_output_token_processing() callback from donau */
   2843         break;
   2844       case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   2845         struct SignedOutputToken *output =
   2846           &pc->output_tokens[i];
   2847         enum GNUNET_DB_QueryStatus qs;
   2848 
   2849         qs = TMH_db->insert_issued_token (TMH_db->cls,
   2850                                           &pc->check_contract.h_contract_terms,
   2851                                           &output->h_issue,
   2852                                           &output->sig);
   2853         switch (qs)
   2854         {
   2855         case GNUNET_DB_STATUS_HARD_ERROR:
   2856           TMH_db->rollback (TMH_db->cls);
   2857           GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   2858           pay_end (pc,
   2859                    TALER_MHD_reply_with_error (pc->connection,
   2860                                                MHD_HTTP_INTERNAL_SERVER_ERROR,
   2861                                                TALER_EC_GENERIC_DB_STORE_FAILED,
   2862                                                "insert output token"));
   2863           return;
   2864         case GNUNET_DB_STATUS_SOFT_ERROR:
   2865           /* Serialization failure, retry */
   2866           TMH_db->rollback (TMH_db->cls);
   2867           return;
   2868         case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   2869           /* UNIQUE constraint violation, meaning this token was already used. */
   2870           TMH_db->rollback (TMH_db->cls);
   2871           pay_end (pc,
   2872                    TALER_MHD_reply_with_error (pc->connection,
   2873                                                MHD_HTTP_INTERNAL_SERVER_ERROR,
   2874                                                TALER_EC_GENERIC_DB_STORE_FAILED,
   2875                                                "duplicate output token"));
   2876           return;
   2877         case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   2878           break;
   2879         }
   2880         break;
   2881       }
   2882     }
   2883   }
   2884 
   2885   TMH_notify_order_change (hc->instance,
   2886                            TMH_OSF_CLAIMED | TMH_OSF_PAID,
   2887                            pc->check_contract.contract_terms->timestamp,
   2888                            pc->check_contract.order_serial);
   2889   {
   2890     enum GNUNET_DB_QueryStatus qs;
   2891     json_t *jhook;
   2892 
   2893     jhook = GNUNET_JSON_PACK (
   2894       GNUNET_JSON_pack_object_incref ("contract_terms",
   2895                                       pc->check_contract.contract_terms_json),
   2896       GNUNET_JSON_pack_string ("order_id",
   2897                                pc->order_id)
   2898       );
   2899     GNUNET_assert (NULL != jhook);
   2900     qs = TMH_trigger_webhook (pc->hc->instance->settings.id,
   2901                               "pay",
   2902                               jhook);
   2903     json_decref (jhook);
   2904     if (qs < 0)
   2905     {
   2906       TMH_db->rollback (TMH_db->cls);
   2907       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   2908         return; /* do it again */
   2909       GNUNET_break (0);
   2910       pay_end (pc,
   2911                TALER_MHD_reply_with_error (pc->connection,
   2912                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   2913                                            TALER_EC_GENERIC_DB_STORE_FAILED,
   2914                                            "failed to trigger webhooks"));
   2915       return;
   2916     }
   2917   }
   2918   {
   2919     enum GNUNET_DB_QueryStatus qs;
   2920 
   2921     /* Now commit! */
   2922     qs = TMH_db->commit (TMH_db->cls);
   2923     if (0 > qs)
   2924     {
   2925       /* commit failed */
   2926       TMH_db->rollback (TMH_db->cls);
   2927       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   2928         return; /* do it again */
   2929       GNUNET_break (0);
   2930       pay_end (pc,
   2931                TALER_MHD_reply_with_error (pc->connection,
   2932                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   2933                                            TALER_EC_GENERIC_DB_COMMIT_FAILED,
   2934                                            NULL));
   2935       return;
   2936     }
   2937   }
   2938   pc->phase++;
   2939 }
   2940 
   2941 
   2942 /**
   2943  * Ensures that the expected number of tokens for a @e key
   2944  * are provided as inputs and have valid signatures.
   2945  *
   2946  * @param[in,out] pc payment context we are processing
   2947  * @param family family the tokens should be from
   2948  * @param index number of the input we are handling
   2949  * @param expected_num number of tokens expected
   2950  * @return #GNUNET_YES on success
   2951  */
   2952 static enum GNUNET_GenericReturnValue
   2953 find_valid_input_tokens (
   2954   struct PayContext *pc,
   2955   const struct TALER_MERCHANT_ContractTokenFamily *family,
   2956   unsigned int index,
   2957   unsigned int expected_num)
   2958 {
   2959   unsigned int num_validated = 0;
   2960   struct GNUNET_TIME_Timestamp now
   2961     = GNUNET_TIME_timestamp_get ();
   2962   const struct TALER_MERCHANT_ContractTokenFamilyKey *kig = NULL;
   2963 
   2964   for (unsigned int j = 0; j < expected_num; j++)
   2965   {
   2966     struct TokenUseConfirmation *tuc
   2967       = &pc->parse_pay.tokens[index + j];
   2968     const struct TALER_MERCHANT_ContractTokenFamilyKey *key = NULL;
   2969 
   2970     for (unsigned int i = 0; i<family->keys_len; i++)
   2971     {
   2972       const struct TALER_MERCHANT_ContractTokenFamilyKey *ki
   2973         = &family->keys[i];
   2974 
   2975       if (0 ==
   2976           GNUNET_memcmp (&ki->pub.public_key->pub_key_hash,
   2977                          &tuc->h_issue.hash))
   2978       {
   2979         if (GNUNET_TIME_timestamp_cmp (ki->valid_after,
   2980                                        >,
   2981                                        now) ||
   2982             GNUNET_TIME_timestamp_cmp (ki->valid_before,
   2983                                        <=,
   2984                                        now))
   2985         {
   2986           /* We have a match, but not in the current validity period */
   2987           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2988                       "Public key %s currently not valid\n",
   2989                       GNUNET_h2s (&ki->pub.public_key->pub_key_hash));
   2990           kig = ki;
   2991           continue;
   2992         }
   2993         key = ki;
   2994         break;
   2995       }
   2996     }
   2997     if (NULL == key)
   2998     {
   2999       if (NULL != kig)
   3000       {
   3001         char start_str[128];
   3002         char end_str[128];
   3003         char emsg[350];
   3004 
   3005         GNUNET_snprintf (start_str,
   3006                          sizeof (start_str),
   3007                          "%s",
   3008                          GNUNET_STRINGS_timestamp_to_string (kig->valid_after));
   3009         GNUNET_snprintf (end_str,
   3010                          sizeof (end_str),
   3011                          "%s",
   3012                          GNUNET_STRINGS_timestamp_to_string (kig->valid_before))
   3013         ;
   3014         /* FIXME: use more specific EC */
   3015         GNUNET_snprintf (emsg,
   3016                          sizeof (emsg),
   3017                          "Token is only valid from %s to %s",
   3018                          start_str,
   3019                          end_str);
   3020         pay_end (pc,
   3021                  TALER_MHD_reply_with_error (
   3022                    pc->connection,
   3023                    MHD_HTTP_GONE,
   3024                    TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED,
   3025                    emsg));
   3026         return GNUNET_NO;
   3027       }
   3028       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3029                   "Input token supplied for public key %s that is not acceptable\n",
   3030                   GNUNET_h2s (&tuc->h_issue.hash));
   3031       GNUNET_break_op (0);
   3032       pay_end (pc,
   3033                TALER_MHD_reply_with_error (
   3034                  pc->connection,
   3035                  MHD_HTTP_BAD_REQUEST,
   3036                  TALER_EC_MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN,
   3037                  NULL));
   3038       return GNUNET_NO;
   3039     }
   3040     if (GNUNET_OK !=
   3041         TALER_token_issue_verify (&tuc->pub,
   3042                                   &key->pub,
   3043                                   &tuc->unblinded_sig))
   3044     {
   3045       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3046                   "Input token for public key with valid_after "
   3047                   "`%s' has invalid issue signature\n",
   3048                   GNUNET_TIME_timestamp2s (key->valid_after));
   3049       GNUNET_break (0);
   3050       pay_end (pc,
   3051                TALER_MHD_reply_with_error (
   3052                  pc->connection,
   3053                  MHD_HTTP_BAD_REQUEST,
   3054                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ISSUE_SIG_INVALID,
   3055                  NULL));
   3056       return GNUNET_NO;
   3057     }
   3058 
   3059     if (GNUNET_OK !=
   3060         TALER_wallet_token_use_verify (&pc->check_contract.h_contract_terms,
   3061                                        &pc->parse_wallet_data.h_wallet_data,
   3062                                        &tuc->pub,
   3063                                        &tuc->sig))
   3064     {
   3065       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3066                   "Input token for public key with valid_before "
   3067                   "`%s' has invalid use signature\n",
   3068                   GNUNET_TIME_timestamp2s (key->valid_before));
   3069       GNUNET_break (0);
   3070       pay_end (pc,
   3071                TALER_MHD_reply_with_error (
   3072                  pc->connection,
   3073                  MHD_HTTP_BAD_REQUEST,
   3074                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_USE_SIG_INVALID,
   3075                  NULL));
   3076       return GNUNET_NO;
   3077     }
   3078 
   3079     num_validated++;
   3080   }
   3081 
   3082   if (num_validated != expected_num)
   3083   {
   3084     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3085                 "Expected %d tokens for family %s, but found %d\n",
   3086                 expected_num,
   3087                 family->slug,
   3088                 num_validated);
   3089     GNUNET_break (0);
   3090     pay_end (pc,
   3091              TALER_MHD_reply_with_error (
   3092                pc->connection,
   3093                MHD_HTTP_BAD_REQUEST,
   3094                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_COUNT_MISMATCH,
   3095                NULL));
   3096     return GNUNET_NO;
   3097   }
   3098   return GNUNET_YES;
   3099 }
   3100 
   3101 
   3102 /**
   3103  * Check if an output token of the given @a tfk is mandatory, or if
   3104  * wallets are allowed to simply not support it and still proceed.
   3105  *
   3106  * @param tfk token family kind to check
   3107  * @return true if such outputs are mandatory and wallets must supply
   3108  *  the corresponding blinded input
   3109  */
   3110 /* FIXME: this function belongs into a lower-level lib! */
   3111 static bool
   3112 test_tfk_mandatory (enum TALER_MERCHANTDB_TokenFamilyKind tfk)
   3113 {
   3114   switch (tfk)
   3115   {
   3116   case TALER_MERCHANTDB_TFK_Discount:
   3117     return false;
   3118   case TALER_MERCHANTDB_TFK_Subscription:
   3119     return true;
   3120   }
   3121   GNUNET_break (0);
   3122   return false;
   3123 }
   3124 
   3125 
   3126 /**
   3127  * Sign the tokens provided by the wallet for a particular @a key.
   3128  *
   3129  * @param[in,out] pc reference for payment we are processing
   3130  * @param key token family data
   3131  * @param priv private key to use to sign with
   3132  * @param mandatory true if the token must exist, if false
   3133  *        and the client did not provide an envelope, that's OK and
   3134  *        we just also skimp on the signature
   3135  * @param index offset in the token envelope array (from other families)
   3136  * @param expected_num number of tokens of this type that we should create
   3137  * @return #GNUNET_NO on failure
   3138  *         #GNUNET_OK on success
   3139  */
   3140 static enum GNUNET_GenericReturnValue
   3141 sign_token_envelopes (
   3142   struct PayContext *pc,
   3143   const struct TALER_MERCHANT_ContractTokenFamilyKey *key,
   3144   const struct TALER_TokenIssuePrivateKey *priv,
   3145   bool mandatory,
   3146   unsigned int index,
   3147   unsigned int expected_num)
   3148 {
   3149   unsigned int num_signed = 0;
   3150 
   3151   for (unsigned int j = 0; j<expected_num; j++)
   3152   {
   3153     unsigned int pos = index + j;
   3154     const struct TokenEnvelope *env
   3155       = &pc->parse_wallet_data.token_envelopes[pos];
   3156     struct SignedOutputToken *output
   3157       = &pc->output_tokens[pos];
   3158 
   3159     if ( (pos >= pc->parse_wallet_data.token_envelopes_cnt) ||
   3160          (pos >= pc->output_tokens_len) )
   3161     {
   3162       GNUNET_assert (0); /* this should not happen */
   3163       return GNUNET_NO;
   3164     }
   3165     if (NULL == env->blinded_token.blinded_pub)
   3166     {
   3167       if (! mandatory)
   3168         continue;
   3169 
   3170       /* mandatory token families require a token envelope. */
   3171       GNUNET_break_op (0);
   3172       pay_end (pc,
   3173                TALER_MHD_reply_with_error (
   3174                  pc->connection,
   3175                  MHD_HTTP_BAD_REQUEST,
   3176                  TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3177                  "Token envelope for mandatory token family missing"));
   3178       return GNUNET_NO;
   3179     }
   3180     TALER_token_issue_sign (priv,
   3181                             &env->blinded_token,
   3182                             &output->sig);
   3183     output->h_issue.hash
   3184       = key->pub.public_key->pub_key_hash;
   3185     num_signed++;
   3186   }
   3187 
   3188   if (mandatory &&
   3189       (num_signed != expected_num) )
   3190   {
   3191     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3192                 "Expected %d token envelopes for public key with valid_after "
   3193                 "'%s', but found %d\n",
   3194                 expected_num,
   3195                 GNUNET_TIME_timestamp2s (key->valid_after),
   3196                 num_signed);
   3197     GNUNET_break (0);
   3198     pay_end (pc,
   3199              TALER_MHD_reply_with_error (
   3200                pc->connection,
   3201                MHD_HTTP_BAD_REQUEST,
   3202                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ENVELOPE_COUNT_MISMATCH,
   3203                NULL));
   3204     return GNUNET_NO;
   3205   }
   3206 
   3207   return GNUNET_OK;
   3208 }
   3209 
   3210 
   3211 /**
   3212  * Find the family entry for the family of the given @a slug
   3213  * in @a pc.
   3214  *
   3215  * @param[in] pc payment context to search
   3216  * @param slug slug to search for
   3217  * @return NULL if @a slug was not found
   3218  */
   3219 static const struct TALER_MERCHANT_ContractTokenFamily *
   3220 find_family (const struct PayContext *pc,
   3221              const char *slug)
   3222 {
   3223   for (unsigned int i = 0;
   3224        i < pc->check_contract.contract_terms->details.v1.token_authorities_len;
   3225        i++)
   3226   {
   3227     const struct TALER_MERCHANT_ContractTokenFamily *tfi
   3228       = &pc->check_contract.contract_terms->details.v1.token_authorities[i];
   3229 
   3230     if (0 == strcmp (tfi->slug,
   3231                      slug))
   3232     {
   3233       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3234                   "Token family %s found with %u keys\n",
   3235                   slug,
   3236                   tfi->keys_len);
   3237       return tfi;
   3238     }
   3239   }
   3240   return NULL;
   3241 }
   3242 
   3243 
   3244 /**
   3245  * Handle contract output of type TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN.
   3246  * Looks up the token family, loads the matching private key,
   3247  * and signs the corresponding token envelopes from the wallet.
   3248  *
   3249  * @param pc context for the pay request
   3250  * @param output contract output we need to process
   3251  * @param output_index index of this output in the contract's outputs array
   3252  * @return #GNUNET_OK on success, #GNUNET_NO if an error was encountered
   3253  */
   3254 static enum GNUNET_GenericReturnValue
   3255 handle_output_token (struct PayContext *pc,
   3256                      const struct TALER_MERCHANT_ContractOutput *output,
   3257                      unsigned int output_index)
   3258 {
   3259   const struct TALER_MERCHANT_ContractTokenFamily *family;
   3260   struct TALER_MERCHANT_ContractTokenFamilyKey *key;
   3261   struct TALER_MERCHANTDB_TokenFamilyKeyDetails details;
   3262   enum GNUNET_DB_QueryStatus qs;
   3263   bool mandatory;
   3264 
   3265   /* Locate token family in the contract.
   3266      This should ever fail as this invariant should
   3267      have been checked when the contract was created. */
   3268   family = find_family (pc,
   3269                         output->details.token.token_family_slug);
   3270   if (NULL == family)
   3271   {
   3272     /* This "should never happen", so treat it as an internal error */
   3273     GNUNET_break (0);
   3274     pay_end (pc,
   3275              TALER_MHD_reply_with_error (
   3276                pc->connection,
   3277                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3278                TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3279                "token family not found in order"));
   3280     return GNUNET_SYSERR;
   3281   }
   3282 
   3283   /* Check the key_index field from the output. */
   3284   if (output->details.token.key_index >= family->keys_len)
   3285   {
   3286     /* Also "should never happen", contract was presumably validated on insert */
   3287     GNUNET_break (0);
   3288     pay_end (pc,
   3289              TALER_MHD_reply_with_error (
   3290                pc->connection,
   3291                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3292                TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3293                "key index invalid for token family"));
   3294     return GNUNET_SYSERR;
   3295   }
   3296 
   3297   /* Pick the correct key inside that family. */
   3298   key = &family->keys[output->details.token.key_index];
   3299 
   3300   /* Fetch the private key from the DB for the merchant instance and
   3301    * this particular family/time interval. */
   3302   qs = TMH_db->lookup_token_family_key (
   3303     TMH_db->cls,
   3304     pc->hc->instance->settings.id,
   3305     family->slug,
   3306     pc->check_contract.contract_terms->timestamp,
   3307     pc->check_contract.contract_terms->pay_deadline,
   3308     &details);
   3309   switch (qs)
   3310   {
   3311   case GNUNET_DB_STATUS_HARD_ERROR:
   3312   case GNUNET_DB_STATUS_SOFT_ERROR:
   3313     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3314                 "Database error looking up token-family key for %s\n",
   3315                 family->slug);
   3316     GNUNET_break (0);
   3317     pay_end (pc,
   3318              TALER_MHD_reply_with_error (
   3319                pc->connection,
   3320                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3321                TALER_EC_GENERIC_DB_FETCH_FAILED,
   3322                NULL));
   3323     return GNUNET_NO;
   3324   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   3325     GNUNET_log (
   3326       GNUNET_ERROR_TYPE_ERROR,
   3327       "Token-family key for %s not found at [%llu,%llu]\n",
   3328       family->slug,
   3329       (unsigned long long)
   3330       pc->check_contract.contract_terms->timestamp.abs_time.abs_value_us,
   3331       (unsigned long long)
   3332       pc->check_contract.contract_terms->pay_deadline.abs_time.abs_value_us
   3333       );
   3334     GNUNET_break (0);
   3335     pay_end (pc,
   3336              TALER_MHD_reply_with_error (
   3337                pc->connection,
   3338                MHD_HTTP_NOT_FOUND,
   3339                TALER_EC_GENERIC_DB_FETCH_FAILED,
   3340                NULL));
   3341     return GNUNET_NO;
   3342 
   3343   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   3344     break;
   3345   }
   3346   GNUNET_assert (NULL != details.priv.private_key);
   3347   GNUNET_free (details.token_family.slug);
   3348   GNUNET_free (details.token_family.name);
   3349   GNUNET_free (details.token_family.description);
   3350   json_decref (details.token_family.description_i18n);
   3351   GNUNET_CRYPTO_blind_sign_pub_decref (details.pub.public_key);
   3352   GNUNET_free (details.token_family.cipher_spec);
   3353 
   3354   /* Depending on the token family, decide if the token envelope
   3355    * is mandatory or optional.  (Simplified logic here: adapt as needed.) */
   3356   mandatory = test_tfk_mandatory (details.token_family.kind);
   3357   /* Actually sign the number of token envelopes specified in 'count'.
   3358    * 'output_index' is the offset into the parse_wallet_data arrays.  */
   3359   if (GNUNET_OK !=
   3360       sign_token_envelopes (pc,
   3361                             key,
   3362                             &details.priv,
   3363                             mandatory,
   3364                             output_index,
   3365                             output->details.token.count))
   3366   {
   3367     /* sign_token_envelopes() already queued up an error via pay_end() */
   3368     GNUNET_break_op (0);
   3369     return GNUNET_NO;
   3370   }
   3371   GNUNET_CRYPTO_blind_sign_priv_decref (details.priv.private_key);
   3372   return GNUNET_OK;
   3373 }
   3374 
   3375 
   3376 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   3377 /**
   3378  * Handle checks for contract output of type TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT.
   3379  * For now, this does nothing and simply returns #GNUNET_OK.
   3380  *
   3381  * @param pc context for the pay request
   3382  * @param output the contract output describing the donation receipt requirement
   3383  * @return #GNUNET_OK on success,
   3384  *         #GNUNET_NO if an error was already queued
   3385  */
   3386 static enum GNUNET_GenericReturnValue
   3387 handle_output_donation_receipt (
   3388   struct PayContext *pc,
   3389   const struct TALER_MERCHANT_ContractOutput *output)
   3390 {
   3391   enum GNUNET_GenericReturnValue ret;
   3392 
   3393   ret = DONAU_get_donation_amount_from_bkps (
   3394     pc->parse_wallet_data.donau_keys,
   3395     pc->parse_wallet_data.bkps,
   3396     pc->parse_wallet_data.num_bkps,
   3397     pc->parse_wallet_data.donau.donation_year,
   3398     &pc->parse_wallet_data.donation_amount);
   3399   switch (ret)
   3400   {
   3401   case GNUNET_SYSERR:
   3402     GNUNET_break (0);
   3403     pay_end (pc,
   3404              TALER_MHD_reply_with_error (
   3405                pc->connection,
   3406                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3407                TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3408                NULL));
   3409     return GNUNET_NO;
   3410   case GNUNET_NO:
   3411     GNUNET_break_op (0);
   3412     pay_end (pc,
   3413              TALER_MHD_reply_with_error (
   3414                pc->connection,
   3415                MHD_HTTP_BAD_REQUEST,
   3416                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3417                "inconsistent bkps / donau keys"));
   3418     return GNUNET_NO;
   3419   case GNUNET_OK:
   3420     break;
   3421   }
   3422 
   3423   if (GNUNET_OK !=
   3424       TALER_amount_cmp_currency (&pc->parse_wallet_data.donation_amount,
   3425                                  &output->details.donation_receipt.amount))
   3426   {
   3427     GNUNET_break_op (0);
   3428     pay_end (pc,
   3429              TALER_MHD_reply_with_error (
   3430                pc->connection,
   3431                MHD_HTTP_BAD_REQUEST,
   3432                TALER_EC_GENERIC_CURRENCY_MISMATCH,
   3433                output->details.donation_receipt.amount.currency));
   3434     return GNUNET_NO;
   3435   }
   3436 
   3437   if (0 !=
   3438       TALER_amount_cmp (&pc->parse_wallet_data.donation_amount,
   3439                         &output->details.donation_receipt.amount))
   3440   {
   3441     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3442                 "Wallet amount: %s\n",
   3443                 TALER_amount2s (&pc->parse_wallet_data.donation_amount));
   3444     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3445                 "Donation receipt amount: %s\n",
   3446                 TALER_amount2s (&output->details.donation_receipt.amount));
   3447     GNUNET_break_op (0);
   3448     pay_end (pc,
   3449              TALER_MHD_reply_with_error (
   3450                pc->connection,
   3451                MHD_HTTP_CONFLICT,
   3452                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH,
   3453                "donation amount mismatch"));
   3454     return GNUNET_NO;
   3455   }
   3456   {
   3457     struct TALER_Amount receipts_to_date;
   3458 
   3459     if (0 >
   3460         TALER_amount_add (&receipts_to_date,
   3461                           &pc->parse_wallet_data.charity_receipts_to_date,
   3462                           &pc->parse_wallet_data.donation_amount))
   3463     {
   3464       GNUNET_break (0);
   3465       pay_end (pc,
   3466                TALER_MHD_reply_with_error (pc->connection,
   3467                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3468                                            TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   3469                                            "adding donation amount"));
   3470       return GNUNET_NO;
   3471     }
   3472 
   3473     if (1 ==
   3474         TALER_amount_cmp (&receipts_to_date,
   3475                           &pc->parse_wallet_data.charity_max_per_year))
   3476     {
   3477       GNUNET_break_op (0);
   3478       pay_end (pc,
   3479                TALER_MHD_reply_with_error (pc->connection,
   3480                                            MHD_HTTP_CONFLICT,
   3481                                            TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH,
   3482                                            "donation limit exceeded"));
   3483       return GNUNET_NO;
   3484     }
   3485     pc->parse_wallet_data.charity_receipts_to_date = receipts_to_date;
   3486   }
   3487   return GNUNET_OK;
   3488 }
   3489 
   3490 
   3491 #endif /* HAVE_DONAU_DONAU_SERVICE_H */
   3492 
   3493 
   3494 /**
   3495  * Count tokens produced by an output.
   3496  *
   3497  * @param pc pay context
   3498  * @param output output to consider
   3499  * @returns number of output tokens
   3500  */
   3501 static unsigned int
   3502 count_output_tokens (const struct PayContext *pc,
   3503                      const struct TALER_MERCHANT_ContractOutput *output)
   3504 {
   3505   switch (output->type)
   3506   {
   3507   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   3508     GNUNET_assert (0);
   3509     break;
   3510   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   3511     return output->details.token.count;
   3512   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   3513 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   3514     return pc->parse_wallet_data.num_bkps;
   3515 #else
   3516     return 0;
   3517 #endif
   3518   }
   3519   /* Not reached. */
   3520   GNUNET_assert (0);
   3521 }
   3522 
   3523 
   3524 /**
   3525  * Validate tokens and token envelopes. First, we check if all tokens listed
   3526  * in the 'inputs' array of the selected choice are present in the 'tokens'
   3527  * array of the request. Then, we validate the signatures of each provided
   3528  * token.
   3529  *
   3530  * @param[in,out] pc context we use to handle the payment
   3531  */
   3532 static void
   3533 phase_validate_tokens (struct PayContext *pc)
   3534 {
   3535   /* We haven't seen a donau output yet. */
   3536   pc->validate_tokens.donau_output_index = -1;
   3537 
   3538   switch (pc->check_contract.contract_terms->version)
   3539   {
   3540   case TALER_MERCHANT_CONTRACT_VERSION_0:
   3541     /* No tokens to validate */
   3542     pc->phase = PP_PAY_TRANSACTION;
   3543     pc->validate_tokens.max_fee
   3544       = pc->check_contract.contract_terms->details.v0.max_fee;
   3545     pc->validate_tokens.brutto
   3546       = pc->check_contract.contract_terms->details.v0.brutto;
   3547     break;
   3548   case TALER_MERCHANT_CONTRACT_VERSION_1:
   3549     {
   3550       const struct TALER_MERCHANT_ContractChoice *selected
   3551         = &pc->check_contract.contract_terms->details.v1.choices[
   3552             pc->parse_wallet_data.choice_index];
   3553       unsigned int output_off;
   3554       unsigned int cnt;
   3555 
   3556       pc->validate_tokens.max_fee = selected->max_fee;
   3557       pc->validate_tokens.brutto = selected->amount;
   3558 
   3559       for (unsigned int i = 0; i<selected->inputs_len; i++)
   3560       {
   3561         const struct TALER_MERCHANT_ContractInput *input
   3562           = &selected->inputs[i];
   3563         const struct TALER_MERCHANT_ContractTokenFamily *family;
   3564 
   3565         switch (input->type)
   3566         {
   3567         case TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID:
   3568           GNUNET_break (0);
   3569           pay_end (pc,
   3570                    TALER_MHD_reply_with_error (
   3571                      pc->connection,
   3572                      MHD_HTTP_BAD_REQUEST,
   3573                      TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3574                      "input token type not valid"));
   3575           return;
   3576 #if FUTURE
   3577         case TALER_MERCHANT_CONTRACT_INPUT_TYPE_COIN:
   3578           GNUNET_break (0);
   3579           pay_end (pc,
   3580                    TALER_MHD_reply_with_error (
   3581                      pc->connection,
   3582                      MHD_HTTP_NOT_IMPLEMENTED,
   3583                      TALER_EC_MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE,
   3584                      "token type not yet supported"));
   3585           return;
   3586 #endif
   3587         case TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN:
   3588           family = find_family (pc,
   3589                                 input->details.token.token_family_slug);
   3590           if (NULL == family)
   3591           {
   3592             /* this should never happen, since the choices and
   3593                token families are validated on insert. */
   3594             GNUNET_break (0);
   3595             pay_end (pc,
   3596                      TALER_MHD_reply_with_error (
   3597                        pc->connection,
   3598                        MHD_HTTP_INTERNAL_SERVER_ERROR,
   3599                        TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3600                        "token family not found in order"));
   3601             return;
   3602           }
   3603           if (GNUNET_NO ==
   3604               find_valid_input_tokens (pc,
   3605                                        family,
   3606                                        i,
   3607                                        input->details.token.count))
   3608           {
   3609             /* Error is already scheduled from find_valid_input_token. */
   3610             return;
   3611           }
   3612         }
   3613       }
   3614 
   3615       /* calculate pc->output_tokens_len */
   3616       output_off = 0;
   3617       for (unsigned int i = 0; i<selected->outputs_len; i++)
   3618       {
   3619         const struct TALER_MERCHANT_ContractOutput *output
   3620           = &selected->outputs[i];
   3621 
   3622         switch (output->type)
   3623         {
   3624         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   3625           GNUNET_assert (0);
   3626           break;
   3627         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   3628           cnt = output->details.token.count;
   3629           if (output_off + cnt < output_off)
   3630           {
   3631             GNUNET_break_op (0);
   3632             pay_end (pc,
   3633                      TALER_MHD_reply_with_error (
   3634                        pc->connection,
   3635                        MHD_HTTP_BAD_REQUEST,
   3636                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3637                        "output token counter overflow"));
   3638             return;
   3639           }
   3640           output_off += cnt;
   3641           break;
   3642         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   3643           /* check that this output type appears at most once */
   3644           if (pc->validate_tokens.donau_output_index >= 0)
   3645           {
   3646             /* This should have been prevented when the
   3647                contract was initially created */
   3648             GNUNET_break (0);
   3649             pay_end (pc,
   3650                      TALER_MHD_reply_with_error (
   3651                        pc->connection,
   3652                        MHD_HTTP_INTERNAL_SERVER_ERROR,
   3653                        TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
   3654                        "two donau output sets in same contract"));
   3655             return;
   3656           }
   3657           pc->validate_tokens.donau_output_index = i;
   3658 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   3659           if (output_off + pc->parse_wallet_data.num_bkps < output_off)
   3660           {
   3661             GNUNET_break_op (0);
   3662             pay_end (pc,
   3663                      TALER_MHD_reply_with_error (
   3664                        pc->connection,
   3665                        MHD_HTTP_BAD_REQUEST,
   3666                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3667                        "output token counter overflow"));
   3668             return;
   3669           }
   3670           output_off += pc->parse_wallet_data.num_bkps;
   3671 #endif
   3672           break;
   3673         }
   3674       }
   3675 
   3676 
   3677       pc->output_tokens_len = output_off;
   3678       pc->output_tokens
   3679         = GNUNET_new_array (pc->output_tokens_len,
   3680                             struct SignedOutputToken);
   3681 
   3682       /* calculate pc->output_tokens[].output_index */
   3683       output_off = 0;
   3684       for (unsigned int i = 0; i<selected->outputs_len; i++)
   3685       {
   3686         const struct TALER_MERCHANT_ContractOutput *output
   3687           = &selected->outputs[i];
   3688         cnt = count_output_tokens (pc,
   3689                                    output);
   3690         for (unsigned int j = 0; j<cnt; j++)
   3691           pc->output_tokens[output_off + j].output_index = i;
   3692         output_off += cnt;
   3693       }
   3694 
   3695       /* compute non-donau outputs */
   3696       output_off = 0;
   3697       for (unsigned int i = 0; i<selected->outputs_len; i++)
   3698       {
   3699         const struct TALER_MERCHANT_ContractOutput *output
   3700           = &selected->outputs[i];
   3701 
   3702         switch (output->type)
   3703         {
   3704         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   3705           GNUNET_assert (0);
   3706           break;
   3707         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   3708           cnt = output->details.token.count;
   3709           GNUNET_assert (output_off + cnt
   3710                          <= pc->output_tokens_len);
   3711           if (GNUNET_OK !=
   3712               handle_output_token (pc,
   3713                                    output,
   3714                                    output_off))
   3715           {
   3716             /* Error is already scheduled from handle_output_token. */
   3717             return;
   3718           }
   3719           output_off += cnt;
   3720           break;
   3721         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   3722 #ifndef HAVE_DONAU_DONAU_SERVICE_H
   3723           /* We checked at parse time, and
   3724              wallet didn't want donau, so OK! */
   3725           return;
   3726 #else
   3727           if ( (0 != pc->parse_wallet_data.num_bkps) &&
   3728                (GNUNET_OK !=
   3729                 handle_output_donation_receipt (pc,
   3730                                                 output)) )
   3731           {
   3732             /* Error is already scheduled from handle_output_donation_receipt. */
   3733             return;
   3734           }
   3735           output_off += pc->parse_wallet_data.num_bkps;
   3736           continue;
   3737 #endif
   3738         } /* switch on output token */
   3739       } /* for all output token types */
   3740     } /* case contract v1 */
   3741     break;
   3742   } /* switch on contract type */
   3743 
   3744   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   3745   {
   3746     const struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   3747 
   3748     if (GNUNET_OK !=
   3749         TALER_amount_cmp_currency (&dc->cdd.amount,
   3750                                    &pc->validate_tokens.brutto))
   3751     {
   3752       GNUNET_break_op (0);
   3753       pay_end (pc,
   3754                TALER_MHD_reply_with_error (
   3755                  pc->connection,
   3756                  MHD_HTTP_CONFLICT,
   3757                  TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH,
   3758                  pc->validate_tokens.brutto.currency));
   3759       return;
   3760     }
   3761   }
   3762 
   3763   pc->phase = PP_PAY_TRANSACTION;
   3764 }
   3765 
   3766 
   3767 /**
   3768  * Function called with information about a coin that was deposited.
   3769  * Checks if this coin is in our list of deposits as well.
   3770  *
   3771  * @param cls closure with our `struct PayContext *`
   3772  * @param deposit_serial which deposit operation is this about
   3773  * @param exchange_url URL of the exchange that issued the coin
   3774  * @param h_wire hash of merchant's wire details
   3775  * @param deposit_timestamp when was the deposit made
   3776  * @param amount_with_fee amount the exchange will deposit for this coin
   3777  * @param deposit_fee fee the exchange will charge for this coin
   3778  * @param coin_pub public key of the coin
   3779  */
   3780 static void
   3781 deposit_paid_check (
   3782   void *cls,
   3783   uint64_t deposit_serial,
   3784   const char *exchange_url,
   3785   const struct TALER_MerchantWireHashP *h_wire,
   3786   struct GNUNET_TIME_Timestamp deposit_timestamp,
   3787   const struct TALER_Amount *amount_with_fee,
   3788   const struct TALER_Amount *deposit_fee,
   3789   const struct TALER_CoinSpendPublicKeyP *coin_pub)
   3790 {
   3791   struct PayContext *pc = cls;
   3792 
   3793   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   3794   {
   3795     struct DepositConfirmation *dci = &pc->parse_pay.dc[i];
   3796 
   3797     if ( (0 ==
   3798           GNUNET_memcmp (&dci->cdd.coin_pub,
   3799                          coin_pub)) &&
   3800          (0 ==
   3801           strcmp (dci->exchange_url,
   3802                   exchange_url)) &&
   3803          (GNUNET_YES ==
   3804           TALER_amount_cmp_currency (&dci->cdd.amount,
   3805                                      amount_with_fee)) &&
   3806          (0 ==
   3807           TALER_amount_cmp (&dci->cdd.amount,
   3808                             amount_with_fee)) )
   3809     {
   3810       dci->matched_in_db = true;
   3811       break;
   3812     }
   3813   }
   3814 }
   3815 
   3816 
   3817 /**
   3818  * Function called with information about a token that was spent.
   3819  * FIXME: Replace this with a more specific function for this cb
   3820  *
   3821  * @param cls closure with `struct PayContext *`
   3822  * @param spent_token_serial "serial" of the spent token unused
   3823  * @param h_contract_terms hash of the contract terms unused
   3824  * @param h_issue_pub hash of the token issue public key unused
   3825  * @param use_pub public key of the token
   3826  * @param use_sig signature of the token
   3827  * @param issue_sig signature of the token issue
   3828  */
   3829 static void
   3830 input_tokens_paid_check (
   3831   void *cls,
   3832   uint64_t spent_token_serial,
   3833   const struct TALER_PrivateContractHashP *h_contract_terms,
   3834   const struct TALER_TokenIssuePublicKeyHashP *h_issue_pub,
   3835   const struct TALER_TokenUsePublicKeyP *use_pub,
   3836   const struct TALER_TokenUseSignatureP *use_sig,
   3837   const struct TALER_TokenIssueSignature *issue_sig)
   3838 {
   3839   struct PayContext *pc = cls;
   3840 
   3841   for (size_t i = 0; i<pc->parse_pay.tokens_cnt; i++)
   3842   {
   3843     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   3844 
   3845     if ( (0 ==
   3846           GNUNET_memcmp (&tuc->pub,
   3847                          use_pub)) &&
   3848          (0 ==
   3849           GNUNET_memcmp (&tuc->sig,
   3850                          use_sig)) &&
   3851          (0 ==
   3852           GNUNET_memcmp (&tuc->unblinded_sig,
   3853                          issue_sig)) )
   3854     {
   3855       tuc->found_in_db = true;
   3856       break;
   3857     }
   3858   }
   3859 }
   3860 
   3861 
   3862 /**
   3863  * Small helper function to append an output token signature from db
   3864  *
   3865  * @param cls closure with `struct PayContext *`
   3866  * @param h_issue hash of the token
   3867  * @param sig signature of the token
   3868  */
   3869 static void
   3870 append_output_token_sig (void *cls,
   3871                          struct GNUNET_HashCode *h_issue,
   3872                          struct GNUNET_CRYPTO_BlindedSignature *sig)
   3873 {
   3874   struct PayContext *pc = cls;
   3875   struct TALER_MERCHANT_ContractChoice *choice;
   3876   const struct TALER_MERCHANT_ContractOutput *output;
   3877   struct SignedOutputToken out;
   3878   unsigned int cnt;
   3879 
   3880   GNUNET_assert (TALER_MERCHANT_CONTRACT_VERSION_1 ==
   3881                  pc->check_contract.contract_terms->version);
   3882   choice = &pc->check_contract.contract_terms->details.v1
   3883            .choices[pc->parse_wallet_data.choice_index];
   3884   output = &choice->outputs[pc->output_index_gen];
   3885   cnt = count_output_tokens (pc,
   3886                              output);
   3887   out.output_index = pc->output_index_gen;
   3888   out.h_issue.hash = *h_issue;
   3889   out.sig.signature = sig;
   3890   GNUNET_CRYPTO_blind_sig_incref (sig);
   3891   GNUNET_array_append (pc->output_tokens,
   3892                        pc->output_tokens_len,
   3893                        out);
   3894   /* Go to next output once we've output all tokens for the current one. */
   3895   pc->output_token_cnt++;
   3896   if (pc->output_token_cnt >= cnt)
   3897   {
   3898     pc->output_token_cnt = 0;
   3899     pc->output_index_gen++;
   3900   }
   3901 }
   3902 
   3903 
   3904 /**
   3905  * Handle case where contract was already paid. Either decides
   3906  * the payment is idempotent, or refunds the excess payment.
   3907  *
   3908  * @param[in,out] pc context we use to handle the payment
   3909  */
   3910 static void
   3911 phase_contract_paid (struct PayContext *pc)
   3912 {
   3913   json_t *refunds;
   3914   bool unmatched = false;
   3915 
   3916   {
   3917     enum GNUNET_DB_QueryStatus qs;
   3918 
   3919     qs = TMH_db->lookup_deposits_by_order (TMH_db->cls,
   3920                                            pc->check_contract.order_serial,
   3921                                            &deposit_paid_check,
   3922                                            pc);
   3923     /* Since orders with choices can have a price of zero,
   3924        0 is also a valid query state */
   3925     if (qs < 0)
   3926     {
   3927       GNUNET_break (0);
   3928       pay_end (pc,
   3929                TALER_MHD_reply_with_error (
   3930                  pc->connection,
   3931                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   3932                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   3933                  "lookup_deposits_by_order"));
   3934       return;
   3935     }
   3936   }
   3937   for (size_t i = 0;
   3938        i<pc->parse_pay.coins_cnt && ! unmatched;
   3939        i++)
   3940   {
   3941     struct DepositConfirmation *dci = &pc->parse_pay.dc[i];
   3942 
   3943     if (! dci->matched_in_db)
   3944       unmatched = true;
   3945   }
   3946   /* Check if provided input tokens match token in the database */
   3947   {
   3948     enum GNUNET_DB_QueryStatus qs;
   3949 
   3950     /* FIXME-Optimization: Maybe use h_contract instead of order_serial here? */
   3951     qs = TMH_db->lookup_spent_tokens_by_order (TMH_db->cls,
   3952                                                pc->check_contract.order_serial,
   3953                                                &input_tokens_paid_check,
   3954                                                pc);
   3955 
   3956     if (qs < 0)
   3957     {
   3958       GNUNET_break (0);
   3959       pay_end (pc,
   3960                TALER_MHD_reply_with_error (
   3961                  pc->connection,
   3962                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   3963                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   3964                  "lookup_spent_tokens_by_order"));
   3965       return;
   3966     }
   3967   }
   3968   for (size_t i = 0; i<pc->parse_pay.tokens_cnt && ! unmatched; i++)
   3969   {
   3970     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   3971 
   3972     if (! tuc->found_in_db)
   3973       unmatched = true;
   3974   }
   3975 
   3976   /* In this part we are fetching token_sigs related output */
   3977   if (! unmatched)
   3978   {
   3979     /* Everything fine, idempotent request, generate response immediately */
   3980     enum GNUNET_DB_QueryStatus qs;
   3981 
   3982     pc->output_index_gen = 0;
   3983     qs = TMH_db->select_order_blinded_sigs (
   3984       TMH_db->cls,
   3985       pc->order_id,
   3986       &append_output_token_sig,
   3987       pc);
   3988     if (0 > qs)
   3989     {
   3990       GNUNET_break (0);
   3991       pay_end (pc,
   3992                TALER_MHD_reply_with_error (
   3993                  pc->connection,
   3994                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   3995                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   3996                  "select_order_blinded_sigs"));
   3997       return;
   3998     }
   3999 
   4000     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4001                 "Idempotent pay request for order `%s', signing again\n",
   4002                 pc->order_id);
   4003     pc->phase = PP_SUCCESS_RESPONSE;
   4004     return;
   4005   }
   4006   /* Conflict, double-payment detected! */
   4007   /* FIXME-#8674: What should we do with input tokens?
   4008      Currently there is no refund for tokens. */
   4009   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4010               "Client attempted to pay extra for already paid order `%s'\n",
   4011               pc->order_id);
   4012   refunds = json_array ();
   4013   GNUNET_assert (NULL != refunds);
   4014   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   4015   {
   4016     struct DepositConfirmation *dci = &pc->parse_pay.dc[i];
   4017     struct TALER_MerchantSignatureP merchant_sig;
   4018 
   4019     if (dci->matched_in_db)
   4020       continue;
   4021     TALER_merchant_refund_sign (&dci->cdd.coin_pub,
   4022                                 &pc->check_contract.h_contract_terms,
   4023                                 0, /* rtransaction id */
   4024                                 &dci->cdd.amount,
   4025                                 &pc->hc->instance->merchant_priv,
   4026                                 &merchant_sig);
   4027     GNUNET_assert (
   4028       0 ==
   4029       json_array_append_new (
   4030         refunds,
   4031         GNUNET_JSON_PACK (
   4032           GNUNET_JSON_pack_data_auto (
   4033             "coin_pub",
   4034             &dci->cdd.coin_pub),
   4035           GNUNET_JSON_pack_data_auto (
   4036             "merchant_sig",
   4037             &merchant_sig),
   4038           TALER_JSON_pack_amount ("amount",
   4039                                   &dci->cdd.amount),
   4040           GNUNET_JSON_pack_uint64 ("rtransaction_id",
   4041                                    0))));
   4042   }
   4043   pay_end (pc,
   4044            TALER_MHD_REPLY_JSON_PACK (
   4045              pc->connection,
   4046              MHD_HTTP_CONFLICT,
   4047              TALER_MHD_PACK_EC (
   4048                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID),
   4049              GNUNET_JSON_pack_array_steal ("refunds",
   4050                                            refunds)));
   4051 }
   4052 
   4053 
   4054 /**
   4055  * Check the database state for the given order.
   4056  * Schedules an error response in the connection on failure.
   4057  *
   4058  * @param[in,out] pc context we use to handle the payment
   4059  */
   4060 static void
   4061 phase_check_contract (struct PayContext *pc)
   4062 {
   4063   /* obtain contract terms */
   4064   enum GNUNET_DB_QueryStatus qs;
   4065   bool paid = false;
   4066 
   4067   if (NULL != pc->check_contract.contract_terms_json)
   4068   {
   4069     json_decref (pc->check_contract.contract_terms_json);
   4070     pc->check_contract.contract_terms_json = NULL;
   4071   }
   4072   if (NULL != pc->check_contract.contract_terms)
   4073   {
   4074     TALER_MERCHANT_contract_free (pc->check_contract.contract_terms);
   4075     pc->check_contract.contract_terms = NULL;
   4076   }
   4077   qs = TMH_db->lookup_contract_terms2 (TMH_db->cls,
   4078                                        pc->hc->instance->settings.id,
   4079                                        pc->order_id,
   4080                                        &pc->check_contract.contract_terms_json,
   4081                                        &pc->check_contract.order_serial,
   4082                                        &paid,
   4083                                        NULL,
   4084                                        &pc->check_contract.pos_key,
   4085                                        &pc->check_contract.pos_alg);
   4086   if (0 > qs)
   4087   {
   4088     /* single, read-only SQL statements should never cause
   4089        serialization problems */
   4090     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
   4091     /* Always report on hard error to enable diagnostics */
   4092     GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   4093     pay_end (pc,
   4094              TALER_MHD_reply_with_error (
   4095                pc->connection,
   4096                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4097                TALER_EC_GENERIC_DB_FETCH_FAILED,
   4098                "contract terms"));
   4099     return;
   4100   }
   4101   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   4102   {
   4103     pay_end (pc,
   4104              TALER_MHD_reply_with_error (
   4105                pc->connection,
   4106                MHD_HTTP_NOT_FOUND,
   4107                TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN,
   4108                pc->order_id));
   4109     return;
   4110   }
   4111   /* hash contract (needed later) */
   4112 #if DEBUG
   4113   json_dumpf (pc->check_contract.contract_terms_json,
   4114               stderr,
   4115               JSON_INDENT (2));
   4116 #endif
   4117   if (GNUNET_OK !=
   4118       TALER_JSON_contract_hash (pc->check_contract.contract_terms_json,
   4119                                 &pc->check_contract.h_contract_terms))
   4120   {
   4121     GNUNET_break (0);
   4122     pay_end (pc,
   4123              TALER_MHD_reply_with_error (
   4124                pc->connection,
   4125                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4126                TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH,
   4127                NULL));
   4128     return;
   4129   }
   4130 
   4131   /* Parse the contract terms even for paid orders,
   4132      as later phases need it. */
   4133 
   4134   pc->check_contract.contract_terms = TALER_MERCHANT_contract_parse (
   4135     pc->check_contract.contract_terms_json,
   4136     true);
   4137 
   4138   if (NULL == pc->check_contract.contract_terms)
   4139   {
   4140     /* invalid contract */
   4141     GNUNET_break (0);
   4142     pay_end (pc,
   4143              TALER_MHD_reply_with_error (
   4144                pc->connection,
   4145                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4146                TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID,
   4147                pc->order_id));
   4148     return;
   4149   }
   4150 
   4151   if (paid)
   4152   {
   4153     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4154                 "Order `%s' paid, checking for double-payment\n",
   4155                 pc->order_id);
   4156     pc->phase = PP_CONTRACT_PAID;
   4157     return;
   4158   }
   4159   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4160               "Handling payment for order `%s' with contract hash `%s'\n",
   4161               pc->order_id,
   4162               GNUNET_h2s (&pc->check_contract.h_contract_terms.hash));
   4163 
   4164   /* Check fundamentals */
   4165   {
   4166     switch (pc->check_contract.contract_terms->version)
   4167     {
   4168     case TALER_MERCHANT_CONTRACT_VERSION_0:
   4169       {
   4170         if (pc->parse_wallet_data.choice_index > 0)
   4171         {
   4172           GNUNET_break (0);
   4173           pay_end (pc,
   4174                    TALER_MHD_reply_with_error (
   4175                      pc->connection,
   4176                      MHD_HTTP_BAD_REQUEST,
   4177                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS,
   4178                      "contract terms v0 has no choices"));
   4179           return;
   4180         }
   4181       }
   4182       break;
   4183     case TALER_MERCHANT_CONTRACT_VERSION_1:
   4184       {
   4185         if (pc->parse_wallet_data.choice_index < 0)
   4186         {
   4187           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4188                       "Order `%s' has non-empty choices array but"
   4189                       "request is missing 'choice_index' field\n",
   4190                       pc->order_id);
   4191           GNUNET_break (0);
   4192           pay_end (pc,
   4193                    TALER_MHD_reply_with_error (
   4194                      pc->connection,
   4195                      MHD_HTTP_BAD_REQUEST,
   4196                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISSING,
   4197                      NULL));
   4198           return;
   4199         }
   4200         if (pc->parse_wallet_data.choice_index >=
   4201             pc->check_contract.contract_terms->details.v1.choices_len)
   4202         {
   4203           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4204                       "Order `%s' has choices array with %u elements but "
   4205                       "request has 'choice_index' field with value %d\n",
   4206                       pc->order_id,
   4207                       pc->check_contract.contract_terms->details.v1.choices_len,
   4208                       pc->parse_wallet_data.choice_index);
   4209           GNUNET_break (0);
   4210           pay_end (pc,
   4211                    TALER_MHD_reply_with_error (
   4212                      pc->connection,
   4213                      MHD_HTTP_BAD_REQUEST,
   4214                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS,
   4215                      NULL));
   4216           return;
   4217         }
   4218       }
   4219       break;
   4220     default:
   4221       GNUNET_break (0);
   4222       pay_end (pc,
   4223                TALER_MHD_reply_with_error (
   4224                  pc->connection,
   4225                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4226                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   4227                  "contract 'version' in database not supported by this backend")
   4228                );
   4229       return;
   4230     }
   4231   }
   4232 
   4233   if (GNUNET_TIME_timestamp_cmp (pc->check_contract.contract_terms->
   4234                                  wire_deadline,
   4235                                  <,
   4236                                  pc->check_contract.contract_terms->
   4237                                  refund_deadline))
   4238   {
   4239     /* This should already have been checked when creating the order! */
   4240     GNUNET_break (0);
   4241     pay_end (pc,
   4242              TALER_MHD_reply_with_error (
   4243                pc->connection,
   4244                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4245                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE,
   4246                NULL));
   4247     return;
   4248   }
   4249   if (GNUNET_TIME_absolute_is_past (pc->check_contract.contract_terms->
   4250                                     pay_deadline.abs_time))
   4251   {
   4252     /* too late */
   4253     pay_end (pc,
   4254              TALER_MHD_reply_with_error (
   4255                pc->connection,
   4256                MHD_HTTP_GONE,
   4257                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED,
   4258                NULL));
   4259     return;
   4260   }
   4261 
   4262 /* Make sure wire method (still) exists for this instance */
   4263   {
   4264     struct TMH_WireMethod *wm;
   4265 
   4266     wm = pc->hc->instance->wm_head;
   4267     while (0 != GNUNET_memcmp (&pc->check_contract.contract_terms->h_wire,
   4268                                &wm->h_wire))
   4269       wm = wm->next;
   4270     if (NULL == wm)
   4271     {
   4272       GNUNET_break (0);
   4273       pay_end (pc,
   4274                TALER_MHD_reply_with_error (
   4275                  pc->connection,
   4276                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4277                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_HASH_UNKNOWN,
   4278                  NULL));
   4279       return;
   4280     }
   4281     pc->check_contract.wm = wm;
   4282   }
   4283   pc->phase = PP_VALIDATE_TOKENS;
   4284 }
   4285 
   4286 
   4287 /**
   4288  * Try to parse the wallet_data object of the pay request into
   4289  * the given context. Schedules an error response in the connection
   4290  * on failure.
   4291  *
   4292  * @param[in,out] pc context we use to handle the payment
   4293  */
   4294 static void
   4295 phase_parse_wallet_data (struct PayContext *pc)
   4296 {
   4297   const json_t *tokens_evs;
   4298   const json_t *donau_obj;
   4299 
   4300   struct GNUNET_JSON_Specification spec[] = {
   4301     GNUNET_JSON_spec_mark_optional (
   4302       GNUNET_JSON_spec_int16 ("choice_index",
   4303                               &pc->parse_wallet_data.choice_index),
   4304       NULL),
   4305     GNUNET_JSON_spec_mark_optional (
   4306       GNUNET_JSON_spec_array_const ("tokens_evs",
   4307                                     &tokens_evs),
   4308       NULL),
   4309     GNUNET_JSON_spec_mark_optional (
   4310       GNUNET_JSON_spec_object_const ("donau",
   4311                                      &donau_obj),
   4312       NULL),
   4313     GNUNET_JSON_spec_end ()
   4314   };
   4315 
   4316   pc->parse_wallet_data.choice_index = -1;
   4317   if (NULL == pc->parse_pay.wallet_data)
   4318   {
   4319     pc->phase = PP_CHECK_CONTRACT;
   4320     return;
   4321   }
   4322   {
   4323     enum GNUNET_GenericReturnValue res;
   4324 
   4325     res = TALER_MHD_parse_json_data (pc->connection,
   4326                                      pc->parse_pay.wallet_data,
   4327                                      spec);
   4328     if (GNUNET_YES != res)
   4329     {
   4330       GNUNET_break_op (0);
   4331       pay_end (pc,
   4332                (GNUNET_NO == res)
   4333              ? MHD_YES
   4334              : MHD_NO);
   4335       return;
   4336     }
   4337   }
   4338 
   4339   pc->parse_wallet_data.token_envelopes_cnt
   4340     = json_array_size (tokens_evs);
   4341   if (pc->parse_wallet_data.token_envelopes_cnt >
   4342       MAX_TOKEN_ALLOWED_OUTPUTs)
   4343   {
   4344     GNUNET_break_op (0);
   4345     pay_end (pc,
   4346              TALER_MHD_reply_with_error (
   4347                pc->connection,
   4348                MHD_HTTP_BAD_REQUEST,
   4349                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4350                "'tokens_evs' array too long"));
   4351     return;
   4352   }
   4353   pc->parse_wallet_data.token_envelopes
   4354     = GNUNET_new_array (pc->parse_wallet_data.token_envelopes_cnt,
   4355                         struct TokenEnvelope);
   4356 
   4357   {
   4358     unsigned int tokens_ev_index;
   4359     json_t *token_ev;
   4360 
   4361     json_array_foreach (tokens_evs,
   4362                         tokens_ev_index,
   4363                         token_ev)
   4364     {
   4365       struct TokenEnvelope *ev
   4366         = &pc->parse_wallet_data.token_envelopes[tokens_ev_index];
   4367       struct GNUNET_JSON_Specification ispec[] = {
   4368         TALER_JSON_spec_token_envelope (NULL,
   4369                                         &ev->blinded_token),
   4370         GNUNET_JSON_spec_end ()
   4371       };
   4372       enum GNUNET_GenericReturnValue res;
   4373 
   4374       if (json_is_null (token_ev))
   4375         continue;
   4376       res = TALER_MHD_parse_json_data (pc->connection,
   4377                                        token_ev,
   4378                                        ispec);
   4379       if (GNUNET_YES != res)
   4380       {
   4381         GNUNET_break_op (0);
   4382         pay_end (pc,
   4383                  (GNUNET_NO == res)
   4384                  ? MHD_YES
   4385                  : MHD_NO);
   4386         return;
   4387       }
   4388 
   4389       for (unsigned int j = 0; j<tokens_ev_index; j++)
   4390       {
   4391         if (0 ==
   4392             GNUNET_memcmp (ev->blinded_token.blinded_pub,
   4393                            pc->parse_wallet_data.token_envelopes[j].
   4394                            blinded_token.blinded_pub))
   4395         {
   4396           GNUNET_break_op (0);
   4397           pay_end (pc,
   4398                    TALER_MHD_reply_with_error (
   4399                      pc->connection,
   4400                      MHD_HTTP_BAD_REQUEST,
   4401                      TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4402                      "duplicate token envelope in list"));
   4403           return;
   4404         }
   4405       }
   4406     }
   4407   }
   4408 
   4409 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   4410   if (NULL != donau_obj)
   4411   {
   4412     const char *donau_url_tmp;
   4413     const json_t *budikeypairs;
   4414     json_t *donau_keys_json;
   4415 
   4416     /* Fetching and checking that all 3 are present in some way */
   4417     struct GNUNET_JSON_Specification dspec[] = {
   4418       GNUNET_JSON_spec_string      ("url",
   4419                                     &donau_url_tmp),
   4420       GNUNET_JSON_spec_uint64      ("year",
   4421                                     &pc->parse_wallet_data.donau.donation_year),
   4422       GNUNET_JSON_spec_array_const ("budikeypairs",
   4423                                     &budikeypairs),
   4424       GNUNET_JSON_spec_end ()
   4425     };
   4426     enum GNUNET_GenericReturnValue res;
   4427 
   4428     res = TALER_MHD_parse_json_data (pc->connection,
   4429                                      donau_obj,
   4430                                      dspec);
   4431     if (GNUNET_YES != res)
   4432     {
   4433       GNUNET_break_op (0);
   4434       pay_end (pc,
   4435                (GNUNET_NO == res)
   4436                ? MHD_YES
   4437                : MHD_NO);
   4438       return;
   4439     }
   4440 
   4441     /* Check if the needed data is present for the given donau URL */
   4442     {
   4443       enum GNUNET_DB_QueryStatus qs;
   4444 
   4445       qs = TMH_db->lookup_order_charity (
   4446         TMH_db->cls,
   4447         pc->hc->instance->settings.id,
   4448         donau_url_tmp,
   4449         &pc->parse_wallet_data.charity_id,
   4450         &pc->parse_wallet_data.charity_priv,
   4451         &pc->parse_wallet_data.charity_max_per_year,
   4452         &pc->parse_wallet_data.charity_receipts_to_date,
   4453         &donau_keys_json,
   4454         &pc->parse_wallet_data.donau_instance_serial);
   4455 
   4456       switch (qs)
   4457       {
   4458       case GNUNET_DB_STATUS_HARD_ERROR:
   4459       case GNUNET_DB_STATUS_SOFT_ERROR:
   4460         TMH_db->rollback (TMH_db->cls);
   4461         pay_end (pc,
   4462                  TALER_MHD_reply_with_error (
   4463                    pc->connection,
   4464                    MHD_HTTP_INTERNAL_SERVER_ERROR,
   4465                    TALER_EC_GENERIC_DB_FETCH_FAILED,
   4466                    "lookup_order_charity"));
   4467         return;
   4468       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   4469         TMH_db->rollback (TMH_db->cls);
   4470         pay_end (pc,
   4471                  TALER_MHD_reply_with_error (
   4472                    pc->connection,
   4473                    MHD_HTTP_NOT_FOUND,
   4474                    TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4475                    "No matching Donau charity found for the given URL"));
   4476         return;
   4477       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   4478         pc->parse_wallet_data.donau.donau_url =
   4479           GNUNET_strdup (donau_url_tmp);
   4480         break;
   4481       }
   4482     }
   4483 
   4484     {
   4485       pc->parse_wallet_data.donau_keys =
   4486         DONAU_keys_from_json (donau_keys_json);
   4487       json_decref (donau_keys_json);
   4488       if (NULL == pc->parse_wallet_data.donau_keys)
   4489       {
   4490         GNUNET_break_op (0);
   4491         pay_end (pc,
   4492                  TALER_MHD_reply_with_error (pc->connection,
   4493                                              MHD_HTTP_BAD_REQUEST,
   4494                                              TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4495                                              "Invalid donau_keys"));
   4496         return;
   4497       }
   4498     }
   4499 
   4500     /* Stage to parse the budikeypairs from json to struct */
   4501     if (0 != json_array_size (budikeypairs))
   4502     {
   4503       size_t num_bkps = json_array_size (budikeypairs);
   4504       struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps =
   4505         GNUNET_new_array (num_bkps,
   4506                           struct DONAU_BlindedUniqueDonorIdentifierKeyPair);
   4507 
   4508       /* Change to json for each*/
   4509       for (size_t i = 0; i < num_bkps; i++)
   4510       {
   4511         const json_t *bkp_obj = json_array_get (budikeypairs,
   4512                                                 i);
   4513         if (GNUNET_SYSERR ==
   4514             merchant_parse_json_bkp (&bkps[i],
   4515                                      bkp_obj))
   4516         {
   4517           GNUNET_break_op (0);
   4518           for (size_t j = 0; i < j; j++)
   4519             GNUNET_CRYPTO_blinded_message_decref (
   4520               bkps[j].blinded_udi.blinded_message);
   4521           GNUNET_free (bkps);
   4522           pay_end (pc,
   4523                    TALER_MHD_reply_with_error (pc->connection,
   4524                                                MHD_HTTP_BAD_REQUEST,
   4525                                                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4526                                                "Failed to parse budikeypairs"));
   4527           return;
   4528         }
   4529       }
   4530 
   4531       pc->parse_wallet_data.num_bkps = num_bkps;
   4532       pc->parse_wallet_data.bkps = bkps;
   4533     }
   4534   }
   4535 #else
   4536   /* Donau not compiled in: reject request if a donau object was given. */
   4537   if (NULL != donau_obj)
   4538   {
   4539     pay_end (pc,
   4540              TALER_MHD_reply_with_error (pc->connection,
   4541                                          MHD_HTTP_NOT_IMPLEMENTED,
   4542                                          TALER_EC_MERCHANT_GENERIC_DONAU_NOT_CONFIGURED,
   4543                                          "donau support disabled"));
   4544     return;
   4545   }
   4546 #endif /* HAVE_DONAU_DONAU_SERVICE_H */
   4547 
   4548   TALER_json_hash (pc->parse_pay.wallet_data,
   4549                    &pc->parse_wallet_data.h_wallet_data);
   4550 
   4551   pc->phase = PP_CHECK_CONTRACT;
   4552 }
   4553 
   4554 
   4555 /**
   4556  * Try to parse the pay request into the given pay context.
   4557  * Schedules an error response in the connection on failure.
   4558  *
   4559  * @param[in,out] pc context we use to handle the payment
   4560  */
   4561 static void
   4562 phase_parse_pay (struct PayContext *pc)
   4563 {
   4564   const char *session_id = NULL;
   4565   const json_t *coins;
   4566   const json_t *tokens;
   4567   struct GNUNET_JSON_Specification spec[] = {
   4568     GNUNET_JSON_spec_array_const ("coins",
   4569                                   &coins),
   4570     GNUNET_JSON_spec_mark_optional (
   4571       GNUNET_JSON_spec_string ("session_id",
   4572                                &session_id),
   4573       NULL),
   4574     GNUNET_JSON_spec_mark_optional (
   4575       GNUNET_JSON_spec_object_const ("wallet_data",
   4576                                      &pc->parse_pay.wallet_data),
   4577       NULL),
   4578     GNUNET_JSON_spec_mark_optional (
   4579       GNUNET_JSON_spec_array_const ("tokens",
   4580                                     &tokens),
   4581       NULL),
   4582     GNUNET_JSON_spec_end ()
   4583   };
   4584 
   4585 #if DEBUG
   4586   {
   4587     char *dump = json_dumps (pc->hc->request_body,
   4588                              JSON_INDENT (2)
   4589                              | JSON_ENCODE_ANY
   4590                              | JSON_SORT_KEYS);
   4591 
   4592     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4593                 "POST /orders/%s/pay – request body follows:\n%s\n",
   4594                 pc->order_id,
   4595                 dump);
   4596 
   4597     free (dump);
   4598 
   4599   }
   4600 #endif /* DEBUG */
   4601 
   4602   GNUNET_assert (PP_PARSE_PAY == pc->phase);
   4603   {
   4604     enum GNUNET_GenericReturnValue res;
   4605 
   4606     res = TALER_MHD_parse_json_data (pc->connection,
   4607                                      pc->hc->request_body,
   4608                                      spec);
   4609     if (GNUNET_YES != res)
   4610     {
   4611       GNUNET_break_op (0);
   4612       pay_end (pc,
   4613                (GNUNET_NO == res)
   4614                ? MHD_YES
   4615                : MHD_NO);
   4616       return;
   4617     }
   4618   }
   4619 
   4620   /* copy session ID (if set) */
   4621   if (NULL != session_id)
   4622   {
   4623     pc->parse_pay.session_id = GNUNET_strdup (session_id);
   4624   }
   4625   else
   4626   {
   4627     /* use empty string as default if client didn't specify it */
   4628     pc->parse_pay.session_id = GNUNET_strdup ("");
   4629   }
   4630 
   4631   pc->parse_pay.coins_cnt = json_array_size (coins);
   4632   if (pc->parse_pay.coins_cnt > MAX_COIN_ALLOWED_COINS)
   4633   {
   4634     GNUNET_break_op (0);
   4635     pay_end (pc,
   4636              TALER_MHD_reply_with_error (
   4637                pc->connection,
   4638                MHD_HTTP_BAD_REQUEST,
   4639                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4640                "'coins' array too long"));
   4641     return;
   4642   }
   4643   /* note: 1 coin = 1 deposit confirmation expected */
   4644   pc->parse_pay.dc = GNUNET_new_array (pc->parse_pay.coins_cnt,
   4645                                        struct DepositConfirmation);
   4646 
   4647   /* This loop populates the array 'dc' in 'pc' */
   4648   {
   4649     unsigned int coins_index;
   4650     json_t *coin;
   4651 
   4652     json_array_foreach (coins, coins_index, coin)
   4653     {
   4654       struct DepositConfirmation *dc = &pc->parse_pay.dc[coins_index];
   4655       const char *exchange_url;
   4656       struct GNUNET_JSON_Specification ispec[] = {
   4657         GNUNET_JSON_spec_fixed_auto ("coin_sig",
   4658                                      &dc->cdd.coin_sig),
   4659         GNUNET_JSON_spec_fixed_auto ("coin_pub",
   4660                                      &dc->cdd.coin_pub),
   4661         TALER_JSON_spec_denom_sig ("ub_sig",
   4662                                    &dc->cdd.denom_sig),
   4663         GNUNET_JSON_spec_fixed_auto ("h_denom",
   4664                                      &dc->cdd.h_denom_pub),
   4665         TALER_JSON_spec_amount_any ("contribution",
   4666                                     &dc->cdd.amount),
   4667         TALER_JSON_spec_web_url ("exchange_url",
   4668                                  &exchange_url),
   4669         /* if a minimum age was required, the minimum_age_sig and
   4670          * age_commitment must be provided */
   4671         GNUNET_JSON_spec_mark_optional (
   4672           GNUNET_JSON_spec_fixed_auto ("minimum_age_sig",
   4673                                        &dc->minimum_age_sig),
   4674           &dc->no_minimum_age_sig),
   4675         GNUNET_JSON_spec_mark_optional (
   4676           TALER_JSON_spec_age_commitment ("age_commitment",
   4677                                           &dc->age_commitment),
   4678           &dc->no_age_commitment),
   4679         /* if minimum age was not required, but coin with age restriction set
   4680          * was used, h_age_commitment must be provided. */
   4681         GNUNET_JSON_spec_mark_optional (
   4682           GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
   4683                                        &dc->cdd.h_age_commitment),
   4684           &dc->no_h_age_commitment),
   4685         GNUNET_JSON_spec_end ()
   4686       };
   4687       enum GNUNET_GenericReturnValue res;
   4688       struct ExchangeGroup *eg = NULL;
   4689 
   4690       res = TALER_MHD_parse_json_data (pc->connection,
   4691                                        coin,
   4692                                        ispec);
   4693       if (GNUNET_YES != res)
   4694       {
   4695         GNUNET_break_op (0);
   4696         pay_end (pc,
   4697                  (GNUNET_NO == res)
   4698                  ? MHD_YES
   4699                  : MHD_NO);
   4700         return;
   4701       }
   4702       for (unsigned int j = 0; j<coins_index; j++)
   4703       {
   4704         if (0 ==
   4705             GNUNET_memcmp (&dc->cdd.coin_pub,
   4706                            &pc->parse_pay.dc[j].cdd.coin_pub))
   4707         {
   4708           GNUNET_break_op (0);
   4709           pay_end (pc,
   4710                    TALER_MHD_reply_with_error (pc->connection,
   4711                                                MHD_HTTP_BAD_REQUEST,
   4712                                                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4713                                                "duplicate coin in list"));
   4714           return;
   4715         }
   4716       }
   4717 
   4718       dc->exchange_url = GNUNET_strdup (exchange_url);
   4719       dc->index = coins_index;
   4720       dc->pc = pc;
   4721 
   4722       /* Check the consistency of the (potential) age restriction
   4723        * information. */
   4724       if (dc->no_age_commitment != dc->no_minimum_age_sig)
   4725       {
   4726         GNUNET_break_op (0);
   4727         pay_end (pc,
   4728                  TALER_MHD_reply_with_error (
   4729                    pc->connection,
   4730                    MHD_HTTP_BAD_REQUEST,
   4731                    TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4732                    "inconsistent: 'age_commitment' vs. 'minimum_age_sig'"
   4733                    ));
   4734         return;
   4735       }
   4736 
   4737       /* Setup exchange group */
   4738       for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
   4739       {
   4740         if (0 ==
   4741             strcmp (pc->parse_pay.egs[i]->exchange_url,
   4742                     exchange_url))
   4743         {
   4744           eg = pc->parse_pay.egs[i];
   4745           break;
   4746         }
   4747       }
   4748       if (NULL == eg)
   4749       {
   4750         eg = GNUNET_new (struct ExchangeGroup);
   4751         eg->pc = pc;
   4752         eg->exchange_url = dc->exchange_url;
   4753         eg->total = dc->cdd.amount;
   4754         GNUNET_array_append (pc->parse_pay.egs,
   4755                              pc->parse_pay.num_exchanges,
   4756                              eg);
   4757       }
   4758       else
   4759       {
   4760         if (0 >
   4761             TALER_amount_add (&eg->total,
   4762                               &eg->total,
   4763                               &dc->cdd.amount))
   4764         {
   4765           GNUNET_break_op (0);
   4766           pay_end (pc,
   4767                    TALER_MHD_reply_with_error (
   4768                      pc->connection,
   4769                      MHD_HTTP_INTERNAL_SERVER_ERROR,
   4770                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   4771                      "Overflow adding up amounts"));
   4772           return;
   4773         }
   4774       }
   4775     }
   4776   }
   4777 
   4778   pc->parse_pay.tokens_cnt = json_array_size (tokens);
   4779   if (pc->parse_pay.tokens_cnt > MAX_TOKEN_ALLOWED_INPUTs)
   4780   {
   4781     GNUNET_break_op (0);
   4782     pay_end (pc,
   4783              TALER_MHD_reply_with_error (
   4784                pc->connection,
   4785                MHD_HTTP_BAD_REQUEST,
   4786                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4787                "'tokens' array too long"));
   4788     return;
   4789   }
   4790 
   4791   pc->parse_pay.tokens = GNUNET_new_array (pc->parse_pay.tokens_cnt,
   4792                                            struct TokenUseConfirmation);
   4793 
   4794   /* This look populates the array 'tokens' in 'pc' */
   4795   {
   4796     unsigned int tokens_index;
   4797     json_t *token;
   4798 
   4799     json_array_foreach (tokens, tokens_index, token)
   4800     {
   4801       struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[tokens_index];
   4802       struct GNUNET_JSON_Specification ispec[] = {
   4803         GNUNET_JSON_spec_fixed_auto ("token_sig",
   4804                                      &tuc->sig),
   4805         GNUNET_JSON_spec_fixed_auto ("token_pub",
   4806                                      &tuc->pub),
   4807         GNUNET_JSON_spec_fixed_auto ("h_issue",
   4808                                      &tuc->h_issue),
   4809         TALER_JSON_spec_token_issue_sig ("ub_sig",
   4810                                          &tuc->unblinded_sig),
   4811         GNUNET_JSON_spec_end ()
   4812       };
   4813       enum GNUNET_GenericReturnValue res;
   4814 
   4815       res = TALER_MHD_parse_json_data (pc->connection,
   4816                                        token,
   4817                                        ispec);
   4818       if (GNUNET_YES != res)
   4819       {
   4820         GNUNET_break_op (0);
   4821         pay_end (pc,
   4822                  (GNUNET_NO == res)
   4823                  ? MHD_YES
   4824                  : MHD_NO);
   4825         return;
   4826       }
   4827 
   4828       for (unsigned int j = 0; j<tokens_index; j++)
   4829       {
   4830         if (0 ==
   4831             GNUNET_memcmp (&tuc->pub,
   4832                            &pc->parse_pay.tokens[j].pub))
   4833         {
   4834           GNUNET_break_op (0);
   4835           pay_end (pc,
   4836                    TALER_MHD_reply_with_error (pc->connection,
   4837                                                MHD_HTTP_BAD_REQUEST,
   4838                                                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4839                                                "duplicate token in list"));
   4840           return;
   4841         }
   4842       }
   4843     }
   4844   }
   4845 
   4846   pc->phase = PP_PARSE_WALLET_DATA;
   4847 }
   4848 
   4849 
   4850 /**
   4851  * Custom cleanup routine for a `struct PayContext`.
   4852  *
   4853  * @param cls the `struct PayContext` to clean up.
   4854  */
   4855 static void
   4856 pay_context_cleanup (void *cls)
   4857 {
   4858   struct PayContext *pc = cls;
   4859 
   4860   if (NULL != pc->batch_deposits.timeout_task)
   4861   {
   4862     GNUNET_SCHEDULER_cancel (pc->batch_deposits.timeout_task);
   4863     pc->batch_deposits.timeout_task = NULL;
   4864   }
   4865   if (NULL != pc->check_contract.contract_terms_json)
   4866   {
   4867     json_decref (pc->check_contract.contract_terms_json);
   4868     pc->check_contract.contract_terms_json = NULL;
   4869   }
   4870   for (unsigned int i = 0; i<pc->parse_pay.coins_cnt; i++)
   4871   {
   4872     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   4873 
   4874     TALER_denom_sig_free (&dc->cdd.denom_sig);
   4875     GNUNET_free (dc->exchange_url);
   4876   }
   4877   GNUNET_free (pc->parse_pay.dc);
   4878   for (unsigned int i = 0; i<pc->parse_pay.tokens_cnt; i++)
   4879   {
   4880     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   4881 
   4882     TALER_token_issue_sig_free (&tuc->unblinded_sig);
   4883   }
   4884   GNUNET_free (pc->parse_pay.tokens);
   4885   for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
   4886   {
   4887     struct ExchangeGroup *eg = pc->parse_pay.egs[i];
   4888 
   4889     if (NULL != eg->fo)
   4890       TMH_EXCHANGES_keys4exchange_cancel (eg->fo);
   4891     GNUNET_free (eg);
   4892   }
   4893   GNUNET_free (pc->parse_pay.egs);
   4894   if (NULL != pc->check_contract.contract_terms)
   4895   {
   4896     TALER_MERCHANT_contract_free (pc->check_contract.contract_terms);
   4897     pc->check_contract.contract_terms = NULL;
   4898   }
   4899   if (NULL != pc->response)
   4900   {
   4901     MHD_destroy_response (pc->response);
   4902     pc->response = NULL;
   4903   }
   4904   GNUNET_free (pc->parse_pay.session_id);
   4905   GNUNET_CONTAINER_DLL_remove (pc_head,
   4906                                pc_tail,
   4907                                pc);
   4908   GNUNET_free (pc->check_contract.pos_key);
   4909 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   4910   if (NULL != pc->parse_wallet_data.bkps)
   4911   {
   4912     for (size_t i = 0; i < pc->parse_wallet_data.num_bkps; i++)
   4913       GNUNET_CRYPTO_blinded_message_decref (
   4914         pc->parse_wallet_data.bkps[i].blinded_udi.blinded_message);
   4915     GNUNET_array_grow (pc->parse_wallet_data.bkps,
   4916                        pc->parse_wallet_data.num_bkps,
   4917                        0);
   4918   }
   4919   if (NULL != pc->parse_wallet_data.donau_keys)
   4920   {
   4921     DONAU_keys_decref (pc->parse_wallet_data.donau_keys);
   4922     pc->parse_wallet_data.donau_keys = NULL;
   4923   }
   4924   GNUNET_free (pc->parse_wallet_data.donau.donau_url);
   4925 #endif
   4926   for (unsigned int i = 0; i<pc->parse_wallet_data.token_envelopes_cnt; i++)
   4927   {
   4928     struct TokenEnvelope *ev
   4929       = &pc->parse_wallet_data.token_envelopes[i];
   4930 
   4931     GNUNET_CRYPTO_blinded_message_decref (ev->blinded_token.blinded_pub);
   4932   }
   4933   GNUNET_free (pc->parse_wallet_data.token_envelopes);
   4934   if (NULL != pc->output_tokens)
   4935   {
   4936     for (unsigned int i = 0; i<pc->output_tokens_len; i++)
   4937       if (NULL != pc->output_tokens[i].sig.signature)
   4938         GNUNET_CRYPTO_blinded_sig_decref (pc->output_tokens[i].sig.signature);
   4939     GNUNET_free (pc->output_tokens);
   4940     pc->output_tokens = NULL;
   4941   }
   4942   GNUNET_free (pc);
   4943 }
   4944 
   4945 
   4946 MHD_RESULT
   4947 TMH_post_orders_ID_pay (const struct TMH_RequestHandler *rh,
   4948                         struct MHD_Connection *connection,
   4949                         struct TMH_HandlerContext *hc)
   4950 {
   4951   struct PayContext *pc = hc->ctx;
   4952 
   4953   GNUNET_assert (NULL != hc->infix);
   4954   if (NULL == pc)
   4955   {
   4956     pc = GNUNET_new (struct PayContext);
   4957     pc->connection = connection;
   4958     pc->hc = hc;
   4959     pc->order_id = hc->infix;
   4960     hc->ctx = pc;
   4961     hc->cc = &pay_context_cleanup;
   4962     GNUNET_CONTAINER_DLL_insert (pc_head,
   4963                                  pc_tail,
   4964                                  pc);
   4965   }
   4966   while (1)
   4967   {
   4968     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4969                 "Processing /pay in phase %d\n",
   4970                 (int) pc->phase);
   4971     switch (pc->phase)
   4972     {
   4973     case PP_PARSE_PAY:
   4974       phase_parse_pay (pc);
   4975       break;
   4976     case PP_PARSE_WALLET_DATA:
   4977       phase_parse_wallet_data (pc);
   4978       break;
   4979     case PP_CHECK_CONTRACT:
   4980       phase_check_contract (pc);
   4981       break;
   4982     case PP_VALIDATE_TOKENS:
   4983       phase_validate_tokens (pc);
   4984       break;
   4985     case PP_CONTRACT_PAID:
   4986       phase_contract_paid (pc);
   4987       break;
   4988     case PP_PAY_TRANSACTION:
   4989       phase_execute_pay_transaction (pc);
   4990       break;
   4991     case PP_REQUEST_DONATION_RECEIPT:
   4992 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   4993       phase_request_donation_receipt (pc);
   4994 #else
   4995       pc->phase++;
   4996 #endif
   4997       break;
   4998     case PP_FINAL_OUTPUT_TOKEN_PROCESSING:
   4999       phase_final_output_token_processing (pc);
   5000       break;
   5001     case PP_PAYMENT_NOTIFICATION:
   5002       phase_payment_notification (pc);
   5003       break;
   5004     case PP_SUCCESS_RESPONSE:
   5005       phase_success_response (pc);
   5006       break;
   5007     case PP_BATCH_DEPOSITS:
   5008       phase_batch_deposits (pc);
   5009       break;
   5010     case PP_RETURN_RESPONSE:
   5011       phase_return_response (pc);
   5012       break;
   5013     case PP_FAIL_LEGAL_REASONS:
   5014       phase_fail_for_legal_reasons (pc);
   5015       break;
   5016     case PP_END_YES:
   5017       return MHD_YES;
   5018     case PP_END_NO:
   5019       return MHD_NO;
   5020     default:
   5021       /* should not be reachable */
   5022       GNUNET_assert (0);
   5023       return MHD_NO;
   5024     }
   5025     switch (pc->suspended)
   5026     {
   5027     case GNUNET_SYSERR:
   5028       /* during shutdown, we don't generate any more replies */
   5029       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5030                   "Processing /pay ends due to shutdown in phase %d\n",
   5031                   (int) pc->phase);
   5032       return MHD_NO;
   5033     case GNUNET_NO:
   5034       /* continue to next phase */
   5035       break;
   5036     case GNUNET_YES:
   5037       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5038                   "Processing /pay suspended in phase %d\n",
   5039                   (int) pc->phase);
   5040       return MHD_YES;
   5041     }
   5042   }
   5043   /* impossible to get here */
   5044   GNUNET_assert (0);
   5045   return MHD_YES;
   5046 }
   5047 
   5048 
   5049 /* end of taler-merchant-httpd_post-orders-ID-pay.c */