exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit b03f77ace16e7935db6115eb8010123c57a1444d
parent 7ea69935a917de5b28af2cfc7946dbccdde85f44
Author: Christian Grothoff <grothoff@gnunet.org>
Date:   Wed, 14 May 2025 15:29:05 +0200

cd ~/private
git commit -a -S -m do
Merge branch 'master' of git+ssh://git.taler.net/exchange

Diffstat:
Msrc/exchangedb/0002-purse_actions.sql | 19-------------------
Msrc/exchangedb/0002-purse_decision.sql | 38--------------------------------------
Msrc/exchangedb/0002-reserves_in.sql | 20--------------------
Msrc/exchangedb/0002-reserves_out.sql | 22----------------------
Msrc/exchangedb/Makefile.am | 3++-
Asrc/exchangedb/exchange_trigger_purse_decision_insert.sql | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/exchange_trigger_purse_requests_insert.sql | 35+++++++++++++++++++++++++++++++++++
Asrc/exchangedb/exchange_trigger_reserves_in_insert.sql | 35+++++++++++++++++++++++++++++++++++
Asrc/exchangedb/exchange_trigger_reserves_out_insert.sql | 37+++++++++++++++++++++++++++++++++++++
Msrc/exchangedb/procedures.sql.in | 4++++
Msrc/util/secmod_common.c | 70+++++++++++++++++++++++++++++++++++++++++++---------------------------
11 files changed, 210 insertions(+), 127 deletions(-)

diff --git a/src/exchangedb/0002-purse_actions.sql b/src/exchangedb/0002-purse_actions.sql @@ -60,25 +60,6 @@ BEGIN END $$; -CREATE OR REPLACE FUNCTION purse_requests_insert_trigger() - RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - INSERT INTO - purse_actions - (purse_pub - ,action_date) - VALUES - (NEW.purse_pub - ,NEW.purse_expiration); - RETURN NEW; -END $$; - -COMMENT ON FUNCTION purse_requests_insert_trigger() - IS 'When a purse is created, insert it into the purse_action table to take action when the purse expires.'; - - CREATE OR REPLACE FUNCTION master_table_purse_actions() RETURNS VOID LANGUAGE plpgsql diff --git a/src/exchangedb/0002-purse_decision.sql b/src/exchangedb/0002-purse_decision.sql @@ -74,44 +74,6 @@ END $$; -CREATE OR REPLACE FUNCTION purse_decision_insert_trigger() - RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - UPDATE purse_requests - SET was_decided=TRUE - WHERE purse_pub=NEW.purse_pub; - IF NEW.refunded - THEN - INSERT INTO coin_history - (coin_pub - ,table_name - ,serial_id) - SELECT - pd.coin_pub - ,'purse_decision' - ,NEW.purse_decision_serial_id - FROM purse_deposits pd - WHERE purse_pub = NEW.purse_pub; - ELSE - INSERT INTO reserve_history - (reserve_pub - ,table_name - ,serial_id) - SELECT - reserve_pub - ,'purse_decision' - ,NEW.purse_decision_serial_id - FROM purse_merges - WHERE purse_pub=NEW.purse_pub; - END IF; - RETURN NEW; -END $$; -COMMENT ON FUNCTION purse_decision_insert_trigger() - IS 'Automatically generate coin history entry and update decision status for the purse.'; - - CREATE FUNCTION master_table_purse_decision() RETURNS VOID LANGUAGE plpgsql diff --git a/src/exchangedb/0002-reserves_in.sql b/src/exchangedb/0002-reserves_in.sql @@ -121,26 +121,6 @@ BEGIN END $$; - -CREATE OR REPLACE FUNCTION reserves_in_insert_trigger() - RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - INSERT INTO reserve_history - (reserve_pub - ,table_name - ,serial_id) - VALUES - (NEW.reserve_pub - ,'reserves_in' - ,NEW.reserve_in_serial_id); - RETURN NEW; -END $$; -COMMENT ON FUNCTION reserves_in_insert_trigger() - IS 'Automatically generate reserve history entry.'; - - CREATE FUNCTION master_table_reserves_in() RETURNS VOID LANGUAGE plpgsql diff --git a/src/exchangedb/0002-reserves_out.sql b/src/exchangedb/0002-reserves_out.sql @@ -107,28 +107,6 @@ END $$; -CREATE FUNCTION reserves_out_insert_trigger() - RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - INSERT INTO reserve_history - (reserve_pub - ,table_name - ,serial_id) - SELECT - res.reserve_pub - ,'reserves_out' - ,NEW.reserve_out_serial_id - FROM - reserves res - WHERE res.reserve_uuid = NEW.reserve_uuid; - RETURN NEW; -END $$; -COMMENT ON FUNCTION reserves_out_insert_trigger() - IS 'Replicate reserve_out inserts into reserve_history table.'; - - CREATE FUNCTION master_table_reserves_out() RETURNS void LANGUAGE plpgsql diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am @@ -24,6 +24,7 @@ sqldir = $(prefix)/share/taler-exchange/sql/ sqlinputs = \ exchange_do_*.sql \ exchange_statistics_*.sql \ + exchange_trigger_*.sql \ procedures.sql.in \ 0002-*.sql \ exchange-0002.sql.in @@ -48,7 +49,7 @@ CLEANFILES = \ exchange-0002.sql \ procedures.sql -procedures.sql: procedures.sql.in exchange_do_*.sql exchange_statistics_helpers.sql +procedures.sql: procedures.sql.in exchange_do_*.sql exchange_statistics_*.sql exchange_trigger_*.sql chmod +w $@ 2> /dev/null || true gcc -E -P -undef - < procedures.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@ chmod ugo-w $@ diff --git a/src/exchangedb/exchange_trigger_purse_decision_insert.sql b/src/exchangedb/exchange_trigger_purse_decision_insert.sql @@ -0,0 +1,54 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2024 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/> +-- + +CREATE OR REPLACE FUNCTION purse_decision_insert_trigger() + RETURNS trigger + LANGUAGE plpgsql + AS $$ +BEGIN + UPDATE exchange.purse_requests + SET was_decided=TRUE + WHERE purse_pub=NEW.purse_pub; + IF NEW.refunded + THEN + INSERT INTO exchange.coin_history + (coin_pub + ,table_name + ,serial_id) + SELECT + pd.coin_pub + ,'purse_decision' + ,NEW.purse_decision_serial_id + FROM exchange.purse_deposits pd + WHERE purse_pub = NEW.purse_pub; + ELSE + INSERT INTO exchange.reserve_history + (reserve_pub + ,table_name + ,serial_id) + SELECT + reserve_pub + ,'purse_decision' + ,NEW.purse_decision_serial_id + FROM exchange.purse_merges + WHERE purse_pub=NEW.purse_pub; + END IF; + RETURN NEW; +END $$; +COMMENT ON FUNCTION purse_decision_insert_trigger() + IS 'Automatically generate coin history entry and update decision status for the purse.'; + + diff --git a/src/exchangedb/exchange_trigger_purse_requests_insert.sql b/src/exchangedb/exchange_trigger_purse_requests_insert.sql @@ -0,0 +1,35 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2024 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/> +-- + +CREATE OR REPLACE FUNCTION purse_requests_insert_trigger() + RETURNS trigger + LANGUAGE plpgsql + AS $$ +BEGIN + INSERT INTO + exchange.purse_actions + (purse_pub + ,action_date) + VALUES + (NEW.purse_pub + ,NEW.purse_expiration); + RETURN NEW; +END $$; + +COMMENT ON FUNCTION purse_requests_insert_trigger() + IS 'When a purse is created, insert it into the purse_action table to take action when the purse expires.'; + + diff --git a/src/exchangedb/exchange_trigger_reserves_in_insert.sql b/src/exchangedb/exchange_trigger_reserves_in_insert.sql @@ -0,0 +1,35 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2024 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/> +-- + +CREATE OR REPLACE FUNCTION reserves_in_insert_trigger() + RETURNS trigger + LANGUAGE plpgsql + AS $$ +BEGIN + INSERT INTO exchange.reserve_history + (reserve_pub + ,table_name + ,serial_id) + VALUES + (NEW.reserve_pub + ,'reserves_in' + ,NEW.reserve_in_serial_id); + RETURN NEW; +END $$; +COMMENT ON FUNCTION reserves_in_insert_trigger() + IS 'Automatically generate reserve history entry.'; + + diff --git a/src/exchangedb/exchange_trigger_reserves_out_insert.sql b/src/exchangedb/exchange_trigger_reserves_out_insert.sql @@ -0,0 +1,37 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2024 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/> +-- + +CREATE OR REPLACE FUNCTION reserves_out_insert_trigger() + RETURNS trigger + LANGUAGE plpgsql + AS $$ +BEGIN + INSERT INTO exchange.reserve_history + (reserve_pub + ,table_name + ,serial_id) + SELECT + res.reserve_pub + ,'reserves_out' + ,NEW.reserve_out_serial_id + FROM + exchange.reserves res + WHERE res.reserve_uuid = NEW.reserve_uuid; + RETURN NEW; +END $$; +COMMENT ON FUNCTION reserves_out_insert_trigger() + IS 'Replicate reserve_out inserts into reserve_history table.'; + diff --git a/src/exchangedb/procedures.sql.in b/src/exchangedb/procedures.sql.in @@ -59,6 +59,10 @@ SET search_path TO exchange; #include "exchange_do_set_aml_lock.sql" #include "exchange_do_insert_sanction_list_hit.sql" #include "exchange_statistics_helpers.sql" +#include "exchange_trigger_purse_requests_insert.sql" +#include "exchange_trigger_reserves_out_insert.sql" +#include "exchange_trigger_reserves_in_insert.sql" +#include "exchange_trigger_purse_decision_insert.sql" DROP PROCEDURE IF EXISTS exchange_do_gc; CREATE PROCEDURE exchange_do_gc( diff --git a/src/util/secmod_common.c b/src/util/secmod_common.c @@ -365,26 +365,6 @@ TES_await_ready (struct TES_Client *client) } -void -TES_free_client (struct TES_Client *client) -{ - GNUNET_assert (0 == pthread_mutex_lock (&TES_clients_lock)); - GNUNET_CONTAINER_DLL_remove (TES_clients_head, - TES_clients_tail, - client); - GNUNET_assert (0 == pthread_mutex_unlock (&TES_clients_lock)); - GNUNET_break (0 == close (client->csock)); -#ifdef __linux__ - GNUNET_break (0 == close (client->esock)); -#else - GNUNET_break (0 == close (client->esock_in)); - GNUNET_break (0 == close (client->esock_out)); -#endif - pthread_detach (client->worker); - GNUNET_free (client); -} - - /** * Main function of a worker thread that signs. * @@ -400,7 +380,6 @@ sign_worker (void *cls) client->cb.init (client)) { GNUNET_break (0); - TES_free_client (client); return NULL; } while (! in_shutdown) @@ -411,12 +390,14 @@ sign_worker (void *cls) client->cb.updater (client)) break; } - if (GNUNET_SYSERR == - TES_read_work (client, - client->cb.dispatch)) - break; + else + { + if (GNUNET_SYSERR == + TES_read_work (client, + client->cb.dispatch)) + break; + } } - TES_free_client (client); return NULL; } @@ -496,7 +477,19 @@ listen_job (void *cls) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "pthread_create"); - TES_free_client (client); + GNUNET_assert (0 == pthread_mutex_lock (&TES_clients_lock)); + GNUNET_CONTAINER_DLL_remove (TES_clients_head, + TES_clients_tail, + client); + GNUNET_assert (0 == pthread_mutex_unlock (&TES_clients_lock)); + GNUNET_break (0 == close (client->csock)); +#ifdef __linux__ + GNUNET_break (0 == close (client->esock)); +#else + GNUNET_break (0 == close (client->esock_in)); + GNUNET_break (0 == close (client->esock_out)); +#endif + GNUNET_free (client); } } } @@ -570,6 +563,8 @@ TES_listen_start (const struct GNUNET_CONFIGURATION_Handle *cfg, void TES_listen_stop (void) { + struct TES_Client *client; + if (NULL != listen_task) { GNUNET_SCHEDULER_cancel (listen_task); @@ -590,4 +585,25 @@ TES_listen_stop (void) GNUNET_free (unixpath); in_shutdown = true; TES_wake_clients (); + GNUNET_assert (0 == pthread_mutex_lock (&TES_clients_lock)); + while (NULL != (client = TES_clients_head)) + { + void *rval; + + GNUNET_CONTAINER_DLL_remove (TES_clients_head, + TES_clients_tail, + client); + GNUNET_break (0 == + pthread_join (client->worker, + &rval)); + GNUNET_break (0 == close (client->csock)); +#ifdef __linux__ + GNUNET_break (0 == close (client->esock)); +#else + GNUNET_break (0 == close (client->esock_in)); + GNUNET_break (0 == close (client->esock_out)); +#endif + GNUNET_free (client); + } + GNUNET_assert (0 == pthread_mutex_unlock (&TES_clients_lock)); }