pg_insert_spent_token.sql (2336B)
1 -- 2 -- This file is part of TALER 3 -- Copyright (C) 2025 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 18 DROP FUNCTION IF EXISTS merchant_do_insert_spent_token; 19 CREATE FUNCTION merchant_do_insert_spent_token ( 20 IN in_h_contract_terms BYTEA, 21 IN in_h_issue_pub BYTEA, 22 IN in_use_pub BYTEA, 23 IN in_use_sig BYTEA, 24 IN in_issue_sig BYTEA, 25 OUT out_no_family BOOL, 26 OUT out_conflict BOOL) 27 LANGUAGE plpgsql 28 AS $$ 29 DECLARE 30 my_rec RECORD; 31 my_tfk_serial INT8; 32 my_tf_serial INT8; 33 BEGIN 34 35 SELECT token_family_key_serial 36 ,token_family_serial 37 INTO my_rec 38 FROM merchant_token_family_keys 39 WHERE h_pub = in_h_issue_pub; 40 41 IF NOT FOUND 42 THEN 43 out_no_family = TRUE; 44 out_conflict = FALSE; 45 return; 46 END IF; 47 48 out_no_family = FALSE; 49 my_tfk_serial = my_rec.token_family_key_serial; 50 my_tf_serial = my_rec.token_family_serial; 51 52 -- This will fail due to the UNIQUE constrained on 'token_pub' 53 -- if a client attempts double-spending. 54 INSERT INTO merchant_used_tokens 55 (token_family_key_serial 56 ,h_contract_terms 57 ,token_pub 58 ,token_sig 59 ,blind_sig 60 ) VALUES 61 (my_tfk_serial 62 ,in_h_contract_terms 63 ,in_use_pub 64 ,in_use_sig 65 ,in_issue_sig) 66 ON CONFLICT DO NOTHING; 67 68 IF NOT FOUND 69 THEN 70 -- Double spending or idempotent? check! 71 PERFORM FROM merchant_used_tokens 72 WHERE token_family_key_serial=my_tfk_serial 73 AND h_contract_terms=in_h_contract_terms 74 AND token_pub=in_use_pub 75 AND token_sig=in_use_sig 76 AND blind_sig=in_issue_sig; 77 -- if FOUND, we are idempotent and it is OK; 78 -- if NOT FOUND, someone tries to double-spend the token 79 out_conflict = NOT FOUND; 80 return; 81 END IF; 82 out_conflict = FALSE; 83 84 UPDATE merchant_token_families 85 SET used=used+1 86 WHERE token_family_serial=my_tf_serial; 87 88 END $$;