merchant

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

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


      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   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1527               "Processing payment with keys from exchange %s\n",
   1528               eg->exchange_url);
   1529   GNUNET_assert (GNUNET_YES == pc->suspended);
   1530   if (NULL == keys)
   1531   {
   1532     GNUNET_break_op (0);
   1533     resume_pay_with_error (
   1534       pc,
   1535       TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT,
   1536       NULL);
   1537     return;
   1538   }
   1539   eg->keys = TALER_EXCHANGE_keys_incref (keys);
   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   GNUNET_assert (GNUNET_OK ==
   2395                  TALER_amount_set_zero (pc->parse_pay.dc[0].cdd.amount.currency,
   2396                                         &assigned));
   2397   GNUNET_assert (NULL != contract);
   2398   for (size_t i = 0; i<contract->products_len; i++)
   2399   {
   2400     const struct TALER_MERCHANT_ProductSold *product
   2401       = &contract->products[i];
   2402     const struct TALER_Amount *price = NULL;
   2403 
   2404     /* find price in the right currency */
   2405     for (unsigned int j = 0; j<product->prices_length; j++)
   2406     {
   2407       if (GNUNET_OK ==
   2408           TALER_amount_cmp_currency (&assigned,
   2409                                      &product->prices[j]))
   2410       {
   2411         price = &product->prices[j];
   2412         break;
   2413       }
   2414     }
   2415     if (NULL == price)
   2416     {
   2417       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2418                   "Product `%s' has no price given in `%s'.\n",
   2419                   product->product_id,
   2420                   assigned.currency);
   2421       continue;
   2422     }
   2423     if (0 != product->product_money_pot)
   2424     {
   2425       GNUNET_assert (0 <=
   2426                      TALER_amount_add (&assigned,
   2427                                        &assigned,
   2428                                        price));
   2429       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2430                   "Contributing to product money pot %llu increment of %s\n",
   2431                   (unsigned long long) product->product_money_pot,
   2432                   TALER_amount2s (price));
   2433       increment_pot (pc,
   2434                      product->product_money_pot,
   2435                      price);
   2436     }
   2437   }
   2438 
   2439   {
   2440     /* Compute what is left from the order total and account for that.
   2441        Also sanity-check and handle the case where the overall order
   2442        is below that of the sum of the products. */
   2443     struct TALER_Amount left;
   2444 
   2445     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2446                 "Order brutto is %s\n",
   2447                 TALER_amount2s (&pc->validate_tokens.brutto));
   2448     if (0 >
   2449         TALER_amount_subtract (&left,
   2450                                &pc->validate_tokens.brutto,
   2451                                &assigned))
   2452     {
   2453       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2454                   "Total order brutto amount below sum from products, skipping per-product money pots\n");
   2455       GNUNET_free (pc->compute_money_pots.pots);
   2456       GNUNET_free (pc->compute_money_pots.increments);
   2457       pc->compute_money_pots.num_pots = 0;
   2458       left = pc->validate_tokens.brutto;
   2459     }
   2460 
   2461     if ( (! TALER_amount_is_zero (&left)) &&
   2462          (0 != contract->default_money_pot) )
   2463     {
   2464       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2465                   "Computing money pot %llu increment as %s\n",
   2466                   (unsigned long long) contract->default_money_pot,
   2467                   TALER_amount2s (&left));
   2468       increment_pot (pc,
   2469                      contract->default_money_pot,
   2470                      &left);
   2471     }
   2472   }
   2473   pc->compute_money_pots.pots_computed = true;
   2474   pc->phase++;
   2475 }
   2476 
   2477 
   2478 /**
   2479  * Function called with information about a coin that was deposited.
   2480  *
   2481  * @param cls closure
   2482  * @param exchange_url exchange where @a coin_pub was deposited
   2483  * @param coin_pub public key of the coin
   2484  * @param amount_with_fee amount the exchange will deposit for this coin
   2485  * @param deposit_fee fee the exchange will charge for this coin
   2486  * @param refund_fee fee the exchange will charge for refunding this coin
   2487  */
   2488 static void
   2489 check_coin_paid (void *cls,
   2490                  const char *exchange_url,
   2491                  const struct TALER_CoinSpendPublicKeyP *coin_pub,
   2492                  const struct TALER_Amount *amount_with_fee,
   2493                  const struct TALER_Amount *deposit_fee,
   2494                  const struct TALER_Amount *refund_fee)
   2495 {
   2496   struct PayContext *pc = cls;
   2497 
   2498   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2499   {
   2500     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   2501 
   2502     if (dc->found_in_db)
   2503       continue; /* processed earlier, skip "expensive" memcmp() */
   2504     /* Get matching coin from results*/
   2505     if ( (0 != GNUNET_memcmp (coin_pub,
   2506                               &dc->cdd.coin_pub)) ||
   2507          (0 !=
   2508           strcmp (exchange_url,
   2509                   dc->exchange_url)) ||
   2510          (GNUNET_OK !=
   2511           TALER_amount_cmp_currency (amount_with_fee,
   2512                                      &dc->cdd.amount)) ||
   2513          (0 != TALER_amount_cmp (amount_with_fee,
   2514                                  &dc->cdd.amount)) )
   2515       continue; /* does not match, skip */
   2516     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2517                 "Deposit of coin `%s' already in our DB.\n",
   2518                 TALER_B2S (coin_pub));
   2519     if ( (GNUNET_OK !=
   2520           TALER_amount_cmp_currency (&pc->pay_transaction.total_paid,
   2521                                      amount_with_fee)) ||
   2522          (GNUNET_OK !=
   2523           TALER_amount_cmp_currency (&pc->pay_transaction.total_fees_paid,
   2524                                      deposit_fee)) )
   2525     {
   2526       GNUNET_break_op (0);
   2527       pc->pay_transaction.deposit_currency_mismatch = true;
   2528       break;
   2529     }
   2530     GNUNET_assert (0 <=
   2531                    TALER_amount_add (&pc->pay_transaction.total_paid,
   2532                                      &pc->pay_transaction.total_paid,
   2533                                      amount_with_fee));
   2534     GNUNET_assert (0 <=
   2535                    TALER_amount_add (&pc->pay_transaction.total_fees_paid,
   2536                                      &pc->pay_transaction.total_fees_paid,
   2537                                      deposit_fee));
   2538     dc->deposit_fee = *deposit_fee;
   2539     dc->refund_fee = *refund_fee;
   2540     dc->cdd.amount = *amount_with_fee;
   2541     dc->found_in_db = true;
   2542     pc->pay_transaction.pending--;
   2543   }
   2544 }
   2545 
   2546 
   2547 /**
   2548  * Function called with information about a refund.  Check if this coin was
   2549  * claimed by the wallet for the transaction, and if so add the refunded
   2550  * amount to the pc's "total_refunded" amount.
   2551  *
   2552  * @param cls closure with a `struct PayContext`
   2553  * @param coin_pub public coin from which the refund comes from
   2554  * @param refund_amount refund amount which is being taken from @a coin_pub
   2555  */
   2556 static void
   2557 check_coin_refunded (void *cls,
   2558                      const struct TALER_CoinSpendPublicKeyP *coin_pub,
   2559                      const struct TALER_Amount *refund_amount)
   2560 {
   2561   struct PayContext *pc = cls;
   2562 
   2563   /* We look at refunds here that apply to the coins
   2564      that the customer is currently trying to pay us with.
   2565 
   2566      Such refunds are not "normal" refunds, but abort-pay refunds, which are
   2567      given in the case that the wallet aborts the payment.
   2568      In the case the wallet then decides to complete the payment *after* doing
   2569      an abort-pay refund (an unusual but possible case), we need
   2570      to make sure that existing refunds are accounted for. */
   2571 
   2572   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2573   {
   2574     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   2575 
   2576     /* Get matching coins from results.  */
   2577     if (0 != GNUNET_memcmp (coin_pub,
   2578                             &dc->cdd.coin_pub))
   2579       continue;
   2580     if (GNUNET_OK !=
   2581         TALER_amount_cmp_currency (&pc->pay_transaction.total_refunded,
   2582                                    refund_amount))
   2583     {
   2584       GNUNET_break (0);
   2585       pc->pay_transaction.refund_currency_mismatch = true;
   2586       break;
   2587     }
   2588     GNUNET_assert (0 <=
   2589                    TALER_amount_add (&pc->pay_transaction.total_refunded,
   2590                                      &pc->pay_transaction.total_refunded,
   2591                                      refund_amount));
   2592     break;
   2593   }
   2594 }
   2595 
   2596 
   2597 /**
   2598  * Check whether the amount paid is sufficient to cover the price.
   2599  *
   2600  * @param pc payment context to check
   2601  * @return true if the payment is sufficient, false if it is
   2602  *         insufficient
   2603  */
   2604 static bool
   2605 check_payment_sufficient (struct PayContext *pc)
   2606 {
   2607   struct TALER_Amount acc_fee;
   2608   struct TALER_Amount acc_amount;
   2609   struct TALER_Amount final_amount;
   2610   struct TALER_Amount total_wire_fee;
   2611   struct TALER_Amount total_needed;
   2612 
   2613   if (0 == pc->parse_pay.coins_cnt)
   2614     return TALER_amount_is_zero (&pc->validate_tokens.brutto);
   2615   GNUNET_assert (GNUNET_OK ==
   2616                  TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2617                                         &total_wire_fee));
   2618   for (unsigned int i = 0; i < pc->parse_pay.num_exchanges; i++)
   2619   {
   2620     if (GNUNET_OK !=
   2621         TALER_amount_cmp_currency (&total_wire_fee,
   2622                                    &pc->parse_pay.egs[i]->wire_fee))
   2623     {
   2624       GNUNET_break_op (0);
   2625       pay_end (pc,
   2626                TALER_MHD_reply_with_error (pc->connection,
   2627                                            MHD_HTTP_BAD_REQUEST,
   2628                                            TALER_EC_GENERIC_CURRENCY_MISMATCH,
   2629                                            total_wire_fee.currency));
   2630       return false;
   2631     }
   2632     if (0 >
   2633         TALER_amount_add (&total_wire_fee,
   2634                           &total_wire_fee,
   2635                           &pc->parse_pay.egs[i]->wire_fee))
   2636     {
   2637       GNUNET_break (0);
   2638       pay_end (pc,
   2639                TALER_MHD_reply_with_error (
   2640                  pc->connection,
   2641                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   2642                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED,
   2643                  "could not add exchange wire fee to total"));
   2644       return false;
   2645     }
   2646   }
   2647 
   2648   /**
   2649    * This loops calculates what are the deposit fee / total
   2650    * amount with fee / and wire fee, for all the coins.
   2651    */
   2652   GNUNET_assert (GNUNET_OK ==
   2653                  TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2654                                         &acc_fee));
   2655   GNUNET_assert (GNUNET_OK ==
   2656                  TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2657                                         &acc_amount));
   2658   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2659   {
   2660     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   2661 
   2662     GNUNET_assert (dc->found_in_db);
   2663     if ( (GNUNET_OK !=
   2664           TALER_amount_cmp_currency (&acc_fee,
   2665                                      &dc->deposit_fee)) ||
   2666          (GNUNET_OK !=
   2667           TALER_amount_cmp_currency (&acc_amount,
   2668                                      &dc->cdd.amount)) )
   2669     {
   2670       GNUNET_break_op (0);
   2671       pay_end (pc,
   2672                TALER_MHD_reply_with_error (
   2673                  pc->connection,
   2674                  MHD_HTTP_BAD_REQUEST,
   2675                  TALER_EC_GENERIC_CURRENCY_MISMATCH,
   2676                  dc->deposit_fee.currency));
   2677       return false;
   2678     }
   2679     if ( (0 >
   2680           TALER_amount_add (&acc_fee,
   2681                             &dc->deposit_fee,
   2682                             &acc_fee)) ||
   2683          (0 >
   2684           TALER_amount_add (&acc_amount,
   2685                             &dc->cdd.amount,
   2686                             &acc_amount)) )
   2687     {
   2688       GNUNET_break (0);
   2689       /* Overflow in these amounts? Very strange. */
   2690       pay_end (pc,
   2691                TALER_MHD_reply_with_error (
   2692                  pc->connection,
   2693                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   2694                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   2695                  "Overflow adding up amounts"));
   2696       return false;
   2697     }
   2698     if (1 ==
   2699         TALER_amount_cmp (&dc->deposit_fee,
   2700                           &dc->cdd.amount))
   2701     {
   2702       GNUNET_break_op (0);
   2703       pay_end (pc,
   2704                TALER_MHD_reply_with_error (
   2705                  pc->connection,
   2706                  MHD_HTTP_BAD_REQUEST,
   2707                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_FEES_EXCEED_PAYMENT,
   2708                  "Deposit fees exceed coin's contribution"));
   2709       return false;
   2710     }
   2711   } /* end deposit loop */
   2712 
   2713   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2714               "Amount received from wallet: %s\n",
   2715               TALER_amount2s (&acc_amount));
   2716   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2717               "Deposit fee for all coins: %s\n",
   2718               TALER_amount2s (&acc_fee));
   2719   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2720               "Total wire fee: %s\n",
   2721               TALER_amount2s (&total_wire_fee));
   2722   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2723               "Deposit fee limit for merchant: %s\n",
   2724               TALER_amount2s (&pc->validate_tokens.max_fee));
   2725   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2726               "Total refunded amount: %s\n",
   2727               TALER_amount2s (&pc->pay_transaction.total_refunded));
   2728 
   2729   /* Now compare exchange wire fee compared to what we are willing to pay */
   2730   if (GNUNET_YES !=
   2731       TALER_amount_cmp_currency (&total_wire_fee,
   2732                                  &acc_fee))
   2733   {
   2734     GNUNET_break (0);
   2735     pay_end (pc,
   2736              TALER_MHD_reply_with_error (
   2737                pc->connection,
   2738                MHD_HTTP_BAD_REQUEST,
   2739                TALER_EC_GENERIC_CURRENCY_MISMATCH,
   2740                total_wire_fee.currency));
   2741     return false;
   2742   }
   2743 
   2744   /* add wire fee to the total fees */
   2745   if (0 >
   2746       TALER_amount_add (&acc_fee,
   2747                         &acc_fee,
   2748                         &total_wire_fee))
   2749   {
   2750     GNUNET_break (0);
   2751     pay_end (pc,
   2752              TALER_MHD_reply_with_error (
   2753                pc->connection,
   2754                MHD_HTTP_INTERNAL_SERVER_ERROR,
   2755                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   2756                "Overflow adding up amounts"));
   2757     return false;
   2758   }
   2759   if (-1 == TALER_amount_cmp (&pc->validate_tokens.max_fee,
   2760                               &acc_fee))
   2761   {
   2762     /**
   2763      * Sum of fees of *all* the different exchanges of all the coins are
   2764      * higher than the fixed limit that the merchant is willing to pay.  The
   2765      * difference must be paid by the customer.
   2766      */
   2767     struct TALER_Amount excess_fee;
   2768 
   2769     /* compute fee amount to be covered by customer */
   2770     GNUNET_assert (TALER_AAR_RESULT_POSITIVE ==
   2771                    TALER_amount_subtract (&excess_fee,
   2772                                           &acc_fee,
   2773                                           &pc->validate_tokens.max_fee));
   2774     /* add that to the total */
   2775     if (0 >
   2776         TALER_amount_add (&total_needed,
   2777                           &excess_fee,
   2778                           &pc->validate_tokens.brutto))
   2779     {
   2780       GNUNET_break (0);
   2781       pay_end (pc,
   2782                TALER_MHD_reply_with_error (
   2783                  pc->connection,
   2784                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   2785                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   2786                  "Overflow adding up amounts"));
   2787       return false;
   2788     }
   2789   }
   2790   else
   2791   {
   2792     /* Fees are fully covered by the merchant, all we require
   2793        is that the total payment is not below the contract's amount */
   2794     total_needed = pc->validate_tokens.brutto;
   2795   }
   2796 
   2797   /* Do not count refunds towards the payment */
   2798   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2799               "Subtracting total refunds from paid amount: %s\n",
   2800               TALER_amount2s (&pc->pay_transaction.total_refunded));
   2801   if (0 >
   2802       TALER_amount_subtract (&final_amount,
   2803                              &acc_amount,
   2804                              &pc->pay_transaction.total_refunded))
   2805   {
   2806     GNUNET_break (0);
   2807     pay_end (pc,
   2808              TALER_MHD_reply_with_error (
   2809                pc->connection,
   2810                MHD_HTTP_INTERNAL_SERVER_ERROR,
   2811                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDS_EXCEED_PAYMENTS,
   2812                "refunded amount exceeds total payments"));
   2813     return false;
   2814   }
   2815 
   2816   if (-1 == TALER_amount_cmp (&final_amount,
   2817                               &total_needed))
   2818   {
   2819     /* acc_amount < total_needed */
   2820     if (-1 < TALER_amount_cmp (&acc_amount,
   2821                                &total_needed))
   2822     {
   2823       GNUNET_break_op (0);
   2824       pay_end (pc,
   2825                TALER_MHD_reply_with_error (
   2826                  pc->connection,
   2827                  MHD_HTTP_PAYMENT_REQUIRED,
   2828                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDED,
   2829                  "contract not paid up due to refunds"));
   2830       return false;
   2831     }
   2832     if (-1 < TALER_amount_cmp (&acc_amount,
   2833                                &pc->validate_tokens.brutto))
   2834     {
   2835       GNUNET_break_op (0);
   2836       pay_end (pc,
   2837                TALER_MHD_reply_with_error (
   2838                  pc->connection,
   2839                  MHD_HTTP_BAD_REQUEST,
   2840                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_DUE_TO_FEES,
   2841                  "contract not paid up due to fees (client may have calculated them badly)"));
   2842       return false;
   2843     }
   2844     GNUNET_break_op (0);
   2845     pay_end (pc,
   2846              TALER_MHD_reply_with_error (
   2847                pc->connection,
   2848                MHD_HTTP_BAD_REQUEST,
   2849                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_PAYMENT_INSUFFICIENT,
   2850                "payment insufficient"));
   2851     return false;
   2852   }
   2853   return true;
   2854 }
   2855 
   2856 
   2857 /**
   2858  * Execute the DB transaction.  If required (from
   2859  * soft/serialization errors), the transaction can be
   2860  * restarted here.
   2861  *
   2862  * @param[in,out] pc payment context to transact
   2863  */
   2864 static void
   2865 phase_execute_pay_transaction (struct PayContext *pc)
   2866 {
   2867   struct TMH_HandlerContext *hc = pc->hc;
   2868   const char *instance_id = hc->instance->settings.id;
   2869 
   2870   if (pc->batch_deposits.got_451)
   2871   {
   2872     pc->phase = PP_FAIL_LEGAL_REASONS;
   2873     return;
   2874   }
   2875   /* Avoid re-trying transactions on soft errors forever! */
   2876   if (pc->pay_transaction.retry_counter++ > MAX_RETRIES)
   2877   {
   2878     GNUNET_break (0);
   2879     pay_end (pc,
   2880              TALER_MHD_reply_with_error (pc->connection,
   2881                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
   2882                                          TALER_EC_GENERIC_DB_SOFT_FAILURE,
   2883                                          NULL));
   2884     return;
   2885   }
   2886 
   2887   /* Initialize some amount accumulators
   2888      (used in check_coin_paid(), check_coin_refunded()
   2889      and check_payment_sufficient()). */
   2890   GNUNET_break (GNUNET_OK ==
   2891                 TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2892                                        &pc->pay_transaction.total_paid));
   2893   GNUNET_break (GNUNET_OK ==
   2894                 TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2895                                        &pc->pay_transaction.total_fees_paid));
   2896   GNUNET_break (GNUNET_OK ==
   2897                 TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2898                                        &pc->pay_transaction.total_refunded));
   2899   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2900     pc->parse_pay.dc[i].found_in_db = false;
   2901   pc->pay_transaction.pending = pc->parse_pay.coins_cnt;
   2902 
   2903   /* First, try to see if we have all we need already done */
   2904   TALER_MERCHANTDB_preflight (TMH_db);
   2905   if (GNUNET_OK !=
   2906       TALER_MERCHANTDB_start (TMH_db,
   2907                               "run pay"))
   2908   {
   2909     GNUNET_break (0);
   2910     pay_end (pc,
   2911              TALER_MHD_reply_with_error (pc->connection,
   2912                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
   2913                                          TALER_EC_GENERIC_DB_START_FAILED,
   2914                                          NULL));
   2915     return;
   2916   }
   2917 
   2918   for (size_t i = 0; i<pc->parse_pay.tokens_cnt; i++)
   2919   {
   2920     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   2921     enum GNUNET_DB_QueryStatus qs;
   2922 
   2923     /* Insert used token into database, the unique constraint will
   2924        case an error if this token was used before. */
   2925     qs = TALER_MERCHANTDB_insert_spent_token (TMH_db,
   2926                                               &pc->check_contract.h_contract_terms,
   2927                                               &tuc->h_issue,
   2928                                               &tuc->pub,
   2929                                               &tuc->sig,
   2930                                               &tuc->unblinded_sig);
   2931 
   2932     switch (qs)
   2933     {
   2934     case GNUNET_DB_STATUS_SOFT_ERROR:
   2935       TALER_MERCHANTDB_rollback (TMH_db);
   2936       return; /* do it again */
   2937     case GNUNET_DB_STATUS_HARD_ERROR:
   2938       /* Always report on hard error as well to enable diagnostics */
   2939       TALER_MERCHANTDB_rollback (TMH_db);
   2940       pay_end (pc,
   2941                TALER_MHD_reply_with_error (pc->connection,
   2942                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   2943                                            TALER_EC_GENERIC_DB_STORE_FAILED,
   2944                                            "insert used token"));
   2945       return;
   2946     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   2947       /* UNIQUE constraint violation, meaning this token was already used. */
   2948       TALER_MERCHANTDB_rollback (TMH_db);
   2949       pay_end (pc,
   2950                TALER_MHD_reply_with_error (pc->connection,
   2951                                            MHD_HTTP_CONFLICT,
   2952                                            TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_INVALID,
   2953                                            NULL));
   2954       return;
   2955     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   2956       /* Good, proceed! */
   2957       break;
   2958     }
   2959   } /* for all tokens */
   2960 
   2961   {
   2962     enum GNUNET_DB_QueryStatus qs;
   2963 
   2964     /* Check if some of these coins already succeeded for _this_ contract.  */
   2965     qs = TALER_MERCHANTDB_lookup_deposits (TMH_db,
   2966                                            instance_id,
   2967                                            &pc->check_contract.h_contract_terms,
   2968                                            &check_coin_paid,
   2969                                            pc);
   2970     if (0 > qs)
   2971     {
   2972       TALER_MERCHANTDB_rollback (TMH_db);
   2973       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   2974         return; /* do it again */
   2975       /* Always report on hard error as well to enable diagnostics */
   2976       GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   2977       pay_end (pc,
   2978                TALER_MHD_reply_with_error (pc->connection,
   2979                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   2980                                            TALER_EC_GENERIC_DB_FETCH_FAILED,
   2981                                            "lookup deposits"));
   2982       return;
   2983     }
   2984     if (pc->pay_transaction.deposit_currency_mismatch)
   2985     {
   2986       TALER_MERCHANTDB_rollback (TMH_db);
   2987       GNUNET_break_op (0);
   2988       pay_end (pc,
   2989                TALER_MHD_reply_with_error (
   2990                  pc->connection,
   2991                  MHD_HTTP_BAD_REQUEST,
   2992                  TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH,
   2993                  pc->validate_tokens.brutto.currency));
   2994       return;
   2995     }
   2996   }
   2997 
   2998   {
   2999     enum GNUNET_DB_QueryStatus qs;
   3000 
   3001     /* Check if we refunded some of the coins */
   3002     qs = TALER_MERCHANTDB_lookup_refunds (TMH_db,
   3003                                           instance_id,
   3004                                           &pc->check_contract.h_contract_terms,
   3005                                           &check_coin_refunded,
   3006                                           pc);
   3007     if (0 > qs)
   3008     {
   3009       TALER_MERCHANTDB_rollback (TMH_db);
   3010       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   3011         return; /* do it again */
   3012       /* Always report on hard error as well to enable diagnostics */
   3013       GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   3014       pay_end (pc,
   3015                TALER_MHD_reply_with_error (pc->connection,
   3016                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3017                                            TALER_EC_GENERIC_DB_FETCH_FAILED,
   3018                                            "lookup refunds"));
   3019       return;
   3020     }
   3021     if (pc->pay_transaction.refund_currency_mismatch)
   3022     {
   3023       TALER_MERCHANTDB_rollback (TMH_db);
   3024       pay_end (pc,
   3025                TALER_MHD_reply_with_error (pc->connection,
   3026                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3027                                            TALER_EC_GENERIC_DB_FETCH_FAILED,
   3028                                            "refund currency in database does not match order currency"));
   3029       return;
   3030     }
   3031   }
   3032 
   3033   /* Check if there are coins that still need to be processed */
   3034   if (0 != pc->pay_transaction.pending)
   3035   {
   3036     /* we made no DB changes, so we can just rollback */
   3037     TALER_MERCHANTDB_rollback (TMH_db);
   3038     /* Ok, we need to first go to the network to process more coins.
   3039        We that interaction in *tiny* transactions (hence the rollback
   3040        above). */
   3041     pc->phase = PP_BATCH_DEPOSITS;
   3042     return;
   3043   }
   3044 
   3045   /* 0 == pc->pay_transaction.pending: all coins processed, let's see if that was enough */
   3046   if (! check_payment_sufficient (pc))
   3047   {
   3048     /* check_payment_sufficient() will have queued an error already.
   3049        We need to still abort the transaction. */
   3050     TALER_MERCHANTDB_rollback (TMH_db);
   3051     return;
   3052   }
   3053   /* Payment succeeded, save in database */
   3054   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3055               "Order `%s' (%s) was fully paid\n",
   3056               pc->order_id,
   3057               GNUNET_h2s (&pc->check_contract.h_contract_terms.hash));
   3058   {
   3059     enum GNUNET_DB_QueryStatus qs;
   3060 
   3061     qs = TALER_MERCHANTDB_mark_contract_paid (TMH_db,
   3062                                               instance_id,
   3063                                               &pc->check_contract.h_contract_terms,
   3064                                               pc->parse_pay.session_id,
   3065                                               pc->parse_wallet_data.choice_index);
   3066     if (qs < 0)
   3067     {
   3068       TALER_MERCHANTDB_rollback (TMH_db);
   3069       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   3070         return; /* do it again */
   3071       GNUNET_break (0);
   3072       pay_end (pc,
   3073                TALER_MHD_reply_with_error (pc->connection,
   3074                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3075                                            TALER_EC_GENERIC_DB_STORE_FAILED,
   3076                                            "mark contract paid"));
   3077       return;
   3078     }
   3079     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3080                 "Marked contract paid returned %d\n",
   3081                 (int) qs);
   3082 
   3083     if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) &&
   3084          (0 < pc->compute_money_pots.num_pots) )
   3085     {
   3086       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3087                   "Incrementing %u money pots by %s\n",
   3088                   pc->compute_money_pots.num_pots,
   3089                   TALER_amount2s (&pc->compute_money_pots.increments[0]));
   3090       qs = TALER_MERCHANTDB_increment_money_pots (TMH_db,
   3091                                                   instance_id,
   3092                                                   pc->compute_money_pots.num_pots,
   3093                                                   pc->compute_money_pots.pots,
   3094                                                   pc->compute_money_pots.increments);
   3095       switch (qs)
   3096       {
   3097       case GNUNET_DB_STATUS_SOFT_ERROR:
   3098         TALER_MERCHANTDB_rollback (TMH_db);
   3099         return; /* do it again */
   3100       case GNUNET_DB_STATUS_HARD_ERROR:
   3101         /* Always report on hard error as well to enable diagnostics */
   3102         TALER_MERCHANTDB_rollback (TMH_db);
   3103         pay_end (pc,
   3104                  TALER_MHD_reply_with_error (pc->connection,
   3105                                              MHD_HTTP_INTERNAL_SERVER_ERROR,
   3106                                              TALER_EC_GENERIC_DB_STORE_FAILED,
   3107                                              "increment_money_pots"));
   3108         return;
   3109       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   3110         /* strange */
   3111         GNUNET_break (0);
   3112         break;
   3113       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   3114         /* Good, proceed! */
   3115         break;
   3116       }
   3117 
   3118     }
   3119 
   3120 
   3121   }
   3122 
   3123 
   3124   {
   3125     const struct TALER_MERCHANT_ContractChoice *choice =
   3126       &pc->check_contract.contract_terms->details.v1
   3127       .choices[pc->parse_wallet_data.choice_index];
   3128 
   3129     for (size_t i = 0; i<pc->output_tokens_len; i++)
   3130     {
   3131       unsigned int output_index;
   3132       enum TALER_MERCHANT_ContractOutputType type;
   3133 
   3134       output_index = pc->output_tokens[i].output_index;
   3135       GNUNET_assert (output_index < choice->outputs_len);
   3136       type = choice->outputs[output_index].type;
   3137 
   3138       switch (type)
   3139       {
   3140       case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   3141         /* Well, good luck getting here */
   3142         GNUNET_break (0);
   3143         pay_end (pc,
   3144                  TALER_MHD_reply_with_error (pc->connection,
   3145                                              MHD_HTTP_INTERNAL_SERVER_ERROR,
   3146                                              TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3147                                              "invalid output type"));
   3148         break;
   3149       case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   3150         /* We skip output tokens of donation receipts here, as they are handled in the
   3151          * phase_final_output_token_processing() callback from donau */
   3152         break;
   3153       case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   3154         struct SignedOutputToken *output =
   3155           &pc->output_tokens[i];
   3156         enum GNUNET_DB_QueryStatus qs;
   3157 
   3158         qs = TALER_MERCHANTDB_insert_issued_token (TMH_db,
   3159                                                    &pc->check_contract.h_contract_terms,
   3160                                                    &output->h_issue,
   3161                                                    &output->sig);
   3162         switch (qs)
   3163         {
   3164         case GNUNET_DB_STATUS_HARD_ERROR:
   3165           TALER_MERCHANTDB_rollback (TMH_db);
   3166           GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   3167           pay_end (pc,
   3168                    TALER_MHD_reply_with_error (pc->connection,
   3169                                                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3170                                                TALER_EC_GENERIC_DB_STORE_FAILED,
   3171                                                "insert output token"));
   3172           return;
   3173         case GNUNET_DB_STATUS_SOFT_ERROR:
   3174           /* Serialization failure, retry */
   3175           TALER_MERCHANTDB_rollback (TMH_db);
   3176           return;
   3177         case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   3178           /* UNIQUE constraint violation, meaning this token was already used. */
   3179           TALER_MERCHANTDB_rollback (TMH_db);
   3180           pay_end (pc,
   3181                    TALER_MHD_reply_with_error (pc->connection,
   3182                                                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3183                                                TALER_EC_GENERIC_DB_STORE_FAILED,
   3184                                                "duplicate output token"));
   3185           return;
   3186         case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   3187           break;
   3188         }
   3189         break;
   3190       }
   3191     }
   3192   }
   3193 
   3194   TMH_notify_order_change (hc->instance,
   3195                            TMH_OSF_CLAIMED | TMH_OSF_PAID,
   3196                            pc->check_contract.contract_terms->timestamp,
   3197                            pc->check_contract.order_serial);
   3198   {
   3199     enum GNUNET_DB_QueryStatus qs;
   3200     json_t *jhook;
   3201 
   3202     jhook = GNUNET_JSON_PACK (
   3203       GNUNET_JSON_pack_object_incref ("contract_terms",
   3204                                       pc->check_contract.contract_terms_json),
   3205       GNUNET_JSON_pack_string ("order_id",
   3206                                pc->order_id)
   3207       );
   3208     GNUNET_assert (NULL != jhook);
   3209     qs = TMH_trigger_webhook (pc->hc->instance->settings.id,
   3210                               "pay",
   3211                               jhook);
   3212     json_decref (jhook);
   3213     if (qs < 0)
   3214     {
   3215       TALER_MERCHANTDB_rollback (TMH_db);
   3216       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   3217         return; /* do it again */
   3218       GNUNET_break (0);
   3219       pay_end (pc,
   3220                TALER_MHD_reply_with_error (pc->connection,
   3221                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3222                                            TALER_EC_GENERIC_DB_STORE_FAILED,
   3223                                            "failed to trigger webhooks"));
   3224       return;
   3225     }
   3226   }
   3227   {
   3228     enum GNUNET_DB_QueryStatus qs;
   3229 
   3230     /* Now commit! */
   3231     qs = TALER_MERCHANTDB_commit (TMH_db);
   3232     if (0 > qs)
   3233     {
   3234       /* commit failed */
   3235       TALER_MERCHANTDB_rollback (TMH_db);
   3236       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   3237         return; /* do it again */
   3238       GNUNET_break (0);
   3239       pay_end (pc,
   3240                TALER_MHD_reply_with_error (pc->connection,
   3241                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3242                                            TALER_EC_GENERIC_DB_COMMIT_FAILED,
   3243                                            NULL));
   3244       return;
   3245     }
   3246   }
   3247   pc->phase++;
   3248 }
   3249 
   3250 
   3251 /**
   3252  * Ensures that the expected number of tokens for a @e key
   3253  * are provided as inputs and have valid signatures.
   3254  *
   3255  * @param[in,out] pc payment context we are processing
   3256  * @param family family the tokens should be from
   3257  * @param index number of the input we are handling
   3258  * @param expected_num number of tokens expected
   3259  * @return #GNUNET_YES on success
   3260  */
   3261 static enum GNUNET_GenericReturnValue
   3262 find_valid_input_tokens (
   3263   struct PayContext *pc,
   3264   const struct TALER_MERCHANT_ContractTokenFamily *family,
   3265   unsigned int index,
   3266   unsigned int expected_num)
   3267 {
   3268   unsigned int num_validated = 0;
   3269   struct GNUNET_TIME_Timestamp now
   3270     = GNUNET_TIME_timestamp_get ();
   3271   const struct TALER_MERCHANT_ContractTokenFamilyKey *kig = NULL;
   3272 
   3273   for (unsigned int j = 0; j < expected_num; j++)
   3274   {
   3275     struct TokenUseConfirmation *tuc
   3276       = &pc->parse_pay.tokens[index + j];
   3277     const struct TALER_MERCHANT_ContractTokenFamilyKey *key = NULL;
   3278 
   3279     for (unsigned int i = 0; i<family->keys_len; i++)
   3280     {
   3281       const struct TALER_MERCHANT_ContractTokenFamilyKey *ki
   3282         = &family->keys[i];
   3283 
   3284       if (0 ==
   3285           GNUNET_memcmp (&ki->pub.public_key->pub_key_hash,
   3286                          &tuc->h_issue.hash))
   3287       {
   3288         if (GNUNET_TIME_timestamp_cmp (ki->valid_after,
   3289                                        >,
   3290                                        now) ||
   3291             GNUNET_TIME_timestamp_cmp (ki->valid_before,
   3292                                        <=,
   3293                                        now))
   3294         {
   3295           /* We have a match, but not in the current validity period */
   3296           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3297                       "Public key %s currently not valid\n",
   3298                       GNUNET_h2s (&ki->pub.public_key->pub_key_hash));
   3299           kig = ki;
   3300           continue;
   3301         }
   3302         key = ki;
   3303         break;
   3304       }
   3305     }
   3306     if (NULL == key)
   3307     {
   3308       if (NULL != kig)
   3309       {
   3310         char start_str[128];
   3311         char end_str[128];
   3312         char emsg[350];
   3313 
   3314         GNUNET_snprintf (start_str,
   3315                          sizeof (start_str),
   3316                          "%s",
   3317                          GNUNET_STRINGS_timestamp_to_string (kig->valid_after));
   3318         GNUNET_snprintf (end_str,
   3319                          sizeof (end_str),
   3320                          "%s",
   3321                          GNUNET_STRINGS_timestamp_to_string (kig->valid_before))
   3322         ;
   3323         /* FIXME: use more specific EC */
   3324         GNUNET_snprintf (emsg,
   3325                          sizeof (emsg),
   3326                          "Token is only valid from %s to %s",
   3327                          start_str,
   3328                          end_str);
   3329         pay_end (pc,
   3330                  TALER_MHD_reply_with_error (
   3331                    pc->connection,
   3332                    MHD_HTTP_GONE,
   3333                    TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED,
   3334                    emsg));
   3335         return GNUNET_NO;
   3336       }
   3337       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3338                   "Input token supplied for public key %s that is not acceptable\n",
   3339                   GNUNET_h2s (&tuc->h_issue.hash));
   3340       GNUNET_break_op (0);
   3341       pay_end (pc,
   3342                TALER_MHD_reply_with_error (
   3343                  pc->connection,
   3344                  MHD_HTTP_BAD_REQUEST,
   3345                  TALER_EC_MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN,
   3346                  NULL));
   3347       return GNUNET_NO;
   3348     }
   3349     if (GNUNET_OK !=
   3350         TALER_token_issue_verify (&tuc->pub,
   3351                                   &key->pub,
   3352                                   &tuc->unblinded_sig))
   3353     {
   3354       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3355                   "Input token for public key with valid_after "
   3356                   "`%s' has invalid issue signature\n",
   3357                   GNUNET_TIME_timestamp2s (key->valid_after));
   3358       GNUNET_break (0);
   3359       pay_end (pc,
   3360                TALER_MHD_reply_with_error (
   3361                  pc->connection,
   3362                  MHD_HTTP_BAD_REQUEST,
   3363                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ISSUE_SIG_INVALID,
   3364                  NULL));
   3365       return GNUNET_NO;
   3366     }
   3367 
   3368     if (GNUNET_OK !=
   3369         TALER_wallet_token_use_verify (&pc->check_contract.h_contract_terms,
   3370                                        &pc->parse_wallet_data.h_wallet_data,
   3371                                        &tuc->pub,
   3372                                        &tuc->sig))
   3373     {
   3374       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3375                   "Input token for public key with valid_before "
   3376                   "`%s' has invalid use signature\n",
   3377                   GNUNET_TIME_timestamp2s (key->valid_before));
   3378       GNUNET_break (0);
   3379       pay_end (pc,
   3380                TALER_MHD_reply_with_error (
   3381                  pc->connection,
   3382                  MHD_HTTP_BAD_REQUEST,
   3383                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_USE_SIG_INVALID,
   3384                  NULL));
   3385       return GNUNET_NO;
   3386     }
   3387 
   3388     num_validated++;
   3389   }
   3390 
   3391   if (num_validated != expected_num)
   3392   {
   3393     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3394                 "Expected %d tokens for family %s, but found %d\n",
   3395                 expected_num,
   3396                 family->slug,
   3397                 num_validated);
   3398     GNUNET_break (0);
   3399     pay_end (pc,
   3400              TALER_MHD_reply_with_error (
   3401                pc->connection,
   3402                MHD_HTTP_BAD_REQUEST,
   3403                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_COUNT_MISMATCH,
   3404                NULL));
   3405     return GNUNET_NO;
   3406   }
   3407   return GNUNET_YES;
   3408 }
   3409 
   3410 
   3411 /**
   3412  * Check if an output token of the given @a tfk is mandatory, or if
   3413  * wallets are allowed to simply not support it and still proceed.
   3414  *
   3415  * @param tfk token family kind to check
   3416  * @return true if such outputs are mandatory and wallets must supply
   3417  *  the corresponding blinded input
   3418  */
   3419 /* FIXME: this function belongs into a lower-level lib! */
   3420 static bool
   3421 test_tfk_mandatory (enum TALER_MERCHANTDB_TokenFamilyKind tfk)
   3422 {
   3423   switch (tfk)
   3424   {
   3425   case TALER_MERCHANTDB_TFK_Discount:
   3426     return false;
   3427   case TALER_MERCHANTDB_TFK_Subscription:
   3428     return true;
   3429   }
   3430   GNUNET_break (0);
   3431   return false;
   3432 }
   3433 
   3434 
   3435 /**
   3436  * Sign the tokens provided by the wallet for a particular @a key.
   3437  *
   3438  * @param[in,out] pc reference for payment we are processing
   3439  * @param key token family data
   3440  * @param priv private key to use to sign with
   3441  * @param mandatory true if the token must exist, if false
   3442  *        and the client did not provide an envelope, that's OK and
   3443  *        we just also skimp on the signature
   3444  * @param index offset in the token envelope array (from other families)
   3445  * @param expected_num number of tokens of this type that we should create
   3446  * @return #GNUNET_NO on failure
   3447  *         #GNUNET_OK on success
   3448  */
   3449 static enum GNUNET_GenericReturnValue
   3450 sign_token_envelopes (
   3451   struct PayContext *pc,
   3452   const struct TALER_MERCHANT_ContractTokenFamilyKey *key,
   3453   const struct TALER_TokenIssuePrivateKey *priv,
   3454   bool mandatory,
   3455   unsigned int index,
   3456   unsigned int expected_num)
   3457 {
   3458   unsigned int num_signed = 0;
   3459 
   3460   for (unsigned int j = 0; j<expected_num; j++)
   3461   {
   3462     unsigned int pos = index + j;
   3463     const struct TokenEnvelope *env
   3464       = &pc->parse_wallet_data.token_envelopes[pos];
   3465     struct SignedOutputToken *output
   3466       = &pc->output_tokens[pos];
   3467 
   3468     if ( (pos >= pc->parse_wallet_data.token_envelopes_cnt) ||
   3469          (pos >= pc->output_tokens_len) )
   3470     {
   3471       GNUNET_assert (0); /* this should not happen */
   3472       return GNUNET_NO;
   3473     }
   3474     if (NULL == env->blinded_token.blinded_pub)
   3475     {
   3476       if (! mandatory)
   3477         continue;
   3478 
   3479       /* mandatory token families require a token envelope. */
   3480       GNUNET_break_op (0);
   3481       pay_end (pc,
   3482                TALER_MHD_reply_with_error (
   3483                  pc->connection,
   3484                  MHD_HTTP_BAD_REQUEST,
   3485                  TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3486                  "Token envelope for mandatory token family missing"));
   3487       return GNUNET_NO;
   3488     }
   3489     TALER_token_issue_sign (priv,
   3490                             &env->blinded_token,
   3491                             &output->sig);
   3492     output->h_issue.hash
   3493       = key->pub.public_key->pub_key_hash;
   3494     num_signed++;
   3495   }
   3496 
   3497   if (mandatory &&
   3498       (num_signed != expected_num) )
   3499   {
   3500     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3501                 "Expected %d token envelopes for public key with valid_after "
   3502                 "'%s', but found %d\n",
   3503                 expected_num,
   3504                 GNUNET_TIME_timestamp2s (key->valid_after),
   3505                 num_signed);
   3506     GNUNET_break (0);
   3507     pay_end (pc,
   3508              TALER_MHD_reply_with_error (
   3509                pc->connection,
   3510                MHD_HTTP_BAD_REQUEST,
   3511                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ENVELOPE_COUNT_MISMATCH,
   3512                NULL));
   3513     return GNUNET_NO;
   3514   }
   3515 
   3516   return GNUNET_OK;
   3517 }
   3518 
   3519 
   3520 /**
   3521  * Find the family entry for the family of the given @a slug
   3522  * in @a pc.
   3523  *
   3524  * @param[in] pc payment context to search
   3525  * @param slug slug to search for
   3526  * @return NULL if @a slug was not found
   3527  */
   3528 static const struct TALER_MERCHANT_ContractTokenFamily *
   3529 find_family (const struct PayContext *pc,
   3530              const char *slug)
   3531 {
   3532   for (unsigned int i = 0;
   3533        i < pc->check_contract.contract_terms->details.v1.token_authorities_len;
   3534        i++)
   3535   {
   3536     const struct TALER_MERCHANT_ContractTokenFamily *tfi
   3537       = &pc->check_contract.contract_terms->details.v1.token_authorities[i];
   3538 
   3539     if (0 == strcmp (tfi->slug,
   3540                      slug))
   3541     {
   3542       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3543                   "Token family %s found with %u keys\n",
   3544                   slug,
   3545                   tfi->keys_len);
   3546       return tfi;
   3547     }
   3548   }
   3549   return NULL;
   3550 }
   3551 
   3552 
   3553 /**
   3554  * Handle contract output of type TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN.
   3555  * Looks up the token family, loads the matching private key,
   3556  * and signs the corresponding token envelopes from the wallet.
   3557  *
   3558  * @param pc context for the pay request
   3559  * @param output contract output we need to process
   3560  * @param output_index index of this output in the contract's outputs array
   3561  * @return #GNUNET_OK on success, #GNUNET_NO if an error was encountered
   3562  */
   3563 static enum GNUNET_GenericReturnValue
   3564 handle_output_token (struct PayContext *pc,
   3565                      const struct TALER_MERCHANT_ContractOutput *output,
   3566                      unsigned int output_index)
   3567 {
   3568   const struct TALER_MERCHANT_ContractTokenFamily *family;
   3569   struct TALER_MERCHANT_ContractTokenFamilyKey *key;
   3570   struct TALER_MERCHANTDB_TokenFamilyKeyDetails details;
   3571   enum GNUNET_DB_QueryStatus qs;
   3572   bool mandatory;
   3573 
   3574   /* Locate token family in the contract.
   3575      This should ever fail as this invariant should
   3576      have been checked when the contract was created. */
   3577   family = find_family (pc,
   3578                         output->details.token.token_family_slug);
   3579   if (NULL == family)
   3580   {
   3581     /* This "should never happen", so treat it as an internal error */
   3582     GNUNET_break (0);
   3583     pay_end (pc,
   3584              TALER_MHD_reply_with_error (
   3585                pc->connection,
   3586                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3587                TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3588                "token family not found in order"));
   3589     return GNUNET_SYSERR;
   3590   }
   3591 
   3592   /* Check the key_index field from the output. */
   3593   if (output->details.token.key_index >= family->keys_len)
   3594   {
   3595     /* Also "should never happen", contract was presumably validated on insert */
   3596     GNUNET_break (0);
   3597     pay_end (pc,
   3598              TALER_MHD_reply_with_error (
   3599                pc->connection,
   3600                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3601                TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3602                "key index invalid for token family"));
   3603     return GNUNET_SYSERR;
   3604   }
   3605 
   3606   /* Pick the correct key inside that family. */
   3607   key = &family->keys[output->details.token.key_index];
   3608 
   3609   /* Fetch the private key from the DB for the merchant instance and
   3610    * this particular family/time interval. */
   3611   qs = TALER_MERCHANTDB_lookup_token_family_key (
   3612     TMH_db,
   3613     pc->hc->instance->settings.id,
   3614     family->slug,
   3615     pc->check_contract.contract_terms->timestamp,
   3616     pc->check_contract.contract_terms->pay_deadline,
   3617     &details);
   3618   switch (qs)
   3619   {
   3620   case GNUNET_DB_STATUS_HARD_ERROR:
   3621   case GNUNET_DB_STATUS_SOFT_ERROR:
   3622     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3623                 "Database error looking up token-family key for %s\n",
   3624                 family->slug);
   3625     GNUNET_break (0);
   3626     pay_end (pc,
   3627              TALER_MHD_reply_with_error (
   3628                pc->connection,
   3629                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3630                TALER_EC_GENERIC_DB_FETCH_FAILED,
   3631                NULL));
   3632     return GNUNET_NO;
   3633   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   3634     GNUNET_log (
   3635       GNUNET_ERROR_TYPE_ERROR,
   3636       "Token-family key for %s not found at [%llu,%llu]\n",
   3637       family->slug,
   3638       (unsigned long long)
   3639       pc->check_contract.contract_terms->timestamp.abs_time.abs_value_us,
   3640       (unsigned long long)
   3641       pc->check_contract.contract_terms->pay_deadline.abs_time.abs_value_us
   3642       );
   3643     GNUNET_break (0);
   3644     pay_end (pc,
   3645              TALER_MHD_reply_with_error (
   3646                pc->connection,
   3647                MHD_HTTP_NOT_FOUND,
   3648                TALER_EC_MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN,
   3649                family->slug));
   3650     return GNUNET_NO;
   3651 
   3652   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   3653     break;
   3654   }
   3655   GNUNET_assert (NULL != details.priv.private_key);
   3656   GNUNET_free (details.token_family.slug);
   3657   GNUNET_free (details.token_family.name);
   3658   GNUNET_free (details.token_family.description);
   3659   json_decref (details.token_family.description_i18n);
   3660   GNUNET_CRYPTO_blind_sign_pub_decref (details.pub.public_key);
   3661   GNUNET_free (details.token_family.cipher_spec);
   3662 
   3663   /* Depending on the token family, decide if the token envelope
   3664    * is mandatory or optional.  (Simplified logic here: adapt as needed.) */
   3665   mandatory = test_tfk_mandatory (details.token_family.kind);
   3666   /* Actually sign the number of token envelopes specified in 'count'.
   3667    * 'output_index' is the offset into the parse_wallet_data arrays.  */
   3668   if (GNUNET_OK !=
   3669       sign_token_envelopes (pc,
   3670                             key,
   3671                             &details.priv,
   3672                             mandatory,
   3673                             output_index,
   3674                             output->details.token.count))
   3675   {
   3676     /* sign_token_envelopes() already queued up an error via pay_end() */
   3677     GNUNET_break_op (0);
   3678     return GNUNET_NO;
   3679   }
   3680   GNUNET_CRYPTO_blind_sign_priv_decref (details.priv.private_key);
   3681   return GNUNET_OK;
   3682 }
   3683 
   3684 
   3685 /**
   3686  * Handle checks for contract output of type TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT.
   3687  * For now, this does nothing and simply returns #GNUNET_OK.
   3688  *
   3689  * @param pc context for the pay request
   3690  * @param output the contract output describing the donation receipt requirement
   3691  * @return #GNUNET_OK on success,
   3692  *         #GNUNET_NO if an error was already queued
   3693  */
   3694 static enum GNUNET_GenericReturnValue
   3695 handle_output_donation_receipt (
   3696   struct PayContext *pc,
   3697   const struct TALER_MERCHANT_ContractOutput *output)
   3698 {
   3699   enum GNUNET_GenericReturnValue ret;
   3700 
   3701   ret = DONAU_get_donation_amount_from_bkps (
   3702     pc->parse_wallet_data.donau_keys,
   3703     pc->parse_wallet_data.bkps,
   3704     pc->parse_wallet_data.num_bkps,
   3705     pc->parse_wallet_data.donau.donation_year,
   3706     &pc->parse_wallet_data.donation_amount);
   3707   switch (ret)
   3708   {
   3709   case GNUNET_SYSERR:
   3710     GNUNET_break (0);
   3711     pay_end (pc,
   3712              TALER_MHD_reply_with_error (
   3713                pc->connection,
   3714                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3715                TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3716                NULL));
   3717     return GNUNET_NO;
   3718   case GNUNET_NO:
   3719     GNUNET_break_op (0);
   3720     pay_end (pc,
   3721              TALER_MHD_reply_with_error (
   3722                pc->connection,
   3723                MHD_HTTP_BAD_REQUEST,
   3724                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3725                "inconsistent bkps / donau keys"));
   3726     return GNUNET_NO;
   3727   case GNUNET_OK:
   3728     break;
   3729   }
   3730 
   3731   if (GNUNET_OK !=
   3732       TALER_amount_cmp_currency (&pc->parse_wallet_data.donation_amount,
   3733                                  &output->details.donation_receipt.amount))
   3734   {
   3735     GNUNET_break_op (0);
   3736     pay_end (pc,
   3737              TALER_MHD_reply_with_error (
   3738                pc->connection,
   3739                MHD_HTTP_BAD_REQUEST,
   3740                TALER_EC_GENERIC_CURRENCY_MISMATCH,
   3741                output->details.donation_receipt.amount.currency));
   3742     return GNUNET_NO;
   3743   }
   3744 
   3745   if (0 !=
   3746       TALER_amount_cmp (&pc->parse_wallet_data.donation_amount,
   3747                         &output->details.donation_receipt.amount))
   3748   {
   3749     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3750                 "Wallet amount: %s\n",
   3751                 TALER_amount2s (&pc->parse_wallet_data.donation_amount));
   3752     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3753                 "Donation receipt amount: %s\n",
   3754                 TALER_amount2s (&output->details.donation_receipt.amount));
   3755     GNUNET_break_op (0);
   3756     pay_end (pc,
   3757              TALER_MHD_reply_with_error (
   3758                pc->connection,
   3759                MHD_HTTP_CONFLICT,
   3760                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH,
   3761                "donation amount mismatch"));
   3762     return GNUNET_NO;
   3763   }
   3764   {
   3765     struct TALER_Amount receipts_to_date;
   3766 
   3767     if (0 >
   3768         TALER_amount_add (&receipts_to_date,
   3769                           &pc->parse_wallet_data.charity_receipts_to_date,
   3770                           &pc->parse_wallet_data.donation_amount))
   3771     {
   3772       GNUNET_break (0);
   3773       pay_end (pc,
   3774                TALER_MHD_reply_with_error (pc->connection,
   3775                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3776                                            TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   3777                                            "adding donation amount"));
   3778       return GNUNET_NO;
   3779     }
   3780 
   3781     if (1 ==
   3782         TALER_amount_cmp (&receipts_to_date,
   3783                           &pc->parse_wallet_data.charity_max_per_year))
   3784     {
   3785       GNUNET_break_op (0);
   3786       pay_end (pc,
   3787                TALER_MHD_reply_with_error (pc->connection,
   3788                                            MHD_HTTP_CONFLICT,
   3789                                            TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH,
   3790                                            "donation limit exceeded"));
   3791       return GNUNET_NO;
   3792     }
   3793     pc->parse_wallet_data.charity_receipts_to_date = receipts_to_date;
   3794   }
   3795   return GNUNET_OK;
   3796 }
   3797 
   3798 
   3799 /**
   3800  * Count tokens produced by an output.
   3801  *
   3802  * @param pc pay context
   3803  * @param output output to consider
   3804  * @returns number of output tokens
   3805  */
   3806 static unsigned int
   3807 count_output_tokens (const struct PayContext *pc,
   3808                      const struct TALER_MERCHANT_ContractOutput *output)
   3809 {
   3810   switch (output->type)
   3811   {
   3812   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   3813     GNUNET_assert (0);
   3814     break;
   3815   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   3816     return output->details.token.count;
   3817   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   3818     return pc->parse_wallet_data.num_bkps;
   3819   }
   3820   /* Not reached. */
   3821   GNUNET_assert (0);
   3822 }
   3823 
   3824 
   3825 /**
   3826  * Validate tokens and token envelopes. First, we check if all tokens listed
   3827  * in the 'inputs' array of the selected choice are present in the 'tokens'
   3828  * array of the request. Then, we validate the signatures of each provided
   3829  * token.
   3830  *
   3831  * @param[in,out] pc context we use to handle the payment
   3832  */
   3833 static void
   3834 phase_validate_tokens (struct PayContext *pc)
   3835 {
   3836   /* We haven't seen a donau output yet. */
   3837   pc->validate_tokens.donau_output_index = -1;
   3838 
   3839   switch (pc->check_contract.contract_terms->version)
   3840   {
   3841   case TALER_MERCHANT_CONTRACT_VERSION_0:
   3842     /* No tokens to validate */
   3843     pc->phase = PP_COMPUTE_MONEY_POTS;
   3844     pc->validate_tokens.max_fee
   3845       = pc->check_contract.contract_terms->details.v0.max_fee;
   3846     pc->validate_tokens.brutto
   3847       = pc->check_contract.contract_terms->details.v0.brutto;
   3848     break;
   3849   case TALER_MERCHANT_CONTRACT_VERSION_1:
   3850     {
   3851       const struct TALER_MERCHANT_ContractChoice *selected
   3852         = &pc->check_contract.contract_terms->details.v1.choices[
   3853             pc->parse_wallet_data.choice_index];
   3854       unsigned int output_off;
   3855       unsigned int cnt;
   3856 
   3857       pc->validate_tokens.max_fee = selected->max_fee;
   3858       pc->validate_tokens.brutto = selected->amount;
   3859 
   3860       for (unsigned int i = 0; i<selected->inputs_len; i++)
   3861       {
   3862         const struct TALER_MERCHANT_ContractInput *input
   3863           = &selected->inputs[i];
   3864         const struct TALER_MERCHANT_ContractTokenFamily *family;
   3865 
   3866         switch (input->type)
   3867         {
   3868         case TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID:
   3869           GNUNET_break (0);
   3870           pay_end (pc,
   3871                    TALER_MHD_reply_with_error (
   3872                      pc->connection,
   3873                      MHD_HTTP_BAD_REQUEST,
   3874                      TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3875                      "input token type not valid"));
   3876           return;
   3877 #if FUTURE
   3878         case TALER_MERCHANT_CONTRACT_INPUT_TYPE_COIN:
   3879           GNUNET_break (0);
   3880           pay_end (pc,
   3881                    TALER_MHD_reply_with_error (
   3882                      pc->connection,
   3883                      MHD_HTTP_NOT_IMPLEMENTED,
   3884                      TALER_EC_MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE,
   3885                      "token type not yet supported"));
   3886           return;
   3887 #endif
   3888         case TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN:
   3889           family = find_family (pc,
   3890                                 input->details.token.token_family_slug);
   3891           if (NULL == family)
   3892           {
   3893             /* this should never happen, since the choices and
   3894                token families are validated on insert. */
   3895             GNUNET_break (0);
   3896             pay_end (pc,
   3897                      TALER_MHD_reply_with_error (
   3898                        pc->connection,
   3899                        MHD_HTTP_INTERNAL_SERVER_ERROR,
   3900                        TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3901                        "token family not found in order"));
   3902             return;
   3903           }
   3904           if (GNUNET_NO ==
   3905               find_valid_input_tokens (pc,
   3906                                        family,
   3907                                        i,
   3908                                        input->details.token.count))
   3909           {
   3910             /* Error is already scheduled from find_valid_input_token. */
   3911             return;
   3912           }
   3913         }
   3914       }
   3915 
   3916       /* calculate pc->output_tokens_len */
   3917       output_off = 0;
   3918       for (unsigned int i = 0; i<selected->outputs_len; i++)
   3919       {
   3920         const struct TALER_MERCHANT_ContractOutput *output
   3921           = &selected->outputs[i];
   3922 
   3923         switch (output->type)
   3924         {
   3925         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   3926           GNUNET_assert (0);
   3927           break;
   3928         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   3929           cnt = output->details.token.count;
   3930           if (output_off + cnt < output_off)
   3931           {
   3932             GNUNET_break_op (0);
   3933             pay_end (pc,
   3934                      TALER_MHD_reply_with_error (
   3935                        pc->connection,
   3936                        MHD_HTTP_BAD_REQUEST,
   3937                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3938                        "output token counter overflow"));
   3939             return;
   3940           }
   3941           output_off += cnt;
   3942           break;
   3943         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   3944           /* check that this output type appears at most once */
   3945           if (pc->validate_tokens.donau_output_index >= 0)
   3946           {
   3947             /* This should have been prevented when the
   3948                contract was initially created */
   3949             GNUNET_break (0);
   3950             pay_end (pc,
   3951                      TALER_MHD_reply_with_error (
   3952                        pc->connection,
   3953                        MHD_HTTP_INTERNAL_SERVER_ERROR,
   3954                        TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
   3955                        "two donau output sets in same contract"));
   3956             return;
   3957           }
   3958           pc->validate_tokens.donau_output_index = i;
   3959           if (output_off + pc->parse_wallet_data.num_bkps < output_off)
   3960           {
   3961             GNUNET_break_op (0);
   3962             pay_end (pc,
   3963                      TALER_MHD_reply_with_error (
   3964                        pc->connection,
   3965                        MHD_HTTP_BAD_REQUEST,
   3966                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3967                        "output token counter overflow"));
   3968             return;
   3969           }
   3970           output_off += pc->parse_wallet_data.num_bkps;
   3971           break;
   3972         }
   3973       }
   3974 
   3975 
   3976       pc->output_tokens_len = output_off;
   3977       pc->output_tokens
   3978         = GNUNET_new_array (pc->output_tokens_len,
   3979                             struct SignedOutputToken);
   3980 
   3981       /* calculate pc->output_tokens[].output_index */
   3982       output_off = 0;
   3983       for (unsigned int i = 0; i<selected->outputs_len; i++)
   3984       {
   3985         const struct TALER_MERCHANT_ContractOutput *output
   3986           = &selected->outputs[i];
   3987         cnt = count_output_tokens (pc,
   3988                                    output);
   3989         for (unsigned int j = 0; j<cnt; j++)
   3990           pc->output_tokens[output_off + j].output_index = i;
   3991         output_off += cnt;
   3992       }
   3993 
   3994       /* compute non-donau outputs */
   3995       output_off = 0;
   3996       for (unsigned int i = 0; i<selected->outputs_len; i++)
   3997       {
   3998         const struct TALER_MERCHANT_ContractOutput *output
   3999           = &selected->outputs[i];
   4000 
   4001         switch (output->type)
   4002         {
   4003         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   4004           GNUNET_assert (0);
   4005           break;
   4006         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   4007           cnt = output->details.token.count;
   4008           GNUNET_assert (output_off + cnt
   4009                          <= pc->output_tokens_len);
   4010           if (GNUNET_OK !=
   4011               handle_output_token (pc,
   4012                                    output,
   4013                                    output_off))
   4014           {
   4015             /* Error is already scheduled from handle_output_token. */
   4016             return;
   4017           }
   4018           output_off += cnt;
   4019           break;
   4020         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   4021           if ( (0 != pc->parse_wallet_data.num_bkps) &&
   4022                (GNUNET_OK !=
   4023                 handle_output_donation_receipt (pc,
   4024                                                 output)) )
   4025           {
   4026             /* Error is already scheduled from handle_output_donation_receipt. */
   4027             return;
   4028           }
   4029           output_off += pc->parse_wallet_data.num_bkps;
   4030           continue;
   4031         } /* switch on output token */
   4032       } /* for all output token types */
   4033     } /* case contract v1 */
   4034     break;
   4035   } /* switch on contract type */
   4036 
   4037   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   4038   {
   4039     const struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   4040 
   4041     if (GNUNET_OK !=
   4042         TALER_amount_cmp_currency (&dc->cdd.amount,
   4043                                    &pc->validate_tokens.brutto))
   4044     {
   4045       GNUNET_break_op (0);
   4046       pay_end (pc,
   4047                TALER_MHD_reply_with_error (
   4048                  pc->connection,
   4049                  MHD_HTTP_CONFLICT,
   4050                  TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH,
   4051                  pc->validate_tokens.brutto.currency));
   4052       return;
   4053     }
   4054   }
   4055 
   4056   pc->phase = PP_COMPUTE_MONEY_POTS;
   4057 }
   4058 
   4059 
   4060 /**
   4061  * Function called with information about a coin that was deposited.
   4062  * Checks if this coin is in our list of deposits as well.
   4063  *
   4064  * @param cls closure with our `struct PayContext *`
   4065  * @param deposit_serial which deposit operation is this about
   4066  * @param exchange_url URL of the exchange that issued the coin
   4067  * @param h_wire hash of merchant's wire details
   4068  * @param deposit_timestamp when was the deposit made
   4069  * @param amount_with_fee amount the exchange will deposit for this coin
   4070  * @param deposit_fee fee the exchange will charge for this coin
   4071  * @param coin_pub public key of the coin
   4072  */
   4073 static void
   4074 deposit_paid_check (
   4075   void *cls,
   4076   uint64_t deposit_serial,
   4077   const char *exchange_url,
   4078   const struct TALER_MerchantWireHashP *h_wire,
   4079   struct GNUNET_TIME_Timestamp deposit_timestamp,
   4080   const struct TALER_Amount *amount_with_fee,
   4081   const struct TALER_Amount *deposit_fee,
   4082   const struct TALER_CoinSpendPublicKeyP *coin_pub)
   4083 {
   4084   struct PayContext *pc = cls;
   4085 
   4086   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   4087   {
   4088     struct DepositConfirmation *dci = &pc->parse_pay.dc[i];
   4089 
   4090     if ( (0 ==
   4091           GNUNET_memcmp (&dci->cdd.coin_pub,
   4092                          coin_pub)) &&
   4093          (0 ==
   4094           strcmp (dci->exchange_url,
   4095                   exchange_url)) &&
   4096          (GNUNET_YES ==
   4097           TALER_amount_cmp_currency (&dci->cdd.amount,
   4098                                      amount_with_fee)) &&
   4099          (0 ==
   4100           TALER_amount_cmp (&dci->cdd.amount,
   4101                             amount_with_fee)) )
   4102     {
   4103       dci->matched_in_db = true;
   4104       break;
   4105     }
   4106   }
   4107 }
   4108 
   4109 
   4110 /**
   4111  * Function called with information about a token that was spent.
   4112  * FIXME: Replace this with a more specific function for this cb
   4113  *
   4114  * @param cls closure with `struct PayContext *`
   4115  * @param spent_token_serial "serial" of the spent token unused
   4116  * @param h_contract_terms hash of the contract terms unused
   4117  * @param h_issue_pub hash of the token issue public key unused
   4118  * @param use_pub public key of the token
   4119  * @param use_sig signature of the token
   4120  * @param issue_sig signature of the token issue
   4121  */
   4122 static void
   4123 input_tokens_paid_check (
   4124   void *cls,
   4125   uint64_t spent_token_serial,
   4126   const struct TALER_PrivateContractHashP *h_contract_terms,
   4127   const struct TALER_TokenIssuePublicKeyHashP *h_issue_pub,
   4128   const struct TALER_TokenUsePublicKeyP *use_pub,
   4129   const struct TALER_TokenUseSignatureP *use_sig,
   4130   const struct TALER_TokenIssueSignature *issue_sig)
   4131 {
   4132   struct PayContext *pc = cls;
   4133 
   4134   for (size_t i = 0; i<pc->parse_pay.tokens_cnt; i++)
   4135   {
   4136     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   4137 
   4138     if ( (0 ==
   4139           GNUNET_memcmp (&tuc->pub,
   4140                          use_pub)) &&
   4141          (0 ==
   4142           GNUNET_memcmp (&tuc->sig,
   4143                          use_sig)) &&
   4144          (0 ==
   4145           GNUNET_memcmp (&tuc->unblinded_sig,
   4146                          issue_sig)) )
   4147     {
   4148       tuc->found_in_db = true;
   4149       break;
   4150     }
   4151   }
   4152 }
   4153 
   4154 
   4155 /**
   4156  * Small helper function to append an output token signature from db
   4157  *
   4158  * @param cls closure with `struct PayContext *`
   4159  * @param h_issue hash of the token
   4160  * @param sig signature of the token
   4161  */
   4162 static void
   4163 append_output_token_sig (void *cls,
   4164                          struct GNUNET_HashCode *h_issue,
   4165                          struct GNUNET_CRYPTO_BlindedSignature *sig)
   4166 {
   4167   struct PayContext *pc = cls;
   4168   struct TALER_MERCHANT_ContractChoice *choice;
   4169   const struct TALER_MERCHANT_ContractOutput *output;
   4170   struct SignedOutputToken out;
   4171   unsigned int cnt;
   4172 
   4173   memset (&out,
   4174           0,
   4175           sizeof (out));
   4176   GNUNET_assert (TALER_MERCHANT_CONTRACT_VERSION_1 ==
   4177                  pc->check_contract.contract_terms->version);
   4178   choice = &pc->check_contract.contract_terms->details.v1
   4179            .choices[pc->parse_wallet_data.choice_index];
   4180   output = &choice->outputs[pc->output_index_gen];
   4181   cnt = count_output_tokens (pc,
   4182                              output);
   4183   out.output_index = pc->output_index_gen;
   4184   out.h_issue.hash = *h_issue;
   4185   out.sig.signature = sig;
   4186   GNUNET_CRYPTO_blind_sig_incref (sig);
   4187   GNUNET_array_append (pc->output_tokens,
   4188                        pc->output_tokens_len,
   4189                        out);
   4190   /* Go to next output once we've output all tokens for the current one. */
   4191   pc->output_token_cnt++;
   4192   if (pc->output_token_cnt >= cnt)
   4193   {
   4194     pc->output_token_cnt = 0;
   4195     pc->output_index_gen++;
   4196   }
   4197 }
   4198 
   4199 
   4200 /**
   4201  * Handle case where contract was already paid. Either decides
   4202  * the payment is idempotent, or refunds the excess payment.
   4203  *
   4204  * @param[in,out] pc context we use to handle the payment
   4205  */
   4206 static void
   4207 phase_contract_paid (struct PayContext *pc)
   4208 {
   4209   json_t *refunds;
   4210   bool unmatched = false;
   4211 
   4212   {
   4213     enum GNUNET_DB_QueryStatus qs;
   4214 
   4215     qs = TALER_MERCHANTDB_lookup_deposits_by_order (TMH_db,
   4216                                                     pc->check_contract.order_serial,
   4217                                                     &deposit_paid_check,
   4218                                                     pc);
   4219     /* Since orders with choices can have a price of zero,
   4220        0 is also a valid query state */
   4221     if (qs < 0)
   4222     {
   4223       GNUNET_break (0);
   4224       pay_end (pc,
   4225                TALER_MHD_reply_with_error (
   4226                  pc->connection,
   4227                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4228                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   4229                  "lookup_deposits_by_order"));
   4230       return;
   4231     }
   4232   }
   4233   for (size_t i = 0;
   4234        i<pc->parse_pay.coins_cnt && ! unmatched;
   4235        i++)
   4236   {
   4237     struct DepositConfirmation *dci = &pc->parse_pay.dc[i];
   4238 
   4239     if (! dci->matched_in_db)
   4240       unmatched = true;
   4241   }
   4242   /* Check if provided input tokens match token in the database */
   4243   {
   4244     enum GNUNET_DB_QueryStatus qs;
   4245 
   4246     /* FIXME-Optimization: Maybe use h_contract instead of order_serial here? */
   4247     qs = TALER_MERCHANTDB_lookup_spent_tokens_by_order (TMH_db,
   4248                                                         pc->check_contract.order_serial,
   4249                                                         &input_tokens_paid_check,
   4250                                                         pc);
   4251 
   4252     if (qs < 0)
   4253     {
   4254       GNUNET_break (0);
   4255       pay_end (pc,
   4256                TALER_MHD_reply_with_error (
   4257                  pc->connection,
   4258                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4259                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   4260                  "lookup_spent_tokens_by_order"));
   4261       return;
   4262     }
   4263   }
   4264   for (size_t i = 0; i<pc->parse_pay.tokens_cnt && ! unmatched; i++)
   4265   {
   4266     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   4267 
   4268     if (! tuc->found_in_db)
   4269       unmatched = true;
   4270   }
   4271 
   4272   /* In this part we are fetching token_sigs related output */
   4273   if (! unmatched)
   4274   {
   4275     /* Everything fine, idempotent request, generate response immediately */
   4276     enum GNUNET_DB_QueryStatus qs;
   4277 
   4278     pc->output_index_gen = 0;
   4279     qs = TALER_MERCHANTDB_select_order_blinded_sigs (
   4280       TMH_db,
   4281       pc->order_id,
   4282       &append_output_token_sig,
   4283       pc);
   4284     if (0 > qs)
   4285     {
   4286       GNUNET_break (0);
   4287       pay_end (pc,
   4288                TALER_MHD_reply_with_error (
   4289                  pc->connection,
   4290                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4291                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   4292                  "select_order_blinded_sigs"));
   4293       return;
   4294     }
   4295 
   4296     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4297                 "Idempotent pay request for order `%s', signing again\n",
   4298                 pc->order_id);
   4299     pc->phase = PP_SUCCESS_RESPONSE;
   4300     return;
   4301   }
   4302   /* Conflict, double-payment detected! */
   4303   /* FIXME-#8674: What should we do with input tokens?
   4304      Currently there is no refund for tokens. */
   4305   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4306               "Client attempted to pay extra for already paid order `%s'\n",
   4307               pc->order_id);
   4308   refunds = json_array ();
   4309   GNUNET_assert (NULL != refunds);
   4310   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   4311   {
   4312     struct DepositConfirmation *dci = &pc->parse_pay.dc[i];
   4313     struct TALER_MerchantSignatureP merchant_sig;
   4314 
   4315     if (dci->matched_in_db)
   4316       continue;
   4317     TALER_merchant_refund_sign (&dci->cdd.coin_pub,
   4318                                 &pc->check_contract.h_contract_terms,
   4319                                 0, /* rtransaction id */
   4320                                 &dci->cdd.amount,
   4321                                 &pc->hc->instance->merchant_priv,
   4322                                 &merchant_sig);
   4323     GNUNET_assert (
   4324       0 ==
   4325       json_array_append_new (
   4326         refunds,
   4327         GNUNET_JSON_PACK (
   4328           GNUNET_JSON_pack_data_auto (
   4329             "coin_pub",
   4330             &dci->cdd.coin_pub),
   4331           GNUNET_JSON_pack_data_auto (
   4332             "merchant_sig",
   4333             &merchant_sig),
   4334           TALER_JSON_pack_amount ("amount",
   4335                                   &dci->cdd.amount),
   4336           GNUNET_JSON_pack_uint64 ("rtransaction_id",
   4337                                    0))));
   4338   }
   4339   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4340               "Generating JSON response with code %d\n",
   4341               (int) TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID);
   4342   pay_end (pc,
   4343            TALER_MHD_REPLY_JSON_PACK (
   4344              pc->connection,
   4345              MHD_HTTP_CONFLICT,
   4346              TALER_MHD_PACK_EC (
   4347                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID),
   4348              GNUNET_JSON_pack_array_steal ("refunds",
   4349                                            refunds)));
   4350 }
   4351 
   4352 
   4353 /**
   4354  * Check the database state for the given order.
   4355  * Schedules an error response in the connection on failure.
   4356  *
   4357  * @param[in,out] pc context we use to handle the payment
   4358  */
   4359 static void
   4360 phase_check_contract (struct PayContext *pc)
   4361 {
   4362   /* obtain contract terms */
   4363   enum GNUNET_DB_QueryStatus qs;
   4364   bool paid = false;
   4365 
   4366   if (NULL != pc->check_contract.contract_terms_json)
   4367   {
   4368     json_decref (pc->check_contract.contract_terms_json);
   4369     pc->check_contract.contract_terms_json = NULL;
   4370   }
   4371   if (NULL != pc->check_contract.contract_terms)
   4372   {
   4373     TALER_MERCHANT_contract_free (pc->check_contract.contract_terms);
   4374     pc->check_contract.contract_terms = NULL;
   4375   }
   4376   qs = TALER_MERCHANTDB_lookup_contract_terms2 (TMH_db,
   4377                                                 pc->hc->instance->settings.id,
   4378                                                 pc->order_id,
   4379                                                 &pc->check_contract.contract_terms_json,
   4380                                                 &pc->check_contract.order_serial,
   4381                                                 &paid,
   4382                                                 NULL,
   4383                                                 &pc->check_contract.pos_key,
   4384                                                 &pc->check_contract.pos_alg);
   4385   if (0 > qs)
   4386   {
   4387     /* single, read-only SQL statements should never cause
   4388        serialization problems */
   4389     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
   4390     /* Always report on hard error to enable diagnostics */
   4391     GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   4392     pay_end (pc,
   4393              TALER_MHD_reply_with_error (
   4394                pc->connection,
   4395                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4396                TALER_EC_GENERIC_DB_FETCH_FAILED,
   4397                "contract terms"));
   4398     return;
   4399   }
   4400   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   4401   {
   4402     pay_end (pc,
   4403              TALER_MHD_reply_with_error (
   4404                pc->connection,
   4405                MHD_HTTP_NOT_FOUND,
   4406                TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN,
   4407                pc->order_id));
   4408     return;
   4409   }
   4410   /* hash contract (needed later) */
   4411 #if DEBUG
   4412   json_dumpf (pc->check_contract.contract_terms_json,
   4413               stderr,
   4414               JSON_INDENT (2));
   4415 #endif
   4416   if (GNUNET_OK !=
   4417       TALER_JSON_contract_hash (pc->check_contract.contract_terms_json,
   4418                                 &pc->check_contract.h_contract_terms))
   4419   {
   4420     GNUNET_break (0);
   4421     pay_end (pc,
   4422              TALER_MHD_reply_with_error (
   4423                pc->connection,
   4424                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4425                TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH,
   4426                NULL));
   4427     return;
   4428   }
   4429 
   4430   /* Parse the contract terms even for paid orders,
   4431      as later phases need it. */
   4432 
   4433   pc->check_contract.contract_terms = TALER_MERCHANT_contract_parse (
   4434     pc->check_contract.contract_terms_json,
   4435     true);
   4436 
   4437   if (NULL == pc->check_contract.contract_terms)
   4438   {
   4439     /* invalid contract */
   4440     GNUNET_break (0);
   4441     pay_end (pc,
   4442              TALER_MHD_reply_with_error (
   4443                pc->connection,
   4444                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4445                TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID,
   4446                pc->order_id));
   4447     return;
   4448   }
   4449 
   4450   if (paid)
   4451   {
   4452     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4453                 "Order `%s' paid, checking for double-payment\n",
   4454                 pc->order_id);
   4455     pc->phase = PP_CONTRACT_PAID;
   4456     return;
   4457   }
   4458   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4459               "Handling payment for order `%s' with contract hash `%s'\n",
   4460               pc->order_id,
   4461               GNUNET_h2s (&pc->check_contract.h_contract_terms.hash));
   4462 
   4463   /* Check fundamentals */
   4464   {
   4465     switch (pc->check_contract.contract_terms->version)
   4466     {
   4467     case TALER_MERCHANT_CONTRACT_VERSION_0:
   4468       {
   4469         if (pc->parse_wallet_data.choice_index > 0)
   4470         {
   4471           GNUNET_break (0);
   4472           pay_end (pc,
   4473                    TALER_MHD_reply_with_error (
   4474                      pc->connection,
   4475                      MHD_HTTP_BAD_REQUEST,
   4476                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS,
   4477                      "contract terms v0 has no choices"));
   4478           return;
   4479         }
   4480       }
   4481       break;
   4482     case TALER_MERCHANT_CONTRACT_VERSION_1:
   4483       {
   4484         if (pc->parse_wallet_data.choice_index < 0)
   4485         {
   4486           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4487                       "Order `%s' has non-empty choices array but"
   4488                       "request is missing 'choice_index' field\n",
   4489                       pc->order_id);
   4490           GNUNET_break (0);
   4491           pay_end (pc,
   4492                    TALER_MHD_reply_with_error (
   4493                      pc->connection,
   4494                      MHD_HTTP_BAD_REQUEST,
   4495                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISSING,
   4496                      NULL));
   4497           return;
   4498         }
   4499         if (pc->parse_wallet_data.choice_index >=
   4500             pc->check_contract.contract_terms->details.v1.choices_len)
   4501         {
   4502           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4503                       "Order `%s' has choices array with %u elements but "
   4504                       "request has 'choice_index' field with value %d\n",
   4505                       pc->order_id,
   4506                       pc->check_contract.contract_terms->details.v1.choices_len,
   4507                       pc->parse_wallet_data.choice_index);
   4508           GNUNET_break (0);
   4509           pay_end (pc,
   4510                    TALER_MHD_reply_with_error (
   4511                      pc->connection,
   4512                      MHD_HTTP_BAD_REQUEST,
   4513                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS,
   4514                      NULL));
   4515           return;
   4516         }
   4517       }
   4518       break;
   4519     default:
   4520       GNUNET_break (0);
   4521       pay_end (pc,
   4522                TALER_MHD_reply_with_error (
   4523                  pc->connection,
   4524                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4525                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   4526                  "contract 'version' in database not supported by this backend")
   4527                );
   4528       return;
   4529     }
   4530   }
   4531 
   4532   if (GNUNET_TIME_timestamp_cmp (pc->check_contract.contract_terms->
   4533                                  wire_deadline,
   4534                                  <,
   4535                                  pc->check_contract.contract_terms->
   4536                                  refund_deadline))
   4537   {
   4538     /* This should already have been checked when creating the order! */
   4539     GNUNET_break (0);
   4540     pay_end (pc,
   4541              TALER_MHD_reply_with_error (
   4542                pc->connection,
   4543                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4544                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE,
   4545                NULL));
   4546     return;
   4547   }
   4548   if (GNUNET_TIME_absolute_is_past (pc->check_contract.contract_terms->
   4549                                     pay_deadline.abs_time))
   4550   {
   4551     /* too late */
   4552     pay_end (pc,
   4553              TALER_MHD_reply_with_error (
   4554                pc->connection,
   4555                MHD_HTTP_GONE,
   4556                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED,
   4557                NULL));
   4558     return;
   4559   }
   4560 
   4561 /* Make sure wire method (still) exists for this instance */
   4562   {
   4563     struct TMH_WireMethod *wm;
   4564 
   4565     wm = pc->hc->instance->wm_head;
   4566     while (0 != GNUNET_memcmp (&pc->check_contract.contract_terms->h_wire,
   4567                                &wm->h_wire))
   4568       wm = wm->next;
   4569     if (NULL == wm)
   4570     {
   4571       GNUNET_break (0);
   4572       pay_end (pc,
   4573                TALER_MHD_reply_with_error (
   4574                  pc->connection,
   4575                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4576                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_HASH_UNKNOWN,
   4577                  NULL));
   4578       return;
   4579     }
   4580     pc->check_contract.wm = wm;
   4581   }
   4582   pc->phase = PP_VALIDATE_TOKENS;
   4583 }
   4584 
   4585 
   4586 /**
   4587  * Try to parse the wallet_data object of the pay request into
   4588  * the given context. Schedules an error response in the connection
   4589  * on failure.
   4590  *
   4591  * @param[in,out] pc context we use to handle the payment
   4592  */
   4593 static void
   4594 phase_parse_wallet_data (struct PayContext *pc)
   4595 {
   4596   const json_t *tokens_evs;
   4597   const json_t *donau_obj;
   4598 
   4599   struct GNUNET_JSON_Specification spec[] = {
   4600     GNUNET_JSON_spec_mark_optional (
   4601       GNUNET_JSON_spec_int16 ("choice_index",
   4602                               &pc->parse_wallet_data.choice_index),
   4603       NULL),
   4604     GNUNET_JSON_spec_mark_optional (
   4605       GNUNET_JSON_spec_array_const ("tokens_evs",
   4606                                     &tokens_evs),
   4607       NULL),
   4608     GNUNET_JSON_spec_mark_optional (
   4609       GNUNET_JSON_spec_object_const ("donau",
   4610                                      &donau_obj),
   4611       NULL),
   4612     GNUNET_JSON_spec_end ()
   4613   };
   4614 
   4615   pc->parse_wallet_data.choice_index = -1;
   4616   if (NULL == pc->parse_pay.wallet_data)
   4617   {
   4618     pc->phase = PP_CHECK_CONTRACT;
   4619     return;
   4620   }
   4621   {
   4622     enum GNUNET_GenericReturnValue res;
   4623 
   4624     res = TALER_MHD_parse_json_data (pc->connection,
   4625                                      pc->parse_pay.wallet_data,
   4626                                      spec);
   4627     if (GNUNET_YES != res)
   4628     {
   4629       GNUNET_break_op (0);
   4630       pay_end (pc,
   4631                (GNUNET_NO == res)
   4632              ? MHD_YES
   4633              : MHD_NO);
   4634       return;
   4635     }
   4636   }
   4637 
   4638   pc->parse_wallet_data.token_envelopes_cnt
   4639     = json_array_size (tokens_evs);
   4640   if (pc->parse_wallet_data.token_envelopes_cnt >
   4641       MAX_TOKEN_ALLOWED_OUTPUTS)
   4642   {
   4643     GNUNET_break_op (0);
   4644     pay_end (pc,
   4645              TALER_MHD_reply_with_error (
   4646                pc->connection,
   4647                MHD_HTTP_BAD_REQUEST,
   4648                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4649                "'tokens_evs' array too long"));
   4650     return;
   4651   }
   4652   pc->parse_wallet_data.token_envelopes
   4653     = GNUNET_new_array (pc->parse_wallet_data.token_envelopes_cnt,
   4654                         struct TokenEnvelope);
   4655 
   4656   {
   4657     unsigned int tokens_ev_index;
   4658     json_t *token_ev;
   4659 
   4660     json_array_foreach (tokens_evs,
   4661                         tokens_ev_index,
   4662                         token_ev)
   4663     {
   4664       struct TokenEnvelope *ev
   4665         = &pc->parse_wallet_data.token_envelopes[tokens_ev_index];
   4666       struct GNUNET_JSON_Specification ispec[] = {
   4667         TALER_JSON_spec_token_envelope (NULL,
   4668                                         &ev->blinded_token),
   4669         GNUNET_JSON_spec_end ()
   4670       };
   4671       enum GNUNET_GenericReturnValue res;
   4672 
   4673       if (json_is_null (token_ev))
   4674         continue;
   4675       res = TALER_MHD_parse_json_data (pc->connection,
   4676                                        token_ev,
   4677                                        ispec);
   4678       if (GNUNET_YES != res)
   4679       {
   4680         GNUNET_break_op (0);
   4681         pay_end (pc,
   4682                  (GNUNET_NO == res)
   4683                  ? MHD_YES
   4684                  : MHD_NO);
   4685         return;
   4686       }
   4687 
   4688       for (unsigned int j = 0; j<tokens_ev_index; j++)
   4689       {
   4690         if (0 ==
   4691             GNUNET_memcmp (ev->blinded_token.blinded_pub,
   4692                            pc->parse_wallet_data.token_envelopes[j].
   4693                            blinded_token.blinded_pub))
   4694         {
   4695           GNUNET_break_op (0);
   4696           pay_end (pc,
   4697                    TALER_MHD_reply_with_error (
   4698                      pc->connection,
   4699                      MHD_HTTP_BAD_REQUEST,
   4700                      TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4701                      "duplicate token envelope in list"));
   4702           return;
   4703         }
   4704       }
   4705     }
   4706   }
   4707 
   4708   if (NULL != donau_obj)
   4709   {
   4710     const char *donau_url_tmp;
   4711     const json_t *budikeypairs;
   4712     json_t *donau_keys_json;
   4713 
   4714     /* Fetching and checking that all 3 are present in some way */
   4715     struct GNUNET_JSON_Specification dspec[] = {
   4716       GNUNET_JSON_spec_string      ("url",
   4717                                     &donau_url_tmp),
   4718       GNUNET_JSON_spec_uint64      ("year",
   4719                                     &pc->parse_wallet_data.donau.donation_year),
   4720       GNUNET_JSON_spec_array_const ("budikeypairs",
   4721                                     &budikeypairs),
   4722       GNUNET_JSON_spec_end ()
   4723     };
   4724     enum GNUNET_GenericReturnValue res;
   4725 
   4726     res = TALER_MHD_parse_json_data (pc->connection,
   4727                                      donau_obj,
   4728                                      dspec);
   4729     if (GNUNET_YES != res)
   4730     {
   4731       GNUNET_break_op (0);
   4732       pay_end (pc,
   4733                (GNUNET_NO == res)
   4734                ? MHD_YES
   4735                : MHD_NO);
   4736       return;
   4737     }
   4738 
   4739     /* Check if the needed data is present for the given donau URL */
   4740     {
   4741       enum GNUNET_DB_QueryStatus qs;
   4742 
   4743       qs = TALER_MERCHANTDB_lookup_order_charity (
   4744         TMH_db,
   4745         pc->hc->instance->settings.id,
   4746         donau_url_tmp,
   4747         &pc->parse_wallet_data.charity_id,
   4748         &pc->parse_wallet_data.charity_priv,
   4749         &pc->parse_wallet_data.charity_max_per_year,
   4750         &pc->parse_wallet_data.charity_receipts_to_date,
   4751         &donau_keys_json,
   4752         &pc->parse_wallet_data.donau_instance_serial);
   4753 
   4754       switch (qs)
   4755       {
   4756       case GNUNET_DB_STATUS_HARD_ERROR:
   4757       case GNUNET_DB_STATUS_SOFT_ERROR:
   4758         TALER_MERCHANTDB_rollback (TMH_db);
   4759         pay_end (pc,
   4760                  TALER_MHD_reply_with_error (
   4761                    pc->connection,
   4762                    MHD_HTTP_INTERNAL_SERVER_ERROR,
   4763                    TALER_EC_GENERIC_DB_FETCH_FAILED,
   4764                    "lookup_order_charity"));
   4765         return;
   4766       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   4767         TALER_MERCHANTDB_rollback (TMH_db);
   4768         pay_end (pc,
   4769                  TALER_MHD_reply_with_error (
   4770                    pc->connection,
   4771                    MHD_HTTP_NOT_FOUND,
   4772                    TALER_EC_MERCHANT_GENERIC_DONAU_CHARITY_UNKNOWN,
   4773                    donau_url_tmp));
   4774         return;
   4775       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   4776         pc->parse_wallet_data.donau.donau_url =
   4777           GNUNET_strdup (donau_url_tmp);
   4778         break;
   4779       }
   4780     }
   4781 
   4782     {
   4783       pc->parse_wallet_data.donau_keys =
   4784         DONAU_keys_from_json (donau_keys_json);
   4785       json_decref (donau_keys_json);
   4786       if (NULL == pc->parse_wallet_data.donau_keys)
   4787       {
   4788         GNUNET_break_op (0);
   4789         pay_end (pc,
   4790                  TALER_MHD_reply_with_error (pc->connection,
   4791                                              MHD_HTTP_BAD_REQUEST,
   4792                                              TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4793                                              "Invalid donau_keys"));
   4794         return;
   4795       }
   4796     }
   4797 
   4798     /* Stage to parse the budikeypairs from json to struct */
   4799     if (0 != json_array_size (budikeypairs))
   4800     {
   4801       size_t num_bkps = json_array_size (budikeypairs);
   4802       struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps =
   4803         GNUNET_new_array (num_bkps,
   4804                           struct DONAU_BlindedUniqueDonorIdentifierKeyPair);
   4805 
   4806       /* Change to json for each*/
   4807       for (size_t i = 0; i < num_bkps; i++)
   4808       {
   4809         const json_t *bkp_obj = json_array_get (budikeypairs,
   4810                                                 i);
   4811         if (GNUNET_SYSERR ==
   4812             merchant_parse_json_bkp (&bkps[i],
   4813                                      bkp_obj))
   4814         {
   4815           GNUNET_break_op (0);
   4816           for (size_t j = 0; j < i; j++)
   4817             GNUNET_CRYPTO_blinded_message_decref (
   4818               bkps[j].blinded_udi.blinded_message);
   4819           GNUNET_free (bkps);
   4820           pay_end (pc,
   4821                    TALER_MHD_reply_with_error (pc->connection,
   4822                                                MHD_HTTP_BAD_REQUEST,
   4823                                                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4824                                                "Failed to parse budikeypairs"));
   4825           return;
   4826         }
   4827       }
   4828 
   4829       pc->parse_wallet_data.num_bkps = num_bkps;
   4830       pc->parse_wallet_data.bkps = bkps;
   4831     }
   4832   }
   4833   TALER_json_hash (pc->parse_pay.wallet_data,
   4834                    &pc->parse_wallet_data.h_wallet_data);
   4835 
   4836   pc->phase = PP_CHECK_CONTRACT;
   4837 }
   4838 
   4839 
   4840 /**
   4841  * Try to parse the pay request into the given pay context.
   4842  * Schedules an error response in the connection on failure.
   4843  *
   4844  * @param[in,out] pc context we use to handle the payment
   4845  */
   4846 static void
   4847 phase_parse_pay (struct PayContext *pc)
   4848 {
   4849   const char *session_id = NULL;
   4850   const json_t *coins;
   4851   const json_t *tokens;
   4852   struct GNUNET_JSON_Specification spec[] = {
   4853     GNUNET_JSON_spec_array_const ("coins",
   4854                                   &coins),
   4855     GNUNET_JSON_spec_mark_optional (
   4856       GNUNET_JSON_spec_string ("session_id",
   4857                                &session_id),
   4858       NULL),
   4859     GNUNET_JSON_spec_mark_optional (
   4860       GNUNET_JSON_spec_object_const ("wallet_data",
   4861                                      &pc->parse_pay.wallet_data),
   4862       NULL),
   4863     GNUNET_JSON_spec_mark_optional (
   4864       GNUNET_JSON_spec_array_const ("tokens",
   4865                                     &tokens),
   4866       NULL),
   4867     GNUNET_JSON_spec_end ()
   4868   };
   4869 
   4870 #if DEBUG
   4871   {
   4872     char *dump = json_dumps (pc->hc->request_body,
   4873                              JSON_INDENT (2)
   4874                              | JSON_ENCODE_ANY
   4875                              | JSON_SORT_KEYS);
   4876 
   4877     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4878                 "POST /orders/%s/pay – request body follows:\n%s\n",
   4879                 pc->order_id,
   4880                 dump);
   4881 
   4882     free (dump);
   4883 
   4884   }
   4885 #endif /* DEBUG */
   4886 
   4887   GNUNET_assert (PP_PARSE_PAY == pc->phase);
   4888   {
   4889     enum GNUNET_GenericReturnValue res;
   4890 
   4891     res = TALER_MHD_parse_json_data (pc->connection,
   4892                                      pc->hc->request_body,
   4893                                      spec);
   4894     if (GNUNET_YES != res)
   4895     {
   4896       GNUNET_break_op (0);
   4897       pay_end (pc,
   4898                (GNUNET_NO == res)
   4899                ? MHD_YES
   4900                : MHD_NO);
   4901       return;
   4902     }
   4903   }
   4904 
   4905   /* copy session ID (if set) */
   4906   if (NULL != session_id)
   4907   {
   4908     pc->parse_pay.session_id = GNUNET_strdup (session_id);
   4909   }
   4910   else
   4911   {
   4912     /* use empty string as default if client didn't specify it */
   4913     pc->parse_pay.session_id = GNUNET_strdup ("");
   4914   }
   4915 
   4916   pc->parse_pay.coins_cnt = json_array_size (coins);
   4917   if (pc->parse_pay.coins_cnt > MAX_COIN_ALLOWED_COINS)
   4918   {
   4919     GNUNET_break_op (0);
   4920     pay_end (pc,
   4921              TALER_MHD_reply_with_error (
   4922                pc->connection,
   4923                MHD_HTTP_BAD_REQUEST,
   4924                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4925                "'coins' array too long"));
   4926     return;
   4927   }
   4928   /* note: 1 coin = 1 deposit confirmation expected */
   4929   pc->parse_pay.dc = GNUNET_new_array (pc->parse_pay.coins_cnt,
   4930                                        struct DepositConfirmation);
   4931 
   4932   /* This loop populates the array 'dc' in 'pc' */
   4933   {
   4934     unsigned int coins_index;
   4935     json_t *coin;
   4936 
   4937     json_array_foreach (coins, coins_index, coin)
   4938     {
   4939       struct DepositConfirmation *dc = &pc->parse_pay.dc[coins_index];
   4940       const char *exchange_url;
   4941       struct GNUNET_JSON_Specification ispec[] = {
   4942         GNUNET_JSON_spec_fixed_auto ("coin_sig",
   4943                                      &dc->cdd.coin_sig),
   4944         GNUNET_JSON_spec_fixed_auto ("coin_pub",
   4945                                      &dc->cdd.coin_pub),
   4946         TALER_JSON_spec_denom_sig ("ub_sig",
   4947                                    &dc->cdd.denom_sig),
   4948         GNUNET_JSON_spec_fixed_auto ("h_denom",
   4949                                      &dc->cdd.h_denom_pub),
   4950         TALER_JSON_spec_amount_any ("contribution",
   4951                                     &dc->cdd.amount),
   4952         TALER_JSON_spec_web_url ("exchange_url",
   4953                                  &exchange_url),
   4954         /* if a minimum age was required, the minimum_age_sig and
   4955          * age_commitment must be provided */
   4956         GNUNET_JSON_spec_mark_optional (
   4957           GNUNET_JSON_spec_fixed_auto ("minimum_age_sig",
   4958                                        &dc->minimum_age_sig),
   4959           &dc->no_minimum_age_sig),
   4960         GNUNET_JSON_spec_mark_optional (
   4961           TALER_JSON_spec_age_commitment ("age_commitment",
   4962                                           &dc->age_commitment),
   4963           &dc->no_age_commitment),
   4964         /* if minimum age was not required, but coin with age restriction set
   4965          * was used, h_age_commitment must be provided. */
   4966         GNUNET_JSON_spec_mark_optional (
   4967           GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
   4968                                        &dc->cdd.h_age_commitment),
   4969           &dc->no_h_age_commitment),
   4970         GNUNET_JSON_spec_end ()
   4971       };
   4972       enum GNUNET_GenericReturnValue res;
   4973       struct ExchangeGroup *eg = NULL;
   4974 
   4975       res = TALER_MHD_parse_json_data (pc->connection,
   4976                                        coin,
   4977                                        ispec);
   4978       if (GNUNET_YES != res)
   4979       {
   4980         GNUNET_break_op (0);
   4981         pay_end (pc,
   4982                  (GNUNET_NO == res)
   4983                  ? MHD_YES
   4984                  : MHD_NO);
   4985         return;
   4986       }
   4987       for (unsigned int j = 0; j<coins_index; j++)
   4988       {
   4989         if (0 ==
   4990             GNUNET_memcmp (&dc->cdd.coin_pub,
   4991                            &pc->parse_pay.dc[j].cdd.coin_pub))
   4992         {
   4993           GNUNET_break_op (0);
   4994           pay_end (pc,
   4995                    TALER_MHD_reply_with_error (pc->connection,
   4996                                                MHD_HTTP_BAD_REQUEST,
   4997                                                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4998                                                "duplicate coin in list"));
   4999           return;
   5000         }
   5001       }
   5002 
   5003       dc->exchange_url = GNUNET_strdup (exchange_url);
   5004       dc->index = coins_index;
   5005       dc->pc = pc;
   5006 
   5007       /* Check the consistency of the (potential) age restriction
   5008        * information. */
   5009       if (dc->no_age_commitment != dc->no_minimum_age_sig)
   5010       {
   5011         GNUNET_break_op (0);
   5012         pay_end (pc,
   5013                  TALER_MHD_reply_with_error (
   5014                    pc->connection,
   5015                    MHD_HTTP_BAD_REQUEST,
   5016                    TALER_EC_GENERIC_PARAMETER_MALFORMED,
   5017                    "inconsistent: 'age_commitment' vs. 'minimum_age_sig'"
   5018                    ));
   5019         return;
   5020       }
   5021 
   5022       /* Setup exchange group */
   5023       for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
   5024       {
   5025         if (0 ==
   5026             strcmp (pc->parse_pay.egs[i]->exchange_url,
   5027                     exchange_url))
   5028         {
   5029           eg = pc->parse_pay.egs[i];
   5030           break;
   5031         }
   5032       }
   5033       if (NULL == eg)
   5034       {
   5035         eg = GNUNET_new (struct ExchangeGroup);
   5036         eg->pc = pc;
   5037         eg->exchange_url = dc->exchange_url;
   5038         eg->total = dc->cdd.amount;
   5039         GNUNET_array_append (pc->parse_pay.egs,
   5040                              pc->parse_pay.num_exchanges,
   5041                              eg);
   5042       }
   5043       else
   5044       {
   5045         if (0 >
   5046             TALER_amount_add (&eg->total,
   5047                               &eg->total,
   5048                               &dc->cdd.amount))
   5049         {
   5050           GNUNET_break_op (0);
   5051           pay_end (pc,
   5052                    TALER_MHD_reply_with_error (
   5053                      pc->connection,
   5054                      MHD_HTTP_INTERNAL_SERVER_ERROR,
   5055                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   5056                      "Overflow adding up amounts"));
   5057           return;
   5058         }
   5059       }
   5060     }
   5061   }
   5062 
   5063   pc->parse_pay.tokens_cnt = json_array_size (tokens);
   5064   if (pc->parse_pay.tokens_cnt > MAX_TOKEN_ALLOWED_INPUTS)
   5065   {
   5066     GNUNET_break_op (0);
   5067     pay_end (pc,
   5068              TALER_MHD_reply_with_error (
   5069                pc->connection,
   5070                MHD_HTTP_BAD_REQUEST,
   5071                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   5072                "'tokens' array too long"));
   5073     return;
   5074   }
   5075 
   5076   pc->parse_pay.tokens = GNUNET_new_array (pc->parse_pay.tokens_cnt,
   5077                                            struct TokenUseConfirmation);
   5078 
   5079   /* This loop populates the array 'tokens' in 'pc' */
   5080   {
   5081     unsigned int tokens_index;
   5082     json_t *token;
   5083 
   5084     json_array_foreach (tokens, tokens_index, token)
   5085     {
   5086       struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[tokens_index];
   5087       struct GNUNET_JSON_Specification ispec[] = {
   5088         GNUNET_JSON_spec_fixed_auto ("token_sig",
   5089                                      &tuc->sig),
   5090         GNUNET_JSON_spec_fixed_auto ("token_pub",
   5091                                      &tuc->pub),
   5092         GNUNET_JSON_spec_fixed_auto ("h_issue",
   5093                                      &tuc->h_issue),
   5094         TALER_JSON_spec_token_issue_sig ("ub_sig",
   5095                                          &tuc->unblinded_sig),
   5096         GNUNET_JSON_spec_end ()
   5097       };
   5098       enum GNUNET_GenericReturnValue res;
   5099 
   5100       res = TALER_MHD_parse_json_data (pc->connection,
   5101                                        token,
   5102                                        ispec);
   5103       if (GNUNET_YES != res)
   5104       {
   5105         GNUNET_break_op (0);
   5106         pay_end (pc,
   5107                  (GNUNET_NO == res)
   5108                  ? MHD_YES
   5109                  : MHD_NO);
   5110         return;
   5111       }
   5112 
   5113       for (unsigned int j = 0; j<tokens_index; j++)
   5114       {
   5115         if (0 ==
   5116             GNUNET_memcmp (&tuc->pub,
   5117                            &pc->parse_pay.tokens[j].pub))
   5118         {
   5119           GNUNET_break_op (0);
   5120           pay_end (pc,
   5121                    TALER_MHD_reply_with_error (pc->connection,
   5122                                                MHD_HTTP_BAD_REQUEST,
   5123                                                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   5124                                                "duplicate token in list"));
   5125           return;
   5126         }
   5127       }
   5128     }
   5129   }
   5130 
   5131   pc->phase = PP_PARSE_WALLET_DATA;
   5132 }
   5133 
   5134 
   5135 /**
   5136  * Custom cleanup routine for a `struct PayContext`.
   5137  *
   5138  * @param cls the `struct PayContext` to clean up.
   5139  */
   5140 static void
   5141 pay_context_cleanup (void *cls)
   5142 {
   5143   struct PayContext *pc = cls;
   5144 
   5145   if (NULL != pc->batch_deposits.timeout_task)
   5146   {
   5147     GNUNET_SCHEDULER_cancel (pc->batch_deposits.timeout_task);
   5148     pc->batch_deposits.timeout_task = NULL;
   5149   }
   5150   if (NULL != pc->check_contract.contract_terms_json)
   5151   {
   5152     json_decref (pc->check_contract.contract_terms_json);
   5153     pc->check_contract.contract_terms_json = NULL;
   5154   }
   5155   for (unsigned int i = 0; i<pc->parse_pay.coins_cnt; i++)
   5156   {
   5157     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   5158 
   5159     TALER_denom_sig_free (&dc->cdd.denom_sig);
   5160     GNUNET_free (dc->exchange_url);
   5161   }
   5162   GNUNET_free (pc->parse_pay.dc);
   5163   for (unsigned int i = 0; i<pc->parse_pay.tokens_cnt; i++)
   5164   {
   5165     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   5166 
   5167     TALER_token_issue_sig_free (&tuc->unblinded_sig);
   5168   }
   5169   GNUNET_free (pc->parse_pay.tokens);
   5170   for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
   5171   {
   5172     struct ExchangeGroup *eg = pc->parse_pay.egs[i];
   5173 
   5174     if (NULL != eg->fo)
   5175       TMH_EXCHANGES_keys4exchange_cancel (eg->fo);
   5176     if (NULL != eg->bdh)
   5177       TALER_EXCHANGE_post_batch_deposit_cancel (eg->bdh);
   5178     if (NULL != eg->keys)
   5179       TALER_EXCHANGE_keys_decref (eg->keys);
   5180     GNUNET_free (eg);
   5181   }
   5182   GNUNET_free (pc->parse_pay.egs);
   5183   if (NULL != pc->check_contract.contract_terms)
   5184   {
   5185     TALER_MERCHANT_contract_free (pc->check_contract.contract_terms);
   5186     pc->check_contract.contract_terms = NULL;
   5187   }
   5188   if (NULL != pc->response)
   5189   {
   5190     MHD_destroy_response (pc->response);
   5191     pc->response = NULL;
   5192   }
   5193   GNUNET_free (pc->parse_pay.session_id);
   5194   GNUNET_CONTAINER_DLL_remove (pc_head,
   5195                                pc_tail,
   5196                                pc);
   5197   GNUNET_free (pc->check_contract.pos_key);
   5198   GNUNET_free (pc->compute_money_pots.pots);
   5199   GNUNET_free (pc->compute_money_pots.increments);
   5200   if (NULL != pc->parse_wallet_data.bkps)
   5201   {
   5202     for (size_t i = 0; i < pc->parse_wallet_data.num_bkps; i++)
   5203       GNUNET_CRYPTO_blinded_message_decref (
   5204         pc->parse_wallet_data.bkps[i].blinded_udi.blinded_message);
   5205     GNUNET_array_grow (pc->parse_wallet_data.bkps,
   5206                        pc->parse_wallet_data.num_bkps,
   5207                        0);
   5208   }
   5209   if (NULL != pc->parse_wallet_data.donau_keys)
   5210   {
   5211     DONAU_keys_decref (pc->parse_wallet_data.donau_keys);
   5212     pc->parse_wallet_data.donau_keys = NULL;
   5213   }
   5214   GNUNET_free (pc->parse_wallet_data.donau.donau_url);
   5215   for (unsigned int i = 0; i<pc->parse_wallet_data.token_envelopes_cnt; i++)
   5216   {
   5217     struct TokenEnvelope *ev
   5218       = &pc->parse_wallet_data.token_envelopes[i];
   5219 
   5220     GNUNET_CRYPTO_blinded_message_decref (ev->blinded_token.blinded_pub);
   5221   }
   5222   GNUNET_free (pc->parse_wallet_data.token_envelopes);
   5223   if (NULL != pc->output_tokens)
   5224   {
   5225     for (unsigned int i = 0; i<pc->output_tokens_len; i++)
   5226       if (NULL != pc->output_tokens[i].sig.signature)
   5227         GNUNET_CRYPTO_blinded_sig_decref (pc->output_tokens[i].sig.signature);
   5228     GNUNET_free (pc->output_tokens);
   5229     pc->output_tokens = NULL;
   5230   }
   5231   GNUNET_free (pc);
   5232 }
   5233 
   5234 
   5235 enum MHD_Result
   5236 TMH_post_orders_ID_pay (const struct TMH_RequestHandler *rh,
   5237                         struct MHD_Connection *connection,
   5238                         struct TMH_HandlerContext *hc)
   5239 {
   5240   struct PayContext *pc = hc->ctx;
   5241 
   5242   GNUNET_assert (NULL != hc->infix);
   5243   if (NULL == pc)
   5244   {
   5245     pc = GNUNET_new (struct PayContext);
   5246     pc->connection = connection;
   5247     pc->hc = hc;
   5248     pc->order_id = hc->infix;
   5249     hc->ctx = pc;
   5250     hc->cc = &pay_context_cleanup;
   5251     GNUNET_CONTAINER_DLL_insert (pc_head,
   5252                                  pc_tail,
   5253                                  pc);
   5254   }
   5255   while (1)
   5256   {
   5257     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5258                 "Processing /pay in phase %d\n",
   5259                 (int) pc->phase);
   5260     switch (pc->phase)
   5261     {
   5262     case PP_PARSE_PAY:
   5263       phase_parse_pay (pc);
   5264       break;
   5265     case PP_PARSE_WALLET_DATA:
   5266       phase_parse_wallet_data (pc);
   5267       break;
   5268     case PP_CHECK_CONTRACT:
   5269       phase_check_contract (pc);
   5270       break;
   5271     case PP_VALIDATE_TOKENS:
   5272       phase_validate_tokens (pc);
   5273       break;
   5274     case PP_CONTRACT_PAID:
   5275       phase_contract_paid (pc);
   5276       break;
   5277     case PP_COMPUTE_MONEY_POTS:
   5278       phase_compute_money_pots (pc);
   5279       break;
   5280     case PP_PAY_TRANSACTION:
   5281       phase_execute_pay_transaction (pc);
   5282       break;
   5283     case PP_REQUEST_DONATION_RECEIPT:
   5284       phase_request_donation_receipt (pc);
   5285       break;
   5286     case PP_FINAL_OUTPUT_TOKEN_PROCESSING:
   5287       phase_final_output_token_processing (pc);
   5288       break;
   5289     case PP_PAYMENT_NOTIFICATION:
   5290       phase_payment_notification (pc);
   5291       break;
   5292     case PP_SUCCESS_RESPONSE:
   5293       phase_success_response (pc);
   5294       break;
   5295     case PP_BATCH_DEPOSITS:
   5296       phase_batch_deposits (pc);
   5297       break;
   5298     case PP_RETURN_RESPONSE:
   5299       phase_return_response (pc);
   5300       break;
   5301     case PP_FAIL_LEGAL_REASONS:
   5302       phase_fail_for_legal_reasons (pc);
   5303       break;
   5304     case PP_END_YES:
   5305       return MHD_YES;
   5306     case PP_END_NO:
   5307       return MHD_NO;
   5308     default:
   5309       /* should not be reachable */
   5310       GNUNET_assert (0);
   5311       return MHD_NO;
   5312     }
   5313     switch (pc->suspended)
   5314     {
   5315     case GNUNET_SYSERR:
   5316       /* during shutdown, we don't generate any more replies */
   5317       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5318                   "Processing /pay ends due to shutdown in phase %d\n",
   5319                   (int) pc->phase);
   5320       return MHD_NO;
   5321     case GNUNET_NO:
   5322       /* continue to next phase */
   5323       break;
   5324     case GNUNET_YES:
   5325       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5326                   "Processing /pay suspended in phase %d\n",
   5327                   (int) pc->phase);
   5328       return MHD_YES;
   5329     }
   5330   }
   5331   /* impossible to get here */
   5332   GNUNET_assert (0);
   5333   return MHD_YES;
   5334 }
   5335 
   5336 
   5337 /* end of taler-merchant-httpd_post-orders-ORDER_ID-pay.c */