diff options
Diffstat (limited to 'src/exchangedb')
-rw-r--r-- | src/exchangedb/0002-reserves.sql | 8 | ||||
-rw-r--r-- | src/exchangedb/0004-kyc_attributes.sql | 44 | ||||
-rw-r--r-- | src/exchangedb/Makefile.am | 1 | ||||
-rw-r--r-- | src/exchangedb/exchange-0004.sql.in | 3 | ||||
-rw-r--r-- | src/exchangedb/exchange_do_insert_kyc_attributes.sql | 92 | ||||
-rw-r--r-- | src/exchangedb/exchange_do_reserves_in_insert.sql | 136 | ||||
-rw-r--r-- | src/exchangedb/pg_insert_kyc_attributes.c | 69 | ||||
-rw-r--r-- | src/exchangedb/pg_insert_kyc_attributes.h | 21 | ||||
-rw-r--r-- | src/exchangedb/pg_insert_records_by_table.c | 7 | ||||
-rw-r--r-- | src/exchangedb/pg_lookup_records_by_table.c | 6 | ||||
-rw-r--r-- | src/exchangedb/pg_reserves_in_insert.c | 281 | ||||
-rw-r--r-- | src/exchangedb/pg_select_kyc_attributes.c | 7 | ||||
-rw-r--r-- | src/exchangedb/pg_select_similar_kyc_attributes.c | 7 | ||||
-rw-r--r-- | src/exchangedb/pg_update_kyc_attributes.c | 68 | ||||
-rw-r--r-- | src/exchangedb/pg_update_kyc_attributes.h | 57 | ||||
-rw-r--r-- | src/exchangedb/pg_update_kyc_process_by_row.c | 3 | ||||
-rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 3 | ||||
-rw-r--r-- | src/exchangedb/procedures.sql.in | 1 |
18 files changed, 630 insertions, 184 deletions
diff --git a/src/exchangedb/0002-reserves.sql b/src/exchangedb/0002-reserves.sql index 03d17aee2..df5b6c3db 100644 --- a/src/exchangedb/0002-reserves.sql +++ b/src/exchangedb/0002-reserves.sql @@ -31,7 +31,7 @@ BEGIN ',current_balance_frac INT4 NOT NULL DEFAULT(0)' ',purses_active INT8 NOT NULL DEFAULT(0)' ',purses_allowed INT8 NOT NULL DEFAULT(0)' - ',max_age INT4 NOT NULL DEFAULT(120)' + ',max_age INT4 NOT NULL DEFAULT(0)' ',expiration_date INT8 NOT NULL' ',gc_date INT8 NOT NULL' ') %s ;' @@ -80,6 +80,12 @@ BEGIN ,table_name ,partition_suffix ); + PERFORM comment_partitioned_column( + 'Birthday of the user in days after 1970, or 0 if user is an adult and is not subject to age restrictions' + ,'max_age' + ,table_name + ,partition_suffix + ); END $$; diff --git a/src/exchangedb/0004-kyc_attributes.sql b/src/exchangedb/0004-kyc_attributes.sql new file mode 100644 index 000000000..e45d46b3b --- /dev/null +++ b/src/exchangedb/0004-kyc_attributes.sql @@ -0,0 +1,44 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2023 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 master_table_kyc_attributes_V2() +RETURNS VOID +LANGUAGE plpgsql +AS $$ +DECLARE + table_name VARCHAR DEFAULT 'kyc_attributes'; +BEGIN + EXECUTE FORMAT ( + 'ALTER TABLE ' || table_name || + ' DROP COLUMN birthdate;' + ); +END $$; + +COMMENT ON FUNCTION master_table_kyc_attributes_V2 + IS 'Removes birthdate column from the kyc_attributes table'; + +INSERT INTO exchange_tables + (name + ,version + ,action + ,partitioned + ,by_range) + VALUES + ('kyc_attributes_V2' + ,'exchange-0004' + ,'master' + ,TRUE + ,FALSE); diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am index ee78b87f7..4df9cb406 100644 --- a/src/exchangedb/Makefile.am +++ b/src/exchangedb/Makefile.am @@ -144,7 +144,6 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \ pg_aggregate.h pg_aggregate.c \ pg_create_aggregation_transient.h pg_create_aggregation_transient.c \ pg_insert_kyc_attributes.h pg_insert_kyc_attributes.c \ - pg_update_kyc_attributes.h pg_update_kyc_attributes.c \ pg_select_similar_kyc_attributes.h pg_select_similar_kyc_attributes.c \ pg_select_kyc_attributes.h pg_select_kyc_attributes.c \ pg_insert_aml_officer.h pg_insert_aml_officer.c \ diff --git a/src/exchangedb/exchange-0004.sql.in b/src/exchangedb/exchange-0004.sql.in index 00979e193..02bdf017a 100644 --- a/src/exchangedb/exchange-0004.sql.in +++ b/src/exchangedb/exchange-0004.sql.in @@ -1,6 +1,6 @@ -- -- This file is part of TALER --- Copyright (C) 2014--2023 Taler Systems SA +-- Copyright (C) 2023 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 @@ -19,6 +19,7 @@ BEGIN; SELECT _v.register_patch('exchange-0004', NULL, NULL); SET search_path TO exchange; +#include "0004-kyc_attributes.sql" #include "0004-wire_accounts.sql" COMMIT; diff --git a/src/exchangedb/exchange_do_insert_kyc_attributes.sql b/src/exchangedb/exchange_do_insert_kyc_attributes.sql new file mode 100644 index 000000000..f1959a66e --- /dev/null +++ b/src/exchangedb/exchange_do_insert_kyc_attributes.sql @@ -0,0 +1,92 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2023 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 exchange_do_insert_kyc_attributes( + IN in_process_row INT8, + IN in_h_payto BYTEA, + IN in_kyc_prox BYTEA, + IN in_provider_section VARCHAR, + IN in_birthday INT4, + IN in_provider_account_id VARCHAR, + IN in_provider_legitimization_id VARCHAR, + IN in_collection_time_ts INT8, + IN in_expiration_time INT8, + IN in_expiration_time_ts INT8, + IN in_enc_attributes BYTEA, + IN in_require_aml BOOLEAN, + IN in_kyc_completed_notify_s VARCHAR, + OUT out_ok BOOLEAN) +LANGUAGE plpgsql +AS $$ +BEGIN + +INSERT INTO exchange.kyc_attributes + (h_payto + ,kyc_prox + ,provider + ,collection_time + ,expiration_time + ,encrypted_attributes + ) VALUES + (in_h_payto + ,in_kyc_prox + ,in_provider_section + ,in_collection_time_ts + ,in_expiration_time_ts + ,in_enc_attributes); + +-- FIXME-Oec: modify to 'return' the reserve_pub here +-- (requires of course to modify other code to store +-- the reserve pub in the right table in the first place) +UPDATE exchange.legitimization_processes + SET provider_user_id=in_provider_account_id + ,provider_legitimization_id=in_provider_legitimization_id + ,expiration_time=GREATEST(expiration_time,in_expiration_time) + WHERE h_payto=in_h_payto + AND legitimization_process_serial_id=in_process_row + AND provider_section=in_provider_section; +out_ok = FOUND; + +-- FIXME-Oec: update exchange reserve table to store in_birthday here! +-- UPDATE exchange.reserves SET max_age=in_birthday WHERE reserve_pub=X; + +IF in_require_aml +THEN + INSERT INTO exchange.aml_status + (h_payto + ,status) + VALUES + (in_h_payto + ,1) + ON CONFLICT (h_payto) DO + UPDATE SET status=EXCLUDED.status | 1; +END IF; + +-- Wake up everyone who might care... +PERFORM pg_notify (in_kyc_completed_notify_s, NULL); + +INSERT INTO kyc_alerts + (h_payto + ,trigger_type) + VALUES + (in_h_payto,1); + + +END $$; + + +COMMENT ON FUNCTION exchange_do_insert_kyc_attributes(INT8, BYTEA, BYTEA, VARCHAR, INT4, VARCHAR, VARCHAR, INT8, INT8, INT8, BYTEA, BOOL, VARCHAR) + IS 'Inserts new KYC attributes and updates the status of the legitimization process and the AML status for the account'; diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql index dffcd8b55..cf57d8e81 100644 --- a/src/exchangedb/exchange_do_reserves_in_insert.sql +++ b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -963,3 +963,139 @@ BEGIN CLOSE curs_transaction_exist; RETURN; END $$; + + + + + + + +DO $$ +BEGIN + CREATE TYPE exchange_do_array_reserve_insert_return_type + AS + (transaction_duplicate BOOLEAN + ,ruuid INT8); +EXCEPTION + WHEN duplicate_object THEN null; +END +$$; + +CREATE OR REPLACE FUNCTION exchange_do_array_reserves_insert( + IN in_gc_date INT8, + IN in_reserve_expiration INT8, + IN ina_reserve_pub BYTEA[], + IN ina_wire_ref INT8[], + IN ina_credit_val INT8[], + IN ina_credit_frac INT4[], + IN ina_exchange_account_name VARCHAR[], + IN ina_execution_date INT8[], + IN ina_wire_source_h_payto BYTEA[], + IN ina_payto_uri VARCHAR[], + IN ina_notify TEXT[]) +RETURNS SETOF exchange_do_array_reserve_insert_return_type +LANGUAGE plpgsql +AS $$ +DECLARE + curs REFCURSOR; +DECLARE + conflict BOOL; +DECLARE + dup BOOL; +DECLARE + uuid INT8; +DECLARE + i RECORD; +BEGIN + + INSERT INTO wire_targets + (wire_target_h_payto + ,payto_uri) + SELECT + wire_source_h_payto + ,payto_uri + FROM + UNNEST (ina_wire_source_h_payto) AS wire_source_h_payto + ,UNNEST (ina_payto_uri) AS payto_uri + ON CONFLICT DO NOTHING; + + FOR i IN + SELECT + reserve_pub + ,wire_ref + ,credit_val + ,credit_frac + ,exchange_account_name + ,execution_date + ,wire_source_h_payto + ,payto_uri + ,notify + FROM + UNNEST (ina_reserve_pub) AS reserve_pub + ,UNNEST (ina_wire_ref) AS wire_ref + ,UNNEST (ina_credit_val) AS credit_val + ,UNNEST (ina_credit_frac) AS credit_frac + ,UNNEST (ina_exchange_account_name) AS exchange_account_name + ,UNNEST (ina_execution_date) AS execution_date + ,UNNEST (ina_wire_source_h_payto) AS wire_source_h_payto + ,UNNEST (ina_notify) AS notify + LOOP + INSERT INTO reserves + (reserve_pub + ,current_balance_val + ,current_balance_frac + ,expiration_date + ,gc_date + ) VALUES ( + i.reserve_pub + ,i.credit_val + ,i.credit_frac + ,in_reserve_expiration + ,in_gc_date + ) + ON CONFLICT DO NOTHING + RETURNING reserve_uuid + INTO uuid; + conflict = NOT FOUND; + + INSERT INTO reserves_in + (reserve_pub + ,wire_reference + ,credit_val + ,credit_frac + ,exchange_account_section + ,wire_source_h_payto + ,execution_date + ) VALUES ( + i.reserve_pub + ,i.wire_reference + ,i.credit_val + ,i.credit_frac + ,i.exchange_account_section + ,i.wire_source_h_payto + ,i.execution_date + ) + ON CONFLICT DO NOTHING; + + IF NOT FOUND + THEN + IF conflict + THEN + dup = TRUE; + else + dup = FALSE; + END IF; + ELSE + IF NOT conflict + THEN + EXECUTE FORMAT ( + 'NOTIFY %s' + ,i.notify); + END IF; + dup = FALSE; + END IF; + RETURN NEXT (dup,uuid); + END LOOP; + + RETURN; +END $$; diff --git a/src/exchangedb/pg_insert_kyc_attributes.c b/src/exchangedb/pg_insert_kyc_attributes.c index fd90950fd..361f491e8 100644 --- a/src/exchangedb/pg_insert_kyc_attributes.c +++ b/src/exchangedb/pg_insert_kyc_attributes.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022, 2023 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 @@ -29,43 +29,72 @@ enum GNUNET_DB_QueryStatus TEH_PG_insert_kyc_attributes ( void *cls, + uint64_t process_row, const struct TALER_PaytoHashP *h_payto, const struct GNUNET_ShortHashCode *kyc_prox, const char *provider_section, - const char *birthdate, + uint32_t birthday, struct GNUNET_TIME_Timestamp collection_time, - struct GNUNET_TIME_Timestamp expiration_time, + const char *provider_account_id, + const char *provider_legitimization_id, + struct GNUNET_TIME_Absolute expiration_time, size_t enc_attributes_size, - const void *enc_attributes) + const void *enc_attributes, + bool require_aml) { struct PostgresClosure *pg = cls; + struct GNUNET_TIME_Timestamp expiration + = GNUNET_TIME_absolute_to_timestamp (expiration_time); + struct TALER_KycCompletedEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), + .h_payto = *h_payto + }; + char *kyc_completed_notify_s + = GNUNET_PG_get_event_notify_channel (&rep.header); struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&process_row), GNUNET_PQ_query_param_auto_from_type (h_payto), GNUNET_PQ_query_param_auto_from_type (kyc_prox), GNUNET_PQ_query_param_string (provider_section), - (NULL == birthdate) + GNUNET_PQ_query_param_uint32 (&birthday), + (NULL == provider_account_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (provider_account_id), + (NULL == provider_legitimization_id) ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (birthdate), + : GNUNET_PQ_query_param_string (provider_legitimization_id), GNUNET_PQ_query_param_timestamp (&collection_time), - GNUNET_PQ_query_param_timestamp (&expiration_time), + GNUNET_PQ_query_param_absolute_time (&expiration_time), + GNUNET_PQ_query_param_timestamp (&expiration), GNUNET_PQ_query_param_fixed_size (enc_attributes, enc_attributes_size), + GNUNET_PQ_query_param_bool (require_aml), + GNUNET_PQ_query_param_string (kyc_completed_notify_s), GNUNET_PQ_query_param_end }; + bool ok; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("out_ok", + &ok), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; PREPARE (pg, "insert_kyc_attributes", - "INSERT INTO kyc_attributes " - "(h_payto" - ",kyc_prox" - ",provider" - ",birthdate" - ",collection_time" - ",expiration_time" - ",encrypted_attributes" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_kyc_attributes", - params); + "SELECT " + " out_ok" + " FROM exchange_do_insert_kyc_attributes " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "insert_kyc_attributes", + params, + rs); + GNUNET_free (kyc_completed_notify_s); + if (qs < 0) + return qs; + if (! ok) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + return qs; } diff --git a/src/exchangedb/pg_insert_kyc_attributes.h b/src/exchangedb/pg_insert_kyc_attributes.h index 8ee307d7d..c1aad0eb5 100644 --- a/src/exchangedb/pg_insert_kyc_attributes.h +++ b/src/exchangedb/pg_insert_kyc_attributes.h @@ -27,30 +27,39 @@ /** - * Store KYC attribute data. + * Store KYC attribute data, update KYC process status and + * AML status for the given account. * * @param cls closure + * @param process_row KYC process row to update * @param h_payto account for which the attribute data is stored * @param kyc_prox key for similarity search * @param provider_section provider that must be checked - * @param birthdate birthdate of user, in format YYYY-MM-DD; can be NULL; - * digits can be 0 if exact day, month or year are unknown + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @param birthday birthdate of user, in days after 1990, or 0 if unknown or definitively adult * @param collection_time when was the data collected * @param expiration_time when does the data expire * @param enc_attributes_size number of bytes in @a enc_attributes * @param enc_attributes encrypted attribute data + * @param require_aml true to trigger AML * @return database transaction status */ enum GNUNET_DB_QueryStatus TEH_PG_insert_kyc_attributes ( void *cls, + uint64_t process_row, const struct TALER_PaytoHashP *h_payto, const struct GNUNET_ShortHashCode *kyc_prox, const char *provider_section, - const char *birthdate, + uint32_t birthday, struct GNUNET_TIME_Timestamp collection_time, - struct GNUNET_TIME_Timestamp expiration_time, + const char *provider_account_id, + const char *provider_legitimization_id, + struct GNUNET_TIME_Absolute expiration_time, size_t enc_attributes_size, - const void *enc_attributes); + const void *enc_attributes, + bool require_aml); + #endif diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c index e16a4b74f..9baaf3b1a 100644 --- a/src/exchangedb/pg_insert_records_by_table.c +++ b/src/exchangedb/pg_insert_records_by_table.c @@ -1995,10 +1995,6 @@ irbt_cb_table_kyc_attributes (struct PostgresClosure *pg, &td->details.kyc_attributes.kyc_prox), GNUNET_PQ_query_param_string ( td->details.kyc_attributes.provider), - (NULL == td->details.kyc_attributes.birthdate) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string ( - td->details.kyc_attributes.birthdate), GNUNET_PQ_query_param_timestamp ( &td->details.kyc_attributes.collection_time), GNUNET_PQ_query_param_timestamp ( @@ -2016,12 +2012,11 @@ irbt_cb_table_kyc_attributes (struct PostgresClosure *pg, ",h_payto" ",kyc_prox" ",provider" - ",birthdate" ",collection_time" ",expiration_time" ",encrypted_attributes" ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8);"); + "($1, $2, $3, $4, $5, $6, $7);"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "insert_into_table_kyc_attributes", params); diff --git a/src/exchangedb/pg_lookup_records_by_table.c b/src/exchangedb/pg_lookup_records_by_table.c index 534e9a1d2..3fcad58c0 100644 --- a/src/exchangedb/pg_lookup_records_by_table.c +++ b/src/exchangedb/pg_lookup_records_by_table.c @@ -2684,11 +2684,6 @@ lrbt_cb_table_kyc_attributes (void *cls, GNUNET_PQ_result_spec_string ( "provider", &td.details.kyc_attributes.provider), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ( - "birthdate", - &td.details.kyc_attributes.birthdate), - NULL), GNUNET_PQ_result_spec_timestamp ( "collection_time", &td.details.kyc_attributes.collection_time), @@ -3577,7 +3572,6 @@ TEH_PG_lookup_records_by_table (void *cls, ",h_payto" ",kyc_prox" ",provider" - ",birthdate" ",collection_time" ",expiration_time" ",encrypted_attributes" diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c index 691c57d38..72fde7499 100644 --- a/src/exchangedb/pg_reserves_in_insert.c +++ b/src/exchangedb/pg_reserves_in_insert.c @@ -615,3 +615,284 @@ TEH_PG_reserves_in_insert ( GNUNET_free (rrs[i].notify_s); return qs; } + + +#if 0 + +/** + * Closure for our helper_cb() + */ +struct Context +{ + /** + * Array of reserve UUIDs to initialize. + */ + uint64_t *reserve_uuids; + + /** + * Array with entries set to 'true' for duplicate transactions. + */ + bool *transaction_duplicates; + + /** + * Array with entries set to 'true' for rows with conflicts. + */ + bool *conflicts; + + /** + * Set to #GNUNET_SYSERR on failures. + */ + struct GNUNET_GenericReturnValue status; + + /** + * Single value (no array) set to true if we need + * to follow-up with an update. + */ + bool *needs_update; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct Context *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct Context *ctx = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ( + "transaction_duplicate", + &ctx->transaction_duplicates[i]), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ("ruuid", + &ctx->reserve_uuids[i]), + &ctx->conflicts[i]), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + *ctx->need_update |= ctx->conflicts[i]; + } +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_reserves_in_insertN ( + void *cls, + const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, + unsigned int reserves_length, + enum GNUNET_DB_QueryStatus *results) +{ + struct PostgresClosure *pg = cls; + struct TALER_PaytoHashP h_paytos[GNUNET_NZL (reserves_length)]; + char *notify_s[GNUNET_NZL (reserves_length)]; + struct TALER_ReservePublicKeyP *reserve_pubs[GNUNET_NZL (reserves_length)]; + struct TALER_Amount *balances[GNUNET_NZL (reserves_length)]; + struct GNUNET_TIME_Timestamp execution_times[GNUNET_NZL (reserves_length)]; + const char *sender_account_details[GNUNET_NZL (reserves_length)]; + const char *exchange_account_names[GNUNET_NZL (reserves_length)]; + uint64_t wire_references[GNUNET_NZL (reserves_length)]; + uint64_t reserve_uuids[GNUNET_NZL (reserves_length)]; + bool transaction_duplicates[GNUNET_NZL (reserves_length)]; + bool conflicts[GNUNET_NZL (reserves_length)]; + struct GNUNET_TIME_Timestamp reserve_expiration + = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time); + struct GNUNET_TIME_Timestamp gc + = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time); + bool needs_update = false; + enum GNUNET_DB_QueryStatus qs; + + for (unsigned int i = 0; i<reserves_length; i++) + { + const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i]; + + TALER_payto_hash (reserve->sender_account_details, + &h_paytos[i]); + notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub); + reserve_pubs[i] = &reserve->reserve_pub; + balances[i] = &reserve->balance; + execution_times[i] = reserve->execution_time; + sender_account_details[i] = reserve->sender_account_details; + exchange_account_names[i] = reserve->exchange_account_name; + wire_references[i] = reserve->wire_reference; + } + + /* NOTE: kind-of pointless to explicitly start a transaction here... */ + if (GNUNET_OK != + TEH_PG_preflight (pg)) + { + GNUNET_break (0); + qs = GNUNET_DB_STATUS_HARD_ERROR; + goto finished; + } + + if (GNUNET_OK != + TEH_PG_start_read_committed (pg, + "READ_COMMITED")) + { + GNUNET_break (0); + qs = GNUNET_DB_STATUS_HARD_ERROR; + goto finished; + } + + PREPARE (pg, + "reserves_insert_with_array", + "SELECT" + " transaction_duplicate" + ",ruuid" + "FROM exchange_do_array_reserves_insert" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);"); + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&gc), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_array_auto_from_type (reserves_length, + reserve_pubs, + pg->conn), + GNUNET_PQ_query_param_array_uint64 (reserves_length, + wire_references, + pg->conn), + TALER_PQ_query_param_array_amount (reserves_length, + balances, + pg->conn), + GNUNET_PQ_query_param_array_string (reserves_length, + exchange_account_names, + pg->conn), + GNUNET_PQ_query_param_array_timestamp (reserves_length, + execution_times, + pg->conn), + GNUNET_PQ_query_param_array_bytes_same_size_cont_auto ( + reserves_length, + h_paytos, + sizeof (struct GNUNET_PaytoHashP), + pg->conn), + GNUNET_PQ_query_param_array_string (reserves_length, + sender_account_details, + pg->conn), + GNUNET_PQ_query_param_array_string (reserves_length, + notify_s, + pg->conn), + GNUNET_PQ_query_param_end + }; + struct Context ctx = { + .reserve_uuids = reserve_uuids, + .transaction_duplicates = transaction_duplicates, + .conflicts = conflicts, + .needs_update = &needs_update, + .status = GNUNET_OK + }; + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "reserves_insert_with_array", + params, + &multi_res, + &ctx); + if ( (qs < 0) || + (GNUNET_OK != ctx.status) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to insert into reserves (%d)\n", + qs); + goto finished; + } + } + + { + enum GNUNET_DB_QueryStatus cs; + + cs = TEH_PG_commit (pg); + if (cs < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to commit\n"); + qs = cs; + goto finished; + } + } + for (unsigned int i = 0; i<reserves_length; i++) + { + results[i] = transaction_duplicates[i] + ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + + if (! need_update) + { + qs = reserves_length; + goto finished; + } + if (GNUNET_OK != + TEH_PG_start (pg, + "reserve-insert-continued")) + { + GNUNET_break (0); + qs = GNUNET_DB_STATUS_HARD_ERROR; + goto finished; + } + + for (unsigned int i = 0; i<reserves_length; i++) + { + if (! conflicts[i]) + continue; + { + bool duplicate; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pubs[i]), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_uint64 (&wire_reference[i]), + TALER_PQ_query_param_amount (balances[i]), + GNUNET_PQ_query_param_string (exchange_account_names[i]), + GNUNET_PQ_query_param_auto_from_type (h_paytos[i]), + GNUNET_PQ_query_param_string (notify_s[i]), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("duplicate", + &duplicate), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "reserves_update", + params, + rs); + if (qs < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to update reserves (%d)\n", + qs); + results[i] = qs; + goto finished; + } + results[i] = duplicate + ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + } +finished: + for (unsigned int i = 0; i<reserves_length; i++) + GNUNET_free (rrs[i].notify_s); + return qs; +} + + +#endif diff --git a/src/exchangedb/pg_select_kyc_attributes.c b/src/exchangedb/pg_select_kyc_attributes.c index c9b992da2..99ac43b3e 100644 --- a/src/exchangedb/pg_select_kyc_attributes.c +++ b/src/exchangedb/pg_select_kyc_attributes.c @@ -80,14 +80,9 @@ get_attributes_cb (void *cls, size_t enc_attributes_size; void *enc_attributes; char *provider; - char *birthdate = NULL; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_string ("provider", &provider), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("birthdate", - &birthdate), - NULL), GNUNET_PQ_result_spec_timestamp ("collection_time", &collection_time), GNUNET_PQ_result_spec_timestamp ("expiration_time", @@ -110,7 +105,6 @@ get_attributes_cb (void *cls, ctx->cb (ctx->cb_cls, ctx->h_payto, provider, - birthdate, collection_time, expiration_time, enc_attributes_size, @@ -145,7 +139,6 @@ TEH_PG_select_kyc_attributes ( "select_kyc_attributes", "SELECT " " provider" - ",birthdate" ",collection_time" ",expiration_time" ",encrypted_attributes" diff --git a/src/exchangedb/pg_select_similar_kyc_attributes.c b/src/exchangedb/pg_select_similar_kyc_attributes.c index a07f2a147..342f9ef33 100644 --- a/src/exchangedb/pg_select_similar_kyc_attributes.c +++ b/src/exchangedb/pg_select_similar_kyc_attributes.c @@ -76,16 +76,11 @@ get_attributes_cb (void *cls, size_t enc_attributes_size; void *enc_attributes; char *provider; - char *birthdate = NULL; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_auto_from_type ("h_payto", &h_payto), GNUNET_PQ_result_spec_string ("provider", &provider), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("birthdate", - &birthdate), - NULL), GNUNET_PQ_result_spec_timestamp ("collection_time", &collection_time), GNUNET_PQ_result_spec_timestamp ("expiration_time", @@ -108,7 +103,6 @@ get_attributes_cb (void *cls, ctx->cb (ctx->cb_cls, &h_payto, provider, - birthdate, collection_time, expiration_time, enc_attributes_size, @@ -143,7 +137,6 @@ TEH_PG_select_similar_kyc_attributes ( "SELECT " " h_payto" ",provider" - ",birthdate" ",collection_time" ",expiration_time" ",encrypted_attributes" diff --git a/src/exchangedb/pg_update_kyc_attributes.c b/src/exchangedb/pg_update_kyc_attributes.c deleted file mode 100644 index f77eb2bfc..000000000 --- a/src/exchangedb/pg_update_kyc_attributes.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_update_kyc_attributes.c - * @brief Implementation of the update_kyc_attributes function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_error_codes.h" -#include "taler_dbevents.h" -#include "taler_pq_lib.h" -#include "pg_update_kyc_attributes.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -TEH_PG_update_kyc_attributes ( - void *cls, - const struct TALER_PaytoHashP *h_payto, - const struct GNUNET_ShortHashCode *kyc_prox, - const char *provider_section, - const char *birthdate, - struct GNUNET_TIME_Timestamp collection_time, - struct GNUNET_TIME_Timestamp expiration_time, - size_t enc_attributes_size, - const void *enc_attributes) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_auto_from_type (kyc_prox), - GNUNET_PQ_query_param_string (provider_section), - (NULL == birthdate) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (birthdate), - GNUNET_PQ_query_param_timestamp (&collection_time), - GNUNET_PQ_query_param_timestamp (&expiration_time), - GNUNET_PQ_query_param_fixed_size (enc_attributes, - enc_attributes_size), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "update_kyc_attributes", - "UPDATE kyc_attributes SET " - " kyc_prox=$2" - ",birthdate=$4" - ",collection_time=$5" - ",expiration_time=$6" - ",encrypted_attributes=$7" - " WHERE h_payto=$1 AND provider_section=$3;"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_kyc_attributes", - params); -} diff --git a/src/exchangedb/pg_update_kyc_attributes.h b/src/exchangedb/pg_update_kyc_attributes.h deleted file mode 100644 index 5d17eb7fa..000000000 --- a/src/exchangedb/pg_update_kyc_attributes.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_update_kyc_attributes.h - * @brief implementation of the update_kyc_attributes function for Postgres - * @author Christian Grothoff - */ -#ifndef PG_UPDATE_KYC_ATTRIBUTES_H -#define PG_UPDATE_KYC_ATTRIBUTES_H - -#include "taler_util.h" -#include "taler_json_lib.h" -#include "taler_exchangedb_plugin.h" - - -/** - * Update KYC attribute data. - * - * @param cls closure - * @param h_payto account for which the attribute data is stored - * @param kyc_prox key for similarity search - * @param provider_section provider that must be checked - * @param birthdate birthdate of user, in format YYYY-MM-DD; can be NULL; - * digits can be 0 if exact day, month or year are unknown - * @param collection_time when was the data collected - * @param expiration_time when does the data expire - * @param enc_attributes_size number of bytes in @a enc_attributes - * @param enc_attributes encrypted attribute data - * @return database transaction status - */ -enum GNUNET_DB_QueryStatus -TEH_PG_update_kyc_attributes ( - void *cls, - const struct TALER_PaytoHashP *h_payto, - const struct GNUNET_ShortHashCode *kyc_prox, - const char *provider_section, - const char *birthdate, - struct GNUNET_TIME_Timestamp collection_time, - struct GNUNET_TIME_Timestamp expiration_time, - size_t enc_attributes_size, - const void *enc_attributes); - - -#endif diff --git a/src/exchangedb/pg_update_kyc_process_by_row.c b/src/exchangedb/pg_update_kyc_process_by_row.c index 4ae44ce53..711f47802 100644 --- a/src/exchangedb/pg_update_kyc_process_by_row.c +++ b/src/exchangedb/pg_update_kyc_process_by_row.c @@ -68,7 +68,8 @@ TEH_PG_update_kyc_process_by_row ( if (qs <= 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to update legitimization process: %d\n", + "Failed to update legitimization process %llu: %d\n", + (unsigned long long) process_row, qs); return qs; } diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index b3ebc7547..006484198 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -207,7 +207,6 @@ #include "pg_setup_wire_target.h" #include "pg_compute_shard.h" #include "pg_insert_kyc_attributes.h" -#include "pg_update_kyc_attributes.h" #include "pg_select_similar_kyc_attributes.h" #include "pg_select_kyc_attributes.h" #include "pg_insert_aml_officer.h" @@ -754,8 +753,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) = &TEH_PG_set_purse_balance; plugin->insert_kyc_attributes = &TEH_PG_insert_kyc_attributes; - plugin->update_kyc_attributes - = &TEH_PG_update_kyc_attributes; plugin->select_similar_kyc_attributes = &TEH_PG_select_similar_kyc_attributes; plugin->select_kyc_attributes diff --git a/src/exchangedb/procedures.sql.in b/src/exchangedb/procedures.sql.in index 12ec3656f..c9277ea60 100644 --- a/src/exchangedb/procedures.sql.in +++ b/src/exchangedb/procedures.sql.in @@ -39,6 +39,7 @@ SET search_path TO exchange; #include "exchange_do_insert_or_update_policy_details.sql" #include "exchange_do_insert_aml_decision.sql" #include "exchange_do_insert_aml_officer.sql" +#include "exchange_do_insert_kyc_attributes.sql" #include "exchange_do_reserves_in_insert.sql" #include "exchange_do_batch_reserves_update.sql" #include "exchange_do_refund_by_coin.sql" |