merchant

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

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


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