exchange_do_check_deposit_idempotent.sql (3616B)
1 -- 2 -- This file is part of TALER 3 -- Copyright (C) 2024 Taler Systems SA 4 -- 5 -- TALER is free software; you can redistribute it and/or modify it under the 6 -- terms of the GNU General Public License as published by the Free Software 7 -- Foundation; either version 3, or (at your option) any later version. 8 -- 9 -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 -- 13 -- You should have received a copy of the GNU General Public License along with 14 -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 -- 16 17 DROP FUNCTION IF EXISTS exchange_do_check_deposit_idempotent; 18 CREATE FUNCTION exchange_do_check_deposit_idempotent( 19 -- For batch_deposits 20 IN in_shard INT8, 21 IN in_merchant_pub BYTEA, 22 IN in_wallet_timestamp INT8, 23 IN in_exchange_timestamp INT8, 24 IN in_refund_deadline INT8, 25 IN in_wire_deadline INT8, 26 IN in_h_contract_terms BYTEA, 27 IN in_wallet_data_hash BYTEA, -- can be NULL 28 IN in_wire_salt BYTEA, 29 IN in_wire_target_h_payto BYTEA, 30 IN in_policy_details_serial_id INT8, -- can be NULL 31 IN in_policy_blocked BOOLEAN, 32 -- For coin_deposits 33 IN ina_coin_pub BYTEA[], 34 IN ina_coin_sig BYTEA[], 35 IN ina_amount_with_fee taler_amount[], 36 OUT out_exchange_timestamp INT8, 37 OUT out_is_idempotent BOOL 38 ) 39 LANGUAGE plpgsql 40 AS $$ 41 DECLARE 42 wtsi INT8; -- wire target serial id 43 bdsi INT8; -- batch_deposits serial id 44 i INT4; 45 ini_amount_with_fee taler_amount; 46 ini_coin_pub BYTEA; 47 ini_coin_sig BYTEA; 48 BEGIN 49 -- Shards: 50 -- SELECT wire_targets (by h_payto); 51 -- INSERT batch_deposits (by shard, merchant_pub), ON CONFLICT idempotency check; 52 -- PERFORM[] coin_deposits (by coin_pub), ON CONFLICT idempotency check; 53 54 out_exchange_timestamp = in_exchange_timestamp; 55 56 -- First, get the 'wtsi' 57 SELECT wire_target_serial_id 58 INTO wtsi 59 FROM wire_targets 60 WHERE wire_target_h_payto=in_wire_target_h_payto; 61 62 IF NOT FOUND 63 THEN 64 out_is_idempotent = FALSE; 65 RETURN; 66 END IF; 67 68 69 -- Idempotency check: see if an identical record exists. 70 -- We do select over merchant_pub, h_contract_terms and wire_target_h_payto 71 -- first to maximally increase the chance of using the existing index. 72 SELECT 73 exchange_timestamp 74 ,batch_deposit_serial_id 75 INTO 76 out_exchange_timestamp 77 ,bdsi 78 FROM batch_deposits 79 WHERE shard=in_shard 80 AND merchant_pub=in_merchant_pub 81 AND h_contract_terms=in_h_contract_terms 82 AND wire_target_h_payto=in_wire_target_h_payto 83 -- now check the rest, too 84 AND ( (wallet_data_hash=in_wallet_data_hash) OR 85 (wallet_data_hash IS NULL AND in_wallet_data_hash IS NULL) ) 86 AND wire_salt=in_wire_salt 87 AND wallet_timestamp=in_wallet_timestamp 88 AND refund_deadline=in_refund_deadline 89 AND wire_deadline=in_wire_deadline 90 AND ( (policy_details_serial_id=in_policy_details_serial_id) OR 91 (policy_details_serial_id IS NULL AND in_policy_details_serial_id IS NULL) ); 92 93 IF NOT FOUND 94 THEN 95 out_is_idempotent=FALSE; 96 RETURN; 97 END IF; 98 99 100 -- Check each coin 101 102 FOR i IN 1..array_length(ina_coin_pub,1) 103 LOOP 104 ini_coin_pub = ina_coin_pub[i]; 105 ini_coin_sig = ina_coin_sig[i]; 106 ini_amount_with_fee = ina_amount_with_fee[i]; 107 108 PERFORM FROM coin_deposits 109 WHERE batch_deposit_serial_id=bdsi 110 AND coin_pub=ini_coin_pub 111 AND coin_sig=ini_coin_sig 112 AND amount_with_fee=ini_amount_with_fee; 113 IF NOT FOUND 114 THEN 115 out_is_idempotent=FALSE; 116 RETURN; 117 END IF; 118 END LOOP; -- end FOR all coins 119 120 out_is_idempotent=TRUE; 121 122 END $$;