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