merchant

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

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


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