--
-- This file is part of TALER
-- Copyright (C) 2025 Taler Systems SA
--
-- TALER is free software; you can redistribute it and/or modify it under the
-- terms of the GNU General Public License as published by the Free Software
-- Foundation; either version 3, or (at your option) any later version.
--
-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License along with
-- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
--


DROP FUNCTION IF EXISTS merchant_do_insert_spent_token;
CREATE FUNCTION merchant_do_insert_spent_token (
  IN in_h_contract_terms BYTEA,
  IN in_h_issue_pub BYTEA,
  IN in_use_pub BYTEA,
  IN in_use_sig BYTEA,
  IN in_issue_sig BYTEA,
  OUT out_no_family BOOL,
  OUT out_conflict BOOL)
LANGUAGE plpgsql
AS $$
DECLARE
  my_rec RECORD;
  my_tfk_serial INT8;
  my_tf_serial INT8;
BEGIN

SELECT token_family_key_serial
      ,token_family_serial
  INTO my_rec
  FROM merchant_token_family_keys
 WHERE h_pub = in_h_issue_pub;

IF NOT FOUND
THEN
  out_no_family = TRUE;
  out_conflict = FALSE;
  return;
END IF;

out_no_family = FALSE;
my_tfk_serial = my_rec.token_family_key_serial;
my_tf_serial = my_rec.token_family_serial;

-- This will fail due to the UNIQUE constrained on 'token_pub'
-- if a client attempts double-spending.
INSERT INTO merchant_used_tokens
  (token_family_key_serial
  ,h_contract_terms
  ,token_pub
  ,token_sig
  ,blind_sig
  ) VALUES
  (my_tfk_serial
  ,in_h_contract_terms
  ,in_use_pub
  ,in_use_sig
  ,in_issue_sig)
  ON CONFLICT DO NOTHING;

IF NOT FOUND
THEN
  -- Double spending or idempotent? check!
  PERFORM FROM merchant_used_tokens
    WHERE token_family_key_serial=my_tfk_serial
      AND h_contract_terms=in_h_contract_terms
      AND token_pub=in_use_pub
      AND token_sig=in_use_sig
      AND blind_sig=in_issue_sig;
  -- if FOUND, we are idempotent and it is OK;
  -- if NOT FOUND, someone tries to double-spend the token
  out_conflict = NOT FOUND;
  return;
END IF;
out_conflict = FALSE;

UPDATE merchant_token_families
   SET used=used+1
 WHERE token_family_serial=my_tf_serial;

END $$;
