merchant

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

taler-merchant-httpd_post-orders-ORDER_ID-pay.c (164600B)


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