merchant

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

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


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