do_recoup_refresh.sql (3744B)
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 DROP FUNCTION IF EXISTS exchange_do_recoup_to_coin; 18 CREATE FUNCTION exchange_do_recoup_to_coin( 19 IN in_old_coin_pub BYTEA, 20 IN in_refresh_id INT8, 21 IN in_coin_index INT4, 22 IN in_coin_blind BYTEA, 23 IN in_coin_pub BYTEA, 24 IN in_known_coin_id INT8, 25 IN in_coin_sig BYTEA, 26 IN in_recoup_timestamp INT8, 27 OUT out_recoup_ok BOOLEAN, 28 OUT out_internal_failure BOOLEAN, 29 OUT out_recoup_timestamp INT8, 30 OUT out_recoup_amount taler_amount) 31 LANGUAGE plpgsql 32 AS $$ 33 DECLARE 34 rval RECORD; 35 DECLARE 36 tmp taler_amount; -- amount recouped 37 BEGIN 38 39 -- Shards: UPDATE known_coins (by coin_pub) 40 -- SELECT recoup_refresh (by coin_pub) 41 -- UPDATE known_coins (by coin_pub) 42 -- INSERT recoup_refresh (by coin_pub) 43 44 out_internal_failure=FALSE; 45 46 -- Check remaining balance of the coin. 47 SELECT 48 remaining 49 INTO 50 rval 51 FROM exchange.known_coins 52 WHERE coin_pub=in_coin_pub; 53 54 IF NOT FOUND 55 THEN 56 out_internal_failure=TRUE; 57 out_recoup_ok=FALSE; 58 RETURN; 59 END IF; 60 61 tmp := rval.remaining; 62 63 IF tmp.val + tmp.frac = 0 64 THEN 65 -- Check for idempotency: only a recoup for this very 66 -- refresh operation and position counts, a recoup of the same 67 -- coin for another operation means the coin has nothing left. 68 -- The coin may have been credited again (by a refund) and 69 -- recouped again since, so report the latest recoup. 70 SELECT 71 recoup_timestamp 72 ,amount 73 INTO 74 rval 75 FROM recoup_refresh 76 WHERE coin_pub=in_coin_pub 77 AND refresh_id=in_refresh_id 78 AND coin_index=in_coin_index 79 ORDER BY recoup_refresh_uuid DESC 80 LIMIT 1; 81 out_recoup_ok=FOUND; 82 IF FOUND 83 THEN 84 out_recoup_timestamp=rval.recoup_timestamp; 85 out_recoup_amount=rval.amount; 86 END IF; 87 RETURN; 88 END IF; 89 90 -- Update balance of the coin. 91 UPDATE known_coins 92 SET 93 remaining.val = 0 94 ,remaining.frac = 0 95 WHERE coin_pub=in_coin_pub; 96 97 -- Credit the old coin. 98 UPDATE known_coins kc 99 SET 100 remaining.frac=(kc.remaining).frac+tmp.frac 101 - CASE 102 WHEN (kc.remaining).frac+tmp.frac >= 100000000 103 THEN 100000000 104 ELSE 0 105 END, 106 remaining.val=(kc.remaining).val+tmp.val 107 + CASE 108 WHEN (kc.remaining).frac+tmp.frac >= 100000000 109 THEN 1 110 ELSE 0 111 END 112 WHERE coin_pub=in_old_coin_pub; 113 114 IF NOT FOUND 115 THEN 116 RAISE NOTICE 'failed to increase old coin balance from recoup'; 117 out_recoup_ok=TRUE; 118 out_internal_failure=TRUE; 119 RETURN; 120 END IF; 121 122 123 INSERT INTO recoup_refresh 124 (coin_pub 125 ,known_coin_id 126 ,coin_sig 127 ,coin_blind 128 ,amount 129 ,recoup_timestamp 130 ,refresh_id 131 ,coin_index 132 ) 133 VALUES 134 (in_coin_pub 135 ,in_known_coin_id 136 ,in_coin_sig 137 ,in_coin_blind 138 ,tmp 139 ,in_recoup_timestamp 140 ,in_refresh_id 141 ,in_coin_index); 142 143 -- Normal end, everything is fine. 144 out_recoup_ok=TRUE; 145 out_recoup_timestamp=in_recoup_timestamp; 146 out_recoup_amount=tmp; 147 148 END $$; 149 150 151 -- COMMENT ON FUNCTION exchange_do_recoup_to_coin(INT8, INT4, BYTEA, BOOLEAN, BOOLEAN) 152 -- IS 'Executes a recoup-refresh of a coin that was obtained from a refresh-reveal process';