exchange_do_reserve_purse.sql (4122B)
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 CREATE OR REPLACE FUNCTION exchange_do_reserve_purse( 18 IN in_purse_pub BYTEA, 19 IN in_merge_sig BYTEA, 20 IN in_merge_timestamp INT8, 21 IN in_reserve_expiration INT8, 22 IN in_reserve_gc INT8, 23 IN in_reserve_sig BYTEA, 24 IN in_reserve_quota BOOLEAN, 25 IN in_purse_fee taler_amount, 26 IN in_reserve_pub BYTEA, 27 IN in_wallet_h_payto BYTEA, 28 OUT out_no_funds BOOLEAN, 29 OUT out_no_reserve BOOLEAN, 30 OUT out_conflict BOOLEAN) 31 LANGUAGE plpgsql 32 AS $$ 33 BEGIN 34 35 -- Store purse merge signature, checks for purse_pub uniqueness 36 INSERT INTO purse_merges 37 (partner_serial_id 38 ,reserve_pub 39 ,purse_pub 40 ,merge_sig 41 ,merge_timestamp) 42 VALUES 43 (NULL 44 ,in_reserve_pub 45 ,in_purse_pub 46 ,in_merge_sig 47 ,in_merge_timestamp) 48 ON CONFLICT DO NOTHING; 49 50 IF NOT FOUND 51 THEN 52 -- Idempotency check: see if an identical record exists. 53 -- Note that by checking 'merge_sig', we implicitly check 54 -- identity over everything that the signature covers. 55 PERFORM 56 FROM purse_merges 57 WHERE purse_pub=in_purse_pub 58 AND merge_sig=in_merge_sig; 59 IF NOT FOUND 60 THEN 61 -- Purse was merged, but to some other reserve. Not allowed. 62 out_conflict=TRUE; 63 out_no_reserve=FALSE; 64 out_no_funds=FALSE; 65 RETURN; 66 END IF; 67 68 -- "success" 69 out_conflict=FALSE; 70 out_no_funds=FALSE; 71 out_no_reserve=FALSE; 72 RETURN; 73 END IF; 74 out_conflict=FALSE; 75 76 PERFORM 77 FROM exchange.reserves 78 WHERE reserve_pub=in_reserve_pub; 79 80 out_no_reserve = NOT FOUND; 81 82 IF (in_reserve_quota) 83 THEN 84 -- Increment active purses per reserve (and check this is allowed) 85 IF (out_no_reserve) 86 THEN 87 out_no_funds=TRUE; 88 RETURN; 89 END IF; 90 UPDATE exchange.reserves 91 SET purses_active=purses_active+1 92 WHERE reserve_pub=in_reserve_pub 93 AND purses_active < purses_allowed; 94 IF NOT FOUND 95 THEN 96 out_no_funds=TRUE; 97 RETURN; 98 END IF; 99 ELSE 100 -- UPDATE reserves balance (and check if balance is enough to pay the fee) 101 IF (out_no_reserve) 102 THEN 103 IF ( (0 != in_purse_fee.val) OR 104 (0 != in_purse_fee.frac) ) 105 THEN 106 out_no_funds=TRUE; 107 RETURN; 108 END IF; 109 INSERT INTO exchange.reserves 110 (reserve_pub 111 ,expiration_date 112 ,gc_date) 113 VALUES 114 (in_reserve_pub 115 ,in_reserve_expiration 116 ,in_reserve_gc); 117 ELSE 118 UPDATE exchange.reserves 119 SET 120 current_balance.frac=(current_balance).frac-in_purse_fee.frac 121 + CASE 122 WHEN (current_balance).frac < in_purse_fee.frac 123 THEN 100000000 124 ELSE 0 125 END, 126 current_balance.val=(current_balance).val-in_purse_fee.val 127 - CASE 128 WHEN (current_balance).frac < in_purse_fee.frac 129 THEN 1 130 ELSE 0 131 END 132 WHERE reserve_pub=in_reserve_pub 133 AND ( ((current_balance).val > in_purse_fee.val) OR 134 ( ((current_balance).frac >= in_purse_fee.frac) AND 135 ((current_balance).val >= in_purse_fee.val) ) ); 136 IF NOT FOUND 137 THEN 138 out_no_funds=TRUE; 139 RETURN; 140 END IF; 141 END IF; 142 END IF; 143 144 out_no_funds=FALSE; 145 146 147 -- Store account merge signature. 148 INSERT INTO account_merges 149 (reserve_pub 150 ,reserve_sig 151 ,purse_pub 152 ,wallet_h_payto) 153 VALUES 154 (in_reserve_pub 155 ,in_reserve_sig 156 ,in_purse_pub 157 ,in_wallet_h_payto); 158 159 END $$; 160 161 COMMENT ON FUNCTION exchange_do_reserve_purse(BYTEA, BYTEA, INT8, INT8, INT8, BYTEA, BOOLEAN, taler_amount, BYTEA, BYTEA) 162 IS 'Create a purse for a reserve.';