merchant

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

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


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