do_recoup.sql (4242B)
1 -- 2 -- This file is part of TALER 3 -- Copyright (C) 2014--2022 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 -- When parameter names have changed, we can not REPLACE 18 -- but need to drop first 19 DROP FUNCTION IF EXISTS exchange_do_recoup_to_reserve; 20 21 CREATE FUNCTION exchange_do_recoup_to_reserve( 22 IN in_reserve_pub BYTEA, 23 IN in_withdraw_id INT8, 24 IN in_coin_index INT4, 25 IN in_coin_blind BYTEA, 26 IN in_coin_pub BYTEA, 27 IN in_known_coin_id INT8, 28 IN in_coin_sig BYTEA, 29 IN in_reserve_gc INT8, 30 IN in_reserve_expiration INT8, 31 IN in_recoup_timestamp INT8, 32 OUT out_recoup_ok BOOLEAN, 33 OUT out_internal_failure BOOLEAN, 34 OUT out_recoup_timestamp INT8, 35 OUT out_recoup_amount taler_amount) 36 LANGUAGE plpgsql 37 AS $$ 38 DECLARE 39 tmp taler_amount; -- amount recouped 40 balance taler_amount; -- current balance of the reserve 41 new_balance taler_amount; -- new balance of the reserve 42 reserve RECORD; 43 rval RECORD; 44 BEGIN 45 -- Shards: SELECT known_coins (by coin_pub) 46 -- SELECT recoup (by coin_pub) 47 -- UPDATE known_coins (by coin_pub) 48 -- UPDATE reserves (by reserve_pub) 49 -- INSERT recoup (by coin_pub) 50 51 out_internal_failure=FALSE; 52 53 54 -- Check remaining balance of the coin. 55 SELECT 56 remaining 57 INTO 58 rval 59 FROM exchange.known_coins 60 WHERE coin_pub=in_coin_pub; 61 62 IF NOT FOUND 63 THEN 64 out_internal_failure=TRUE; 65 out_recoup_ok=FALSE; 66 RETURN; 67 END IF; 68 69 tmp := rval.remaining; 70 71 IF tmp.val + tmp.frac = 0 72 THEN 73 -- Check for idempotency: only a recoup for this very 74 -- withdraw operation and position counts, a recoup of the same 75 -- coin for another operation means the coin has nothing left. 76 -- The coin may have been credited again (by a refund) and 77 -- recouped again since, so report the latest recoup. 78 SELECT 79 recoup_timestamp 80 ,amount 81 INTO 82 rval 83 FROM exchange.recoup 84 WHERE coin_pub=in_coin_pub 85 AND withdraw_id=in_withdraw_id 86 AND coin_index=in_coin_index 87 ORDER BY recoup_uuid DESC 88 LIMIT 1; 89 90 out_recoup_ok=FOUND; 91 IF FOUND 92 THEN 93 out_recoup_timestamp=rval.recoup_timestamp; 94 out_recoup_amount=rval.amount; 95 END IF; 96 RETURN; 97 END IF; 98 99 100 -- Update balance of the coin. 101 UPDATE known_coins 102 SET 103 remaining.val = 0 104 ,remaining.frac = 0 105 WHERE coin_pub=in_coin_pub; 106 107 -- Get current balance 108 SELECT current_balance 109 INTO reserve 110 FROM reserves 111 WHERE reserve_pub=in_reserve_pub; 112 113 balance = reserve.current_balance; 114 new_balance.frac=balance.frac+tmp.frac 115 - CASE 116 WHEN balance.frac+tmp.frac >= 100000000 117 THEN 100000000 118 ELSE 0 119 END; 120 121 new_balance.val=balance.val+tmp.val 122 + CASE 123 WHEN balance.frac+tmp.frac >= 100000000 124 THEN 1 125 ELSE 0 126 END; 127 128 -- Credit the reserve and update reserve timers. 129 UPDATE reserves 130 SET 131 current_balance = new_balance, 132 gc_date=GREATEST(gc_date, in_reserve_gc), 133 expiration_date=GREATEST(expiration_date, in_reserve_expiration) 134 WHERE reserve_pub=in_reserve_pub; 135 136 137 IF NOT FOUND 138 THEN 139 RAISE NOTICE 'failed to increase reserve balance from recoup'; 140 out_recoup_ok=TRUE; 141 out_internal_failure=TRUE; 142 RETURN; 143 END IF; 144 145 146 INSERT INTO exchange.recoup 147 (coin_pub 148 ,coin_sig 149 ,coin_blind 150 ,amount 151 ,recoup_timestamp 152 ,withdraw_id 153 ,coin_index 154 ) 155 VALUES 156 (in_coin_pub 157 ,in_coin_sig 158 ,in_coin_blind 159 ,tmp 160 ,in_recoup_timestamp 161 ,in_withdraw_id 162 ,in_coin_index); 163 164 -- Normal end, everything is fine. 165 out_recoup_ok=TRUE; 166 out_recoup_timestamp=in_recoup_timestamp; 167 out_recoup_amount=tmp; 168 169 END $$; 170 171 -- COMMENT ON FUNCTION exchange_do_recoup_to_reserve(INT8, INT4, BYTEA, BOOLEAN, BOOLEAN) 172 -- IS 'Executes a recoup of a coin that was withdrawn from a reserve';