commit c887cfd76734ea1896bbe844f81bd29962aab7f7 parent 700fc785c3b537a6fa7c67e5761927956fd1cfb4 Author: Christian Grothoff <christian@grothoff.org> Date: Sat, 24 May 2025 21:35:21 +0200 fix #10003 (exchange KYC auth does not work when non-normalized payto URI differs between withdrawal and KYC auth) Diffstat:
51 files changed, 869 insertions(+), 324 deletions(-)
diff --git a/src/auditor/taler-helper-auditor-reserves.c b/src/auditor/taler-helper-auditor-reserves.c @@ -513,7 +513,7 @@ handle_reserve_in ( * @param denom_serials array with length @e num_denom_serials of serial ID's of denominations in our DB * @param selected_h hash over the gamma-selected planchets * @param h_planchets running hash over all hashes of blinded planchets in the original withdraw request - * @param blinding_seed the master seed used for CS denominations; might be NULL + * @param blinding_seed the blinding seed for CS denominations that was provided during withdraw; might be NULL * @param age_proof_required true if the withdraw request required an age proof. * @param max_age if @e age_proof_required is true, the maximum age that was set on the coins. * @param noreveal_index if @e age_proof_required is true, the index that was returned by the exchange for the reveal phase. diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c @@ -538,10 +538,10 @@ phase_run_transaction ( &mhd_ret, &withdraw_transaction, wc); - GNUNET_break (GNUNET_OK == qs); - /* If the transaction has changed the phase, we don't alter it and return.*/ if (WITHDRAW_PHASE_RUN_TRANSACTION != wc->phase) return; + GNUNET_break (GNUNET_OK == qs); + /* If the transaction has changed the phase, we don't alter it and return.*/ wc->phase++; } diff --git a/src/exchangedb/0002-legitimization_measures.sql b/src/exchangedb/0002-legitimization_measures.sql @@ -46,7 +46,7 @@ BEGIN ,partition_suffix ); PERFORM comment_partitioned_column( - 'foreign key linking the entry to the wire_targets table, NOT a primary key (multiple legitimizations are possible per account)' + 'foreign key linking the entry to the kyc_targets table, NOT a primary key (multiple legitimizations are possible per account)' ,'access_token' ,'legitimization_measures' ,partition_suffix diff --git a/src/exchangedb/0002-legitimization_outcomes.sql b/src/exchangedb/0002-legitimization_outcomes.sql @@ -49,7 +49,7 @@ BEGIN ,partition_suffix ); PERFORM comment_partitioned_column( - 'hash of the payto://-URI this outcome is about; foreign key linking the entry to the wire_targets table, NOT a primary key (multiple outcomes are possible per account over time)' + 'hash of the normalized payto://-URI this outcome is about; foreign key linking the entry to the kyc_targets table, NOT a primary key (multiple outcomes are possible per account over time)' ,'h_payto' ,'legitimization_outcomes' ,partition_suffix diff --git a/src/exchangedb/0002-legitimization_processes.sql b/src/exchangedb/0002-legitimization_processes.sql @@ -53,7 +53,7 @@ BEGIN ,shard_suffix ); PERFORM comment_partitioned_column( - 'hash over the normalized payto URI; foreign key linking the entry to the wire_targets table, NOT a primary key (multiple legitimizations are possible per wire target)' + 'hash over the normalized payto URI; foreign key linking the entry to the kyc_targets table, NOT a primary key (multiple legitimizations are possible per wire target)' ,'h_payto' ,'legitimization_processes' ,shard_suffix @@ -204,4 +204,3 @@ INSERT INTO exchange_tables ,'foreign' ,TRUE ,FALSE); - diff --git a/src/exchangedb/0002-reserves_in.sql b/src/exchangedb/0002-reserves_in.sql @@ -117,7 +117,7 @@ BEGIN ' FOREIGN KEY (wire_source_h_payto)' ' REFERENCES wire_targets (wire_target_h_payto)' ' ON DELETE RESTRICT' - ); + ); END $$; diff --git a/src/exchangedb/0002-wire_targets.sql b/src/exchangedb/0002-wire_targets.sql @@ -47,7 +47,8 @@ BEGIN ,'wire_targets' ,'PARTITION BY HASH (wire_target_h_payto)' ,partition_suffix - ); + +); PERFORM comment_partitioned_table( 'All senders and recipients of money via the exchange' ,'wire_targets' diff --git a/src/exchangedb/0003-kyc_targets.sql b/src/exchangedb/0003-kyc_targets.sql @@ -0,0 +1,156 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2014--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/> +-- + +CREATE FUNCTION create_table_kyc_targets( + IN partition_suffix TEXT DEFAULT NULL +) +RETURNS VOID +LANGUAGE plpgsql +AS $$ +DECLARE + my_rec RECORD; + my_payto TEXT; + my_is_wallet BOOL; + wtc CURSOR FOR + SELECT + access_token + ,target_pub + ,h_normalized_payto + ,aml_program_lock_timeout + ,payto_uri + FROM exchange.wire_targets; +BEGIN + PERFORM create_partitioned_table( + 'CREATE TABLE %I' + '(kyc_target_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' + ',h_normalized_payto BYTEA PRIMARY KEY CHECK(LENGTH(h_normalized_payto)=32)' + ',access_token BYTEA CHECK(LENGTH(access_token)=32)' + ' DEFAULT random_bytea(32)' + ',target_pub BYTEA CHECK(LENGTH(target_pub)=32) DEFAULT NULL' + ',aml_program_lock_timeout INT8 DEFAULT NULL' + ',is_wallet BOOL' + ') %s ;' + ,'kyc_targets' + ,'PARTITION BY HASH (h_normalized_payto)' + ,partition_suffix + ); + PERFORM comment_partitioned_table( + 'All identities for KYC purposes based on normalized payto URIs' + ,'kyc_targets' + ,partition_suffix + ); + PERFORM comment_partitioned_column( + 'high-entropy random value that is used as a bearer token used to authenticate access to the KYC SPA and its state (without requiring a signature)' + ,'access_token' + ,'kyc_targets' + ,NULL + ); + PERFORM comment_partitioned_column( + 'Public key of a merchant instance or reserve to authenticate access; NULL if KYC is not allowed for the account (if there was no incoming KYC wire transfer yet); updated, thus NOT available to the auditor' + ,'target_pub' + ,'kyc_targets' + ,NULL + ); + PERFORM comment_partitioned_column( + 'hash over the normalized payto URI for this account; used for KYC operations' + ,'h_normalized_payto' + ,'kyc_targets' + ,NULL + ); + PERFORM comment_partitioned_column( + 'If non-NULL, an AML program should be running and it holds a lock on this account, thus other AML programs should not be started concurrently. Given the possibility of crashes, the lock automatically expires at the time value given in this column. At that time, the lock can be considered stale.' + ,'aml_program_lock_timeout' + ,'kyc_targets' + ,NULL + ); + PERFORM comment_partitioned_column( + 'True if this KYC account is for a wallet, false if it is for a bank account' + ,'is_wallet' + ,'kyc_targets' + ,NULL + ); + + -- Migrate existing entries. We may have multiple for + -- the same account, which is a historic bug (#10003) + -- we are implicitly fixing here via "ON CONFLICT + -- DO NOTHING" which ensures that moving forward we + -- have a unique access token per KYC account. + FOR my_rec IN wtc + LOOP + my_payto = my_rec.payto_uri; + my_is_wallet + = (LOWER (SUBSTRING (my_payto, 22)) = + 'payto://taler-reserve/') OR + (LOWER (SUBSTRING (my_payto, 27)) = + 'payto://taler-reserve-http/'); + INSERT INTO kyc_targets + (h_normalized_payto + ,access_token + ,target_pub + ,aml_program_lock_timeout + ) VALUES ( + my_rec.h_normalized_payto + ,my_rec.access_token + ,my_rec.target_pub + ,my_rec.aml_program_lock_timeout + ,my_is_wallet + ) + ON CONFLICT DO NOTHING; + END LOOP; +END $$; + + +CREATE FUNCTION constrain_table_kyc_targets( + IN partition_suffix TEXT +) +RETURNS void +LANGUAGE plpgsql +AS $$ +DECLARE + table_name TEXT DEFAULT 'kyc_targets'; +BEGIN + table_name = concat_ws('_', table_name, partition_suffix); + EXECUTE FORMAT ( + 'ALTER TABLE ' || table_name || + ' ADD CONSTRAINT ' || table_name || '_kyc_target_serial_id_key' + ' UNIQUE (kyc_target_serial_id)' + ); + EXECUTE FORMAT ( + 'ALTER TABLE ' || table_name || + ' ADD CONSTRAINT ' || table_name || '_kyc_target_access_token_unique' + ' UNIQUE (access_token)' + ); +END +$$; + + +INSERT INTO exchange_tables + (name + ,version + ,action + ,partitioned + ,by_range) + VALUES + ('kyc_targets' + ,'exchange-0003' + ,'create' + ,TRUE + ,FALSE), + ('kyc_targets' + ,'exchange-0003' + ,'constrain' + ,TRUE + ,FALSE); diff --git a/src/exchangedb/0003-legitimization_measures.sql b/src/exchangedb/0003-legitimization_measures.sql @@ -0,0 +1,49 @@ +-- +-- 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 FUNCTION foreign_table_legitimization_measures3() +RETURNS void +LANGUAGE plpgsql +AS $$ +DECLARE + table_name TEXT DEFAULT 'legitimization_measures'; +BEGIN + + EXECUTE FORMAT ( + 'ALTER TABLE ' || table_name || + ' DROP CONSTRAINT ' || table_name || '_foreign_key_access_token'); + EXECUTE FORMAT ( + 'ALTER TABLE ' || table_name || + ' ADD CONSTRAINT ' || table_name || '_foreign_key_access_token' + ' FOREIGN KEY (access_token)' + ' REFERENCES kyc_targets (access_token)' + ' ON DELETE CASCADE'); +END +$$; + + +INSERT INTO exchange_tables + (name + ,version + ,action + ,partitioned + ,by_range) + VALUES + ('legitimization_measures3' + ,'exchange-0003' + ,'foreign' + ,TRUE + ,FALSE); diff --git a/src/exchangedb/0003-legitimization_outcomes.sql b/src/exchangedb/0003-legitimization_outcomes.sql @@ -0,0 +1,45 @@ +-- +-- 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/> +-- + +CREATE FUNCTION foreign_table_legitimization_outcomes3() +RETURNS void +LANGUAGE plpgsql +AS $$ +DECLARE + table_name TEXT DEFAULT 'legitimization_outcomes'; +BEGIN + EXECUTE FORMAT ( + 'ALTER TABLE ' || table_name || + ' ADD CONSTRAINT ' || table_name || '_foreign_key_h_payto' + ' FOREIGN KEY (h_payto)' + ' REFERENCES kyc_targets (h_normalized_payto)' + ' ON DELETE CASCADE'); +END +$$; + + +INSERT INTO exchange_tables + (name + ,version + ,action + ,partitioned + ,by_range) + VALUES + ('legitimization_outcomes3' + ,'exchange-0003' + ,'foreign' + ,TRUE + ,FALSE); diff --git a/src/exchangedb/0003-legitimization_processes.sql b/src/exchangedb/0003-legitimization_processes.sql @@ -0,0 +1,45 @@ +-- +-- 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/> +-- + +CREATE FUNCTION foreign_table_legitimization_processes3() +RETURNS void +LANGUAGE plpgsql +AS $$ +DECLARE + table_name TEXT DEFAULT 'legitimization_processes'; +BEGIN + EXECUTE FORMAT ( + 'ALTER TABLE ' || table_name || + ' ADD CONSTRAINT ' || table_name || '_foreign_key_h_payto' + ' FOREIGN KEY (h_payto)' + ' REFERENCES kyc_targets (h_normalized_payto)' + ' ON DELETE CASCADE'); +END +$$; + + +INSERT INTO exchange_tables + (name + ,version + ,action + ,partitioned + ,by_range) + VALUES + ('legitimization_processes3' + ,'exchange-0003' + ,'foreign' + ,TRUE + ,FALSE); diff --git a/src/exchangedb/0003-wire_targets.sql b/src/exchangedb/0003-wire_targets.sql @@ -0,0 +1,63 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2014--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/> +-- + +CREATE FUNCTION alter_table_wire_targets3( + IN partition_suffix TEXT DEFAULT NULL +) +RETURNS VOID +LANGUAGE plpgsql +AS $$ +BEGIN + ALTER TABLE wire_targets + DROP COLUMN access_token, + DROP COLUMN aml_program_lock_timeout, + DROP COLUMN target_pub; +END $$; + + +CREATE FUNCTION foreign_table_wire_targets3() +RETURNS void +LANGUAGE plpgsql +AS $$ +DECLARE + table_name TEXT DEFAULT 'wire_targets'; +BEGIN + EXECUTE FORMAT ( + 'ALTER TABLE ' || table_name || + ' ADD CONSTRAINT ' || table_name || '_fk_kyc_targets' + ' FOREIGN KEY (h_normalized_payto) REFERENCES kyc_targets (h_normalized_payto)' + ); +END +$$; + + +INSERT INTO exchange_tables + (name + ,version + ,action + ,partitioned + ,by_range) + VALUES + ('wire_targets3' + ,'exchange-0003' + ,'alter' + ,TRUE + ,FALSE), + ('wire_targets3' + ,'exchange-0003' + ,'foreign' + ,TRUE + ,FALSE); diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am @@ -27,7 +27,9 @@ sqlinputs = \ exchange_trigger_*.sql \ procedures.sql.in \ 0002-*.sql \ - exchange-0002.sql.in + exchange-0002.sql.in \ + 0003-*.sql \ + exchange-0003.sql.in sql_DATA = \ benchmark-0001.sql \ @@ -35,6 +37,7 @@ sql_DATA = \ auditor-triggers-0001.sql \ exchange-0001.sql \ exchange-0002.sql \ + exchange-0003.sql \ drop.sql \ procedures.sql \ tops-0001.sql @@ -47,6 +50,7 @@ BUILT_SOURCES = \ CLEANFILES = \ exchange-0002.sql \ + exchange-0003.sql \ procedures.sql procedures.sql: procedures.sql.in exchange_do_*.sql exchange_statistics_*.sql exchange_trigger_*.sql @@ -59,6 +63,11 @@ exchange-0002.sql: exchange-0002.sql.in 0002-*.sql gcc -E -P -undef - < exchange-0002.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@ chmod ugo-w $@ +exchange-0003.sql: exchange-0003.sql.in 0003-*.sql + chmod +w $@ 2> /dev/null || true + gcc -E -P -undef - < exchange-0003.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@ + chmod ugo-w $@ + check_SCRIPTS = \ test_idempotency.sh diff --git a/src/exchangedb/exchange-0003.sql.in b/src/exchangedb/exchange-0003.sql.in @@ -0,0 +1,32 @@ +-- +-- 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/> +-- + +BEGIN; + +SELECT _v.register_patch('exchange-0003', NULL, NULL); +SET search_path TO exchange; + +#include "0003-kyc_targets.sql" +#include "0003-legitimization_measures.sql" +#include "0003-legitimization_outcomes.sql" +#include "0003-legitimization_processes.sql" +-- Note that wire_targets MUST be after kyc_targets and +-- legitimization measures here, +-- as we first need to create kyc_targets and migrate the +-- data before dropping it in wire_targets! +#include "0003-wire_targets.sql" + +COMMIT; diff --git a/src/exchangedb/exchange_do_deposit.sql b/src/exchangedb/exchange_do_deposit.sql @@ -1,6 +1,6 @@ -- -- This file is part of TALER --- Copyright (C) 2014--2023 Taler Systems SA +-- Copyright (C) 2014--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 @@ -38,6 +38,7 @@ CREATE FUNCTION exchange_do_deposit( IN ina_coin_sig BYTEA[], IN ina_amount_with_fee taler_amount[], IN in_total_amount taler_amount, + IN in_is_wallet BOOL, OUT out_exchange_timestamp INT8, OUT out_insufficient_balance_coin_index INT4, -- index of coin with bad balance, NULL if none OUT out_conflict BOOL @@ -59,30 +60,36 @@ BEGIN -- UPDATE[] known_coins (by coin_pub) +-- Make sure the kyc_target entry exists +INSERT INTO kyc_targets + (h_normalized_payto + ,is_wallet + ) VALUES ( + in_h_normalized_payto + ,in_is_wallet + ) + ON CONFLICT DO NOTHING; + -- First, get or create the 'wtsi' INSERT INTO wire_targets - (wire_target_h_payto - ,h_normalized_payto - ,payto_uri) - VALUES - (in_wire_target_h_payto - ,in_h_normalized_payto - ,in_receiver_wire_account) + (wire_target_h_payto + ,h_normalized_payto + ,payto_uri + ) VALUES ( + in_wire_target_h_payto + ,in_h_normalized_payto + ,in_receiver_wire_account + ) ON CONFLICT DO NOTHING -- for CONFLICT ON (wire_target_h_payto) - RETURNING - wire_target_serial_id - INTO - wtsi; + RETURNING wire_target_serial_id + INTO wtsi; IF NOT FOUND THEN - SELECT - wire_target_serial_id - INTO - wtsi - FROM wire_targets - WHERE - wire_target_h_payto=in_wire_target_h_payto; + SELECT wire_target_serial_id + INTO wtsi + FROM wire_targets + WHERE wire_target_h_payto=in_wire_target_h_payto; END IF; @@ -102,9 +109,8 @@ INSERT INTO batch_deposits ,policy_details_serial_id ,policy_blocked ,total_amount - ) - VALUES - (in_shard + ) VALUES ( + in_shard ,in_merchant_pub ,in_merchant_sig ,in_wallet_timestamp @@ -172,9 +178,8 @@ LOOP ,coin_pub ,coin_sig ,amount_with_fee - ) - VALUES - (bdsi + ) VALUES ( + bdsi ,ini_coin_pub ,ini_coin_sig ,ini_amount_with_fee diff --git a/src/exchangedb/exchange_do_insert_aml_decision.sql b/src/exchangedb/exchange_do_insert_aml_decision.sql @@ -39,7 +39,7 @@ CREATE FUNCTION exchange_do_insert_aml_decision( OUT out_account_unknown BOOLEAN, OUT out_last_date INT8, OUT out_legitimization_measure_serial_id INT8, - OUT out_payto_uri TEXT) + OUT out_is_wallet BOOL) -- can be (left at) NULL LANGUAGE plpgsql AS $$ DECLARE @@ -101,33 +101,48 @@ ELSE END IF; SELECT access_token - ,payto_uri + ,is_wallet INTO my_rec - FROM wire_targets + FROM kyc_targets WHERE h_normalized_payto=in_h_normalized_payto; IF NOT FOUND THEN + -- AML decision for previously unknown account; better includes + -- all required details about the account ... IF in_payto_uri IS NULL THEN -- AML decision on an unknown account without payto_uri => fail. out_account_unknown=TRUE; RETURN; END IF; - out_payto_uri = in_payto_uri; + -- Well, fine, setup the account + out_is_wallet + = (LOWER (SUBSTRING (in_payto_uri, 22)) = + 'payto://taler-reserve/') OR + (LOWER (SUBSTRING (in_payto_uri, 27)) = + 'payto://taler-reserve-http/'); + INSERT INTO kyc_targets + (h_normalized_payto + ,is_wallet + ) VALUES ( + in_h_full_payto + ,out_is_wallet + ) + RETURNING access_token + INTO my_access_token; INSERT INTO wire_targets (wire_target_h_payto ,h_normalized_payto - ,payto_uri) - VALUES - (in_h_full_payto + ,payto_uri + ) VALUES ( + in_h_full_payto ,in_h_normalized_payto - ,in_payto_uri) - RETURNING access_token - INTO my_access_token; + ,in_payto_uri + ); ELSE my_access_token = my_rec.access_token; - out_payto_uri = my_rec.payto_uri; + out_is_wallet = my_rec.is_wallet; END IF; -- Did KYC measures get prescribed? @@ -149,9 +164,9 @@ THEN (access_token ,start_time ,jmeasures - ,display_priority) - VALUES - (my_access_token + ,display_priority + ) VALUES ( + my_access_token ,in_decision_time ,in_jmeasures ,1) @@ -187,9 +202,8 @@ INSERT INTO legitimization_outcomes ,new_measure_name ,to_investigate ,jnew_rules - ) - VALUES - (in_h_normalized_payto + ) VALUES ( + in_h_normalized_payto ,in_decision_time ,in_expiration_time ,in_properties @@ -197,10 +211,8 @@ INSERT INTO legitimization_outcomes ,in_to_investigate ,in_new_rules ) - RETURNING - outcome_serial_id - INTO - my_outcome_serial_id; + RETURNING outcome_serial_id + INTO my_outcome_serial_id; IF in_kyc_attributes_enc IS NOT NULL THEN @@ -220,8 +232,8 @@ THEN ,provider_name ,provider_user_id ,finished - ) VALUES - (in_h_normalized_payto + ) VALUES ( + in_h_normalized_payto ,in_decision_time -- Process starts and finishes instantly ,in_decision_time @@ -240,8 +252,8 @@ THEN ,by_aml_officer ,encrypted_attributes ,legitimization_serial - ) VALUES - (in_h_normalized_payto + ) VALUES ( + in_h_normalized_payto ,in_decision_time ,in_kyc_attributes_expiration ,in_form_name @@ -263,8 +275,8 @@ THEN ,decider_sig ,kyc_attributes_hash ,kyc_attributes_serial_id - ) VALUES - (in_h_normalized_payto + ) VALUES ( + in_h_normalized_payto ,my_outcome_serial_id ,in_justification ,in_decider_pub @@ -280,18 +292,20 @@ LOOP ini_event = ina_events[i]; INSERT INTO kyc_events (event_timestamp - ,event_type) - VALUES - (in_decision_time + ,event_type + ) VALUES ( + in_decision_time ,ini_event); END LOOP; -- wake up taler-exchange-aggregator INSERT INTO kyc_alerts (h_payto - ,trigger_type) - VALUES - (in_h_normalized_payto,1) + ,trigger_type + ) VALUES ( + in_h_normalized_payto + ,1 + ) ON CONFLICT DO NOTHING; EXECUTE FORMAT ( diff --git a/src/exchangedb/exchange_do_insert_successor_measure.sql b/src/exchangedb/exchange_do_insert_successor_measure.sql @@ -30,6 +30,7 @@ AS $$ DECLARE my_outcome_serial_id INT8; my_access_token BYTEA; + my_is_wallet BOOL; BEGIN out_account_unknown=FALSE; @@ -60,7 +61,7 @@ END IF; SELECT access_token INTO my_access_token - FROM wire_targets + FROM kyc_targets WHERE h_normalized_payto=in_h_normalized_payto; IF NOT FOUND @@ -72,6 +73,19 @@ THEN RETURN; END IF; + my_is_wallet + = (LOWER (SUBSTRING (in_payto_uri, 22)) = + 'payto://taler-reserve/') OR + (LOWER (SUBSTRING (in_payto_uri, 27)) = + 'payto://taler-reserve-http/'); + INSERT INTO kyc_targets + (h_normalized_payto + ,is_wallet) + VALUES + (in_h_normalized_payto + ,my_is_wallet) + RETURNING access_token + INTO my_access_token; INSERT INTO wire_targets (wire_target_h_payto ,h_normalized_payto @@ -79,9 +93,7 @@ THEN VALUES (in_h_full_payto ,in_h_normalized_payto - ,in_payto_uri) - RETURNING access_token - INTO my_access_token; + ,in_payto_uri); END IF; diff --git a/src/exchangedb/exchange_do_kycauth_in_insert.sql b/src/exchangedb/exchange_do_kycauth_in_insert.sql @@ -28,6 +28,8 @@ CREATE PROCEDURE exchange_do_kycauth_in_insert( IN in_notify_s TEXT) LANGUAGE plpgsql AS $$ +DECLARE + my_is_wallet BOOL; BEGIN INSERT INTO kycauths_in @@ -53,22 +55,34 @@ BEGIN RETURN; END IF; - UPDATE wire_targets + UPDATE kyc_targets SET target_pub=in_account_pub - WHERE wire_target_h_payto=in_wire_source_h_payto; + WHERE h_normalized_payto=in_h_normalized_payto; IF NOT FOUND THEN + -- First time we see this account, setup everything. + my_is_wallet + = (LOWER (SUBSTRING (in_payto_uri, 22)) = + 'payto://taler-reserve/') OR + (LOWER (SUBSTRING (in_payto_uri, 27)) = + 'payto://taler-reserve-http/'); + INSERT INTO kyc_targets + (h_normalized_payto + ,is_wallet + ,target_pub + ) VALUES ( + in_h_normalized_payto + ,my_is_wallet + ,in_account_pub); INSERT INTO wire_targets (wire_target_h_payto ,h_normalized_payto ,payto_uri - ,target_pub ) VALUES ( in_wire_source_h_payto ,in_h_normalized_payto - ,in_payto_uri - ,in_account_pub); + ,in_payto_uri); END IF; EXECUTE FORMAT ( diff --git a/src/exchangedb/exchange_do_lookup_kyc_requirement_by_row.sql b/src/exchangedb/exchange_do_lookup_kyc_requirement_by_row.sql @@ -23,7 +23,7 @@ CREATE FUNCTION exchange_do_lookup_kyc_requirement_by_row( OUT out_reserve_pub BYTEA, -- NULL allowed OUT out_access_token BYTEA, -- NULL if 'out_not_found' OUT out_jrules TEXT, -- NULL allowed - OUT out_payto TEXT, -- NULL allowed + OUT out_is_wallet BOOLEAN, -- NULL allowed OUT out_not_found BOOLEAN, OUT out_rule_gen INT8, -- NULL allowed OUT out_aml_review BOOLEAN, -- NULL allowed @@ -38,9 +38,9 @@ BEGIN -- Find the access token and the current account public key. SELECT access_token ,target_pub - ,payto_uri + ,is_wallet INTO my_wtrec - FROM wire_targets + FROM kyc_targets WHERE h_normalized_payto=in_h_normalized_payto; IF NOT FOUND @@ -51,7 +51,7 @@ THEN END IF; out_not_found = FALSE; -out_payto = my_wtrec.payto_uri; +out_is_wallet = my_wtrec.is_wallet; out_account_pub = my_wtrec.target_pub; out_access_token = my_wtrec.access_token; diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -36,6 +36,7 @@ DECLARE dup BOOL; uuid INT8; i INT4; + my_is_wallet BOOL; ini_reserve_pub BYTEA; ini_wire_ref INT8; ini_credit taler_amount; @@ -61,6 +62,19 @@ BEGIN -- RAISE WARNING 'Starting loop on %', ini_notify; + my_is_wallet + = (LOWER (SUBSTRING (ini_payto_uri, 22)) = + 'payto://taler-reserve/') OR + (LOWER (SUBSTRING (ini_payto_uri, 27)) = + 'payto://taler-reserve-http/'); + INSERT INTO kyc_targets + (h_normalized_payto + ,is_wallet + ) VALUES ( + ini_h_normalized_payto + ,my_is_wallet + ) + ON CONFLICT DO NOTHING; INSERT INTO wire_targets (wire_target_h_payto ,h_normalized_payto diff --git a/src/exchangedb/exchange_do_set_aml_lock.sql b/src/exchangedb/exchange_do_set_aml_lock.sql @@ -24,7 +24,7 @@ LANGUAGE plpgsql AS $$ BEGIN -UPDATE wire_targets +UPDATE kyc_targets SET aml_program_lock_timeout=in_expiration WHERE h_normalized_payto=in_h_payto AND ( (aml_program_lock_timeout IS NULL) @@ -33,7 +33,7 @@ IF NOT FOUND THEN SELECT aml_program_lock_timeout INTO out_aml_program_lock_timeout - FROM wire_targets + FROM kyc_targets WHERE h_normalized_payto=in_h_payto; ELSE out_aml_program_lock_timeout = 0; diff --git a/src/exchangedb/exchange_do_trigger_kyc_rule_for_account.sql b/src/exchangedb/exchange_do_trigger_kyc_rule_for_account.sql @@ -32,6 +32,7 @@ LANGUAGE plpgsql AS $$ DECLARE my_rec RECORD; + my_is_wallet BOOL; my_access_token BYTEA; my_account_pub BYTEA; my_reserve_pub BYTEA; @@ -39,14 +40,11 @@ BEGIN -- Note: in_payto_uri is allowed to be NULL *if* -- in_h_normalized_payto is already in wire_targets - -SELECT - access_token - ,target_pub -INTO - my_rec -FROM wire_targets - WHERE h_normalized_payto=in_h_normalized_payto; +SELECT access_token + ,target_pub + INTO my_rec + FROM kyc_targets + WHERE h_normalized_payto=in_h_normalized_payto; IF FOUND THEN @@ -57,19 +55,31 @@ THEN ELSE -- No constraint on merchant_pub, just create -- the wire_target. + my_is_wallet + = (LOWER (SUBSTRING (in_payto_uri, 22)) = + 'payto://taler-reserve/') OR + (LOWER (SUBSTRING (in_payto_uri, 27)) = + 'payto://taler-reserve-http/'); + INSERT INTO kyc_targets + (h_normalized_payto + ,is_wallet + ,target_pub + ) VALUES ( + in_h_normalized_payto + ,my_is_wallet + ,in_account_pub + ) + RETURNING access_token + INTO my_access_token; INSERT INTO wire_targets (payto_uri ,wire_target_h_payto ,h_normalized_payto - ,target_pub) - VALUES - (in_payto_uri + ) VALUES ( + in_payto_uri ,in_h_full_payto ,in_h_normalized_payto - ,in_account_pub) - RETURNING - access_token - INTO my_access_token; + ); out_bad_kyc_auth=TRUE; END IF; @@ -107,16 +117,14 @@ THEN (access_token ,start_time ,jmeasures - ,display_priority) - VALUES - (my_access_token + ,display_priority + ) VALUES ( + my_access_token ,in_now ,in_jmeasures ,in_display_priority) - RETURNING - legitimization_measure_serial_id - INTO - out_legitimization_measure_serial_id; + RETURNING legitimization_measure_serial_id + INTO out_legitimization_measure_serial_id; -- mark all other active measures finished! UPDATE legitimization_measures diff --git a/src/exchangedb/exchange_do_withdraw.sql b/src/exchangedb/exchange_do_withdraw.sql @@ -70,6 +70,7 @@ THEN out_reserve_balance.frac = 0; out_balance_ok = FALSE; out_nonce_reuse = FALSE; + out_reserve_birthday = 0; RETURN; END IF; diff --git a/src/exchangedb/pg_clear_aml_lock.c b/src/exchangedb/pg_clear_aml_lock.c @@ -40,9 +40,8 @@ TEH_PG_clear_aml_lock ( PREPARE (pg, "clear_aml_lock", - "UPDATE wire_targets" - " SET" - " aml_program_lock_timeout=NULL" + "UPDATE kyc_targets" + " SET aml_program_lock_timeout=NULL" " WHERE h_normalized_payto=$1"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "clear_aml_lock", diff --git a/src/exchangedb/pg_do_deposit.c b/src/exchangedb/pg_do_deposit.c @@ -77,6 +77,8 @@ TEH_PG_do_deposit ( pg->conn), TALER_PQ_query_param_amount (pg->conn, &total_amount), + GNUNET_PQ_query_param_bool (TALER_payto_is_wallet ( + bd->receiver_wire_account.full_payto)), GNUNET_PQ_query_param_end }; bool no_time; @@ -129,8 +131,7 @@ TEH_PG_do_deposit ( ",out_insufficient_balance_coin_index AS insufficient_balance_coin_index" ",out_conflict AS conflicted" " FROM exchange_do_deposit" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19);") - ; + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20);"); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "call_deposit", params, diff --git a/src/exchangedb/pg_get_kyc_rules.c b/src/exchangedb/pg_get_kyc_rules.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022-2024 Taler Systems SA + Copyright (C) 2022-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 @@ -72,17 +72,23 @@ TEH_PG_get_kyc_rules ( PREPARE (pg, "get_kyc_rules", "SELECT" - " wt.target_pub" + " kt.target_pub" " ,lo.jnew_rules" " ,ri.reserve_pub" - " FROM wire_targets wt" + " FROM kyc_targets kt" + /* This may result in multiple matches */ + " JOIN wire_targets wt" + " USING (h_normalized_payto)" + /* zero or more matches, reserve_pub will be NULL if no match */ " LEFT JOIN reserves_in ri" " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)" + /* zero or more matches, jnew_rules will be NULL if no match */ " LEFT JOIN legitimization_outcomes lo" - " ON (lo.h_payto = wt.h_normalized_payto)" - " WHERE wt.h_normalized_payto=$1" + " ON (lo.h_payto = kt.h_normalized_payto)" + " WHERE kt.h_normalized_payto=$1" " AND COALESCE(lo.expiration_time >= $2, TRUE)" " AND COALESCE(lo.is_active, TRUE)" + /* If multiple reserves_in match, we pick the latest one */ " ORDER BY ri.execution_date DESC" " LIMIT 1;"); return GNUNET_PQ_eval_prepared_singleton_select ( diff --git a/src/exchangedb/pg_get_wire_hash_for_contract.c b/src/exchangedb/pg_get_wire_hash_for_contract.c @@ -55,13 +55,13 @@ TEH_PG_get_wire_hash_for_contract ( PREPARE (pg, "get_wire_hash_for_contract", "SELECT" - " bdep.wire_salt" - ",wt.payto_uri" + " bdep.wire_salt" + " ,wt.payto_uri" " FROM coin_deposits" - " JOIN batch_deposits bdep" - " USING (batch_deposit_serial_id)" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" + " JOIN batch_deposits bdep" + " USING (batch_deposit_serial_id)" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" " WHERE bdep.merchant_pub=$1" " AND bdep.h_contract_terms=$2"); /* NOTE: above query might be more efficient if we computed the shard diff --git a/src/exchangedb/pg_insert_aml_decision.c b/src/exchangedb/pg_insert_aml_decision.c @@ -64,6 +64,7 @@ TEH_PG_insert_aml_decision ( struct TALER_FullPaytoHashP h_full_payto; char *notify_s = GNUNET_PQ_get_event_notify_channel (&rep.header); + bool account_unknown; struct GNUNET_PQ_QueryParam params[] = { /* $1: in_payto_uri */ NULL == payto_uri.full_payto @@ -129,7 +130,6 @@ TEH_PG_insert_aml_decision ( : GNUNET_PQ_query_param_string (form_name), GNUNET_PQ_query_param_end }; - char *rpayto = NULL; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_bool ("out_invalid_officer", invalid_officer), @@ -140,13 +140,14 @@ TEH_PG_insert_aml_decision ( GNUNET_PQ_result_spec_uint64 ("out_legitimization_measure_serial_id", legitimization_measure_serial_id), GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("out_payto_uri", - &rpayto), - NULL), + GNUNET_PQ_result_spec_bool ("out_is_wallet", + is_wallet), + &account_unknown), GNUNET_PQ_result_spec_end }; enum GNUNET_DB_QueryStatus qs; + *is_wallet = false; GNUNET_assert ( ( (NULL == decider_pub) && (NULL == decider_sig) && (NULL == justification) ) || @@ -164,7 +165,7 @@ TEH_PG_insert_aml_decision ( ",out_account_unknown" ",out_last_date" ",out_legitimization_measure_serial_id" - ",out_payto_uri" + ",out_is_wallet" " FROM exchange_do_insert_aml_decision" "($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19);"); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, @@ -176,12 +177,7 @@ TEH_PG_insert_aml_decision ( GNUNET_PQ_event_do_poll (pg->conn); if (qs <= 0) return qs; - if (NULL != rpayto) - { - *is_wallet = TALER_payto_is_wallet (rpayto); - GNUNET_free (rpayto); - } - else + if (account_unknown) { GNUNET_assert ((*invalid_officer) || (*unknown_account)); } diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c @@ -159,7 +159,7 @@ irbt_cb_table_denomination_revocations ( /** - * Function called with denominations records to insert into table. + * Function called with wire target records to insert into table. * * @param pg plugin context * @param td record to insert @@ -176,12 +176,6 @@ irbt_cb_table_wire_targets (struct PostgresClosure *pg, GNUNET_PQ_query_param_auto_from_type (&normalized_payto_hash), GNUNET_PQ_query_param_string ( td->details.wire_targets.full_payto_uri.full_payto), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wire_targets.access_token), - td->details.wire_targets.no_account - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type ( - &td->details.wire_targets.target_pub), GNUNET_PQ_query_param_end }; @@ -198,12 +192,52 @@ irbt_cb_table_wire_targets (struct PostgresClosure *pg, ",wire_target_h_payto" ",h_normalized_payto" ",payto_uri" + ") VALUES " + "($1, $2, $3, $4);"); + return GNUNET_PQ_eval_prepared_non_select ( + pg->conn, + "insert_into_table_wire_targets", + params); +} + + +/** + * Function called with kyc target records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_kyc_targets (struct PostgresClosure *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.kyc_targets.h_normalized_payto), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.kyc_targets.access_token), + td->details.kyc_targets.no_account + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type ( + &td->details.kyc_targets.target_pub), + GNUNET_PQ_query_param_bool ( + td->details.kyc_targets.is_wallet), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_kyc_targets", + "INSERT INTO kyc_targets" + "(kyc_target_serial_id" + ",h_normalized_payto" ",access_token" ",target_pub" + ",is_wallet" ") VALUES " - "($1, $2, $3, $4, $5, $6);"); + "($1, $2, $3, $4,);"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_wire_targets", + "insert_into_table_kyc_targets", params); } @@ -2279,6 +2313,9 @@ TEH_PG_insert_records_by_table (void *cls, case TALER_EXCHANGEDB_RT_WIRE_TARGETS: rh = &irbt_cb_table_wire_targets; break; + case TALER_EXCHANGEDB_RT_KYC_TARGETS: + rh = &irbt_cb_table_kyc_targets; + break; case TALER_EXCHANGEDB_RT_RESERVES: rh = &irbt_cb_table_reserves; break; diff --git a/src/exchangedb/pg_iterate_reserve_close_info.c b/src/exchangedb/pg_iterate_reserve_close_info.c @@ -112,10 +112,9 @@ TEH_PG_iterate_reserve_close_info ( PREPARE (pg, "iterate_reserve_close_info", - "SELECT" - " amount" - ",execution_date" - " FROM reserves_close" + "SELECT amount" + " ,execution_date" + " FROM reserves_close" " WHERE wire_target_h_payto IN (" " SELECT wire_target_h_payto" " FROM wire_targets" diff --git a/src/exchangedb/pg_kyc_provider_account_lookup.c b/src/exchangedb/pg_kyc_provider_account_lookup.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022-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 @@ -41,28 +41,26 @@ TEH_PG_kyc_provider_account_lookup ( GNUNET_PQ_query_param_string (provider_name), GNUNET_PQ_query_param_end }; - char *payto_uri; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_auto_from_type ("h_payto", h_payto), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri), + GNUNET_PQ_result_spec_bool ("is_wallet", + is_wallet), GNUNET_PQ_result_spec_uint64 ("legitimization_process_serial_id", process_row), GNUNET_PQ_result_spec_end }; enum GNUNET_DB_QueryStatus qs; - *is_wallet = false; PREPARE (pg, "get_wire_target_by_legitimization_id", "SELECT " " lp.h_payto" - ",wt.payto_uri" + ",kt.is_wallet" ",lp.legitimization_process_serial_id" " FROM legitimization_processes lp" - " JOIN wire_targets wt" - " ON (lp.h_payto = wt.h_normalized_payto)" + " JOIN kyc_targets kt" + " ON (lp.h_payto = kt.h_normalized_payto)" " WHERE provider_legitimization_id=$1" " AND provider_name=$2;"); qs = GNUNET_PQ_eval_prepared_singleton_select ( @@ -72,7 +70,5 @@ TEH_PG_kyc_provider_account_lookup ( rs); if (qs <= 0) return qs; - *is_wallet = TALER_payto_is_wallet (payto_uri); - GNUNET_free (payto_uri); return qs; } diff --git a/src/exchangedb/pg_lookup_completed_legitimization.c b/src/exchangedb/pg_lookup_completed_legitimization.c @@ -46,7 +46,6 @@ TEH_PG_lookup_completed_legitimization ( GNUNET_PQ_query_param_uint32 (&measure_index), GNUNET_PQ_query_param_end }; - char *payto_uri; struct GNUNET_PQ_ResultSpec rs[] = { TALER_PQ_result_spec_json ( "jmeasures", @@ -66,42 +65,35 @@ TEH_PG_lookup_completed_legitimization ( encrypted_attributes, encrypted_attributes_len), NULL), - GNUNET_PQ_result_spec_string ( - "payto_uri", - &payto_uri), + GNUNET_PQ_result_spec_bool ( + "is_wallet", + is_wallet), GNUNET_PQ_result_spec_end }; - enum GNUNET_DB_QueryStatus qs; *encrypted_attributes_len = 0; *encrypted_attributes = NULL; - *is_wallet = false; PREPARE (pg, "lookup_completed_legitimization", "SELECT " " lm.jmeasures" - ",wt.h_normalized_payto" - ",wt.payto_uri" + ",kt.h_normalized_payto" + ",kt.is_wallet" ",lm.access_token" ",lm.is_finished" ",ka.encrypted_attributes" " FROM legitimization_measures lm" - " JOIN wire_targets wt" - " ON (lm.access_token = wt.access_token)" + " JOIN kyc_targets kt" + " ON (lm.access_token = kt.access_token)" " LEFT JOIN legitimization_processes lp" " ON (lm.legitimization_measure_serial_id = lp.legitimization_measure_serial_id)" " LEFT JOIN kyc_attributes ka" " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)" " WHERE lm.legitimization_measure_serial_id=$1" " AND lp.measure_index=$2;"); - qs = GNUNET_PQ_eval_prepared_singleton_select ( + return GNUNET_PQ_eval_prepared_singleton_select ( pg->conn, "lookup_completed_legitimization", params, rs); - if (qs <= 0) - return qs; - *is_wallet = TALER_payto_is_wallet (payto_uri); - GNUNET_free (payto_uri); - return qs; } diff --git a/src/exchangedb/pg_lookup_h_payto_by_access_token.c b/src/exchangedb/pg_lookup_h_payto_by_access_token.c @@ -38,34 +38,26 @@ TEH_PG_lookup_h_payto_by_access_token ( GNUNET_PQ_query_param_auto_from_type (access_token), GNUNET_PQ_query_param_end }; - char *payto; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_auto_from_type ( "h_normalized_payto", h_payto), - GNUNET_PQ_result_spec_string ( - "payto_uri", - &payto), + GNUNET_PQ_result_spec_bool ( + "is_wallet", + is_wallet), GNUNET_PQ_result_spec_end }; - enum GNUNET_DB_QueryStatus qs; - *is_wallet = false; PREPARE (pg, "lookup_h_payto_by_access_token", "SELECT " " h_normalized_payto" - " ,payto_uri" - " FROM wire_targets" + " ,is_wallet" + " FROM kyc_targets" " WHERE (access_token = $1);"); - qs = GNUNET_PQ_eval_prepared_singleton_select ( + return GNUNET_PQ_eval_prepared_singleton_select ( pg->conn, "lookup_h_payto_by_access_token", params, rs); - if (qs <= 0) - return qs; - *is_wallet = TALER_payto_is_wallet (payto); - GNUNET_free (payto); - return qs; } diff --git a/src/exchangedb/pg_lookup_kyc_process_by_account.c b/src/exchangedb/pg_lookup_kyc_process_by_account.c @@ -43,7 +43,6 @@ TEH_PG_lookup_kyc_process_by_account ( GNUNET_PQ_query_param_string (provider_name), GNUNET_PQ_query_param_end }; - char *payto_uri; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_uint64 ( "legitimization_process_serial_id", @@ -61,42 +60,35 @@ TEH_PG_lookup_kyc_process_by_account ( "provider_legitimization_id", provider_legitimization_id), NULL), - GNUNET_PQ_result_spec_string ( - "payto_uri", - &payto_uri), + GNUNET_PQ_result_spec_bool ( + "is_wallet", + is_wallet), GNUNET_PQ_result_spec_end }; - enum GNUNET_DB_QueryStatus qs; *provider_account_id = NULL; *provider_legitimization_id = NULL; - *is_wallet = false; PREPARE (pg, - "lookup_process_by_account", + "lookup_kyc_process_by_account", "SELECT " " lp.legitimization_process_serial_id" ",lp.expiration_time" ",lp.provider_user_id" ",lp.provider_legitimization_id" - ",wt.payto_uri" + ",kt.is_wallet" " FROM legitimization_processes lp" - " JOIN wire_targets wt" - " ON (lp.h_payto = wt.h_normalized_payto)" + " JOIN kyc_targets kt" + " ON (lp.h_payto = kt.h_normalized_payto)" " WHERE h_payto=$1" " AND provider_name=$2" " AND NOT finished" /* Note: there *should* only be one unfinished match, so this is just to be safe(r): */ - " ORDER BY expiration_time DESC" + " ORDER BY lp.expiration_time DESC" " LIMIT 1;"); - qs = GNUNET_PQ_eval_prepared_singleton_select ( + return GNUNET_PQ_eval_prepared_singleton_select ( pg->conn, - "lookup_process_by_account", + "lookup_kyc_process_by_account", params, rs); - if (qs <= 0) - return qs; - *is_wallet = TALER_payto_is_wallet (payto_uri); - GNUNET_free (payto_uri); - return qs; } diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.c b/src/exchangedb/pg_lookup_kyc_requirement_by_row.c @@ -45,7 +45,6 @@ TEH_PG_lookup_kyc_requirement_by_row ( GNUNET_PQ_query_param_end }; bool not_found; - char *payto = NULL; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("account_pub", @@ -66,8 +65,8 @@ TEH_PG_lookup_kyc_requirement_by_row ( NULL), GNUNET_PQ_result_spec_allow_null ( /* can be NULL due to LEFT JOIN */ - GNUNET_PQ_result_spec_string ("payto", - &payto), + GNUNET_PQ_result_spec_bool ("is_wallet", + is_wallet), NULL), GNUNET_PQ_result_spec_allow_null ( /* can be NULL due to LEFT JOIN */ @@ -106,7 +105,7 @@ TEH_PG_lookup_kyc_requirement_by_row ( ",out_reserve_pub AS reserve_pub" ",out_access_token AS access_token" ",out_jrules AS jrules" - ",out_payto AS payto" + ",out_is_wallet AS is_wallet" ",out_not_found AS not_found" ",out_aml_review AS aml_review" ",out_kyc_required AS kyc_required" @@ -120,11 +119,6 @@ TEH_PG_lookup_kyc_requirement_by_row ( rs); if (qs <= 0) return qs; - if (NULL != payto) - { - *is_wallet = TALER_payto_is_wallet (payto); - GNUNET_free (payto); - } if (not_found) return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; return qs; diff --git a/src/exchangedb/pg_lookup_pending_legitimization.c b/src/exchangedb/pg_lookup_pending_legitimization.c @@ -41,7 +41,6 @@ TEH_PG_lookup_pending_legitimization ( GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id), GNUNET_PQ_query_param_end }; - char *payto_uri; struct GNUNET_PQ_ResultSpec rs[] = { TALER_PQ_result_spec_json ( "jmeasures", @@ -55,34 +54,27 @@ TEH_PG_lookup_pending_legitimization ( GNUNET_PQ_result_spec_bool ( "is_finished", is_finished), - GNUNET_PQ_result_spec_string ( - "payto_uri", - &payto_uri), + GNUNET_PQ_result_spec_bool ( + "is_wallet", + is_wallet), GNUNET_PQ_result_spec_end }; - enum GNUNET_DB_QueryStatus qs; - *is_wallet = false; PREPARE (pg, "lookup_pending_legitimization", "SELECT " " lm.jmeasures" - ",wt.h_normalized_payto" - ",wt.payto_uri" + ",kt.h_normalized_payto" + ",kt.is_wallet" ",lm.access_token" ",lm.is_finished" " FROM legitimization_measures lm" - " JOIN wire_targets wt" - " ON (lm.access_token = wt.access_token)" + " JOIN kyc_targets kt" + " USING (access_token)" " WHERE lm.legitimization_measure_serial_id=$1;"); - qs = GNUNET_PQ_eval_prepared_singleton_select ( + return GNUNET_PQ_eval_prepared_singleton_select ( pg->conn, "lookup_pending_legitimization", params, rs); - if (qs <= 0) - return qs; - *is_wallet = TALER_payto_is_wallet (payto_uri); - GNUNET_free (payto_uri); - return qs; } diff --git a/src/exchangedb/pg_lookup_records_by_table.c b/src/exchangedb/pg_lookup_records_by_table.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet - Copyright (C) 2020-2024 Taler Systems SA + Copyright (C) 2020-2025 Taler Systems SA GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published @@ -213,17 +213,65 @@ lrbt_cb_table_wire_targets (void *cls, GNUNET_PQ_result_spec_uint64 ( "serial", &td.serial), + GNUNET_PQ_result_spec_string ( + "payto_uri", + &td.details.wire_targets.full_payto_uri.full_payto), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with wire_targets table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_kyc_targets (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_KYC_TARGETS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "h_normalized_payto", + &td.details.kyc_targets.h_normalized_payto), GNUNET_PQ_result_spec_auto_from_type ( "access_token", - &td.details.wire_targets.access_token), + &td.details.kyc_targets.access_token), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ( "target_pub", - &td.details.wire_targets.target_pub), - &td.details.wire_targets.no_account), - GNUNET_PQ_result_spec_string ( - "payto_uri", - &td.details.wire_targets.full_payto_uri.full_payto), + &td.details.kyc_targets.target_pub), + &td.details.kyc_targets.no_account), + GNUNET_PQ_result_spec_bool ( + "is_wallet", + &td.details.kyc_targets.is_wallet), GNUNET_PQ_result_spec_end }; @@ -3095,14 +3143,25 @@ TEH_PG_lookup_records_by_table (void *cls, XPREPARE ("select_above_serial_by_table_wire_targets", "SELECT" " wire_target_serial_id AS serial" - ",access_token" - ",target_pub" ",payto_uri" " FROM wire_targets" " WHERE wire_target_serial_id > $1" " ORDER BY wire_target_serial_id ASC;"); rh = &lrbt_cb_table_wire_targets; break; + case TALER_EXCHANGEDB_RT_KYC_TARGETS: + XPREPARE ("select_above_serial_by_table_kyc_targets", + "SELECT" + " kyc_target_serial_id AS serial" + ",h_normalized_payto" + ",access_token" + ",target_pub" + ",is_wallet" + " FROM kyc_targets" + " WHERE kyc_target_serial_id > $1" + " ORDER BY kyc_target_serial_id ASC;"); + rh = &lrbt_cb_table_kyc_targets; + break; case TALER_EXCHANGEDB_RT_RESERVES: XPREPARE ("select_above_serial_by_table_reserves", "SELECT" diff --git a/src/exchangedb/pg_lookup_serial_by_table.c b/src/exchangedb/pg_lookup_serial_by_table.c @@ -77,6 +77,14 @@ TEH_PG_lookup_serial_by_table (void *cls, " ORDER BY wire_target_serial_id DESC" " LIMIT 1;"); break; + case TALER_EXCHANGEDB_RT_KYC_TARGETS: + XPREPARE ("select_serial_by_table_kyc_targets", + "SELECT" + " kyc_target_serial_id AS serial" + " FROM kyc_targets" + " ORDER BY kyc_target_serial_id DESC" + " LIMIT 1;"); + break; case TALER_EXCHANGEDB_RT_RESERVES: XPREPARE ("select_serial_by_table_reserves", "SELECT" diff --git a/src/exchangedb/pg_lookup_transfer_by_deposit.c b/src/exchangedb/pg_lookup_transfer_by_deposit.c @@ -83,13 +83,16 @@ TEH_PG_lookup_transfer_by_deposit ( ",cdep.amount_with_fee" ",bdep.wire_salt" ",wt.payto_uri" - ",wt.target_pub" + ",kt.target_pub" ",denom.fee_deposit" " FROM coin_deposits cdep" " JOIN batch_deposits bdep" " USING (batch_deposit_serial_id)" " JOIN wire_targets wt" " USING (wire_target_h_payto)" + /* kyc_targets might not match; then target_pub will be NULL */ + " LEFT JOIN kyc_targets kt" + " USING (h_normalized_payto)" " JOIN aggregation_tracking atr" " ON (cdep.batch_deposit_serial_id = atr.batch_deposit_serial_id)" " JOIN known_coins kc" @@ -170,12 +173,15 @@ TEH_PG_lookup_transfer_by_deposit ( ",denom.fee_deposit" ",bdep.wire_deadline" ",agt.legitimization_requirement_serial_id" - ",wt.target_pub" + ",kt.target_pub" " FROM coin_deposits cdep" " JOIN batch_deposits bdep" " USING (batch_deposit_serial_id)" " JOIN wire_targets wt" " USING (wire_target_h_payto)" + /* kyc_targets might not match; then target_pub will be NULL */ + " LEFT JOIN kyc_targets kt" + " USING (h_normalized_payto)" " JOIN known_coins kc" " ON (kc.coin_pub = cdep.coin_pub)" " JOIN denominations denom" diff --git a/src/exchangedb/pg_lookup_wire_transfer.c b/src/exchangedb/pg_lookup_wire_transfer.c @@ -156,7 +156,7 @@ TEH_PG_lookup_wire_transfer ( " aggregation_serial_id" ",bdep.h_contract_terms" ",payto_uri" - ",wire_targets.wire_target_h_payto" + ",wt.wire_target_h_payto" ",kc.coin_pub" ",bdep.merchant_pub" ",wire_out.execution_date" @@ -168,7 +168,7 @@ TEH_PG_lookup_wire_transfer ( " USING (batch_deposit_serial_id)" " JOIN coin_deposits cdep" " USING (batch_deposit_serial_id)" - " JOIN wire_targets" + " JOIN wire_targets wt" " USING (wire_target_h_payto)" " JOIN known_coins kc" " USING (coin_pub)" diff --git a/src/exchangedb/pg_reserves_get_origin.c b/src/exchangedb/pg_reserves_get_origin.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022, 2024 Taler Systems SA + Copyright (C) 2022, 2024, 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 @@ -51,12 +51,12 @@ TEH_PG_reserves_get_origin ( PREPARE (pg, "get_h_wire_source_of_reserve", "SELECT" - " wire_source_h_payto" - ",payto_uri" + " rt.wire_source_h_payto" + ",wt.payto_uri" " FROM reserves_in rt" " JOIN wire_targets wt" " ON (rt.wire_source_h_payto = wt.wire_target_h_payto)" - " WHERE reserve_pub=$1"); + " WHERE rt.reserve_pub=$1"); return GNUNET_PQ_eval_prepared_singleton_select ( pg->conn, "get_h_wire_source_of_reserve", diff --git a/src/exchangedb/pg_select_aml_decisions.c b/src/exchangedb/pg_select_aml_decisions.c @@ -77,7 +77,7 @@ handle_aml_result (void *cls, struct GNUNET_TIME_Timestamp decision_time; struct GNUNET_TIME_Absolute expiration_time; json_t *jproperties = NULL; - char *payto; + bool is_wallet; bool to_investigate; bool is_active; json_t *account_rules; @@ -86,8 +86,8 @@ handle_aml_result (void *cls, &rowid), GNUNET_PQ_result_spec_auto_from_type ("h_payto", &h_payto), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto), + GNUNET_PQ_result_spec_bool ("is_wallet", + &is_wallet), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_string ("justification", &justification), @@ -120,10 +120,10 @@ handle_aml_result (void *cls, } if (GNUNET_TIME_absolute_is_past (expiration_time)) is_active = false; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning AML decisions for `%s' (%s)\n", - payto, - TALER_payto_is_wallet (payto) + TALER_B2S (&h_payto), + is_wallet ? "wallet" : "account"); ctx->cb (ctx->cb_cls, @@ -135,7 +135,7 @@ handle_aml_result (void *cls, jproperties, to_investigate, is_active, - TALER_payto_is_wallet (payto), + is_wallet, account_rules); GNUNET_PQ_cleanup_result (rs); } @@ -195,10 +195,10 @@ TEH_PG_select_aml_decisions ( ",lo.to_investigate" ",lo.is_active" ",lo.jnew_rules" - ",wt.payto_uri" + ",kt.is_wallet" " FROM legitimization_outcomes lo" - " JOIN wire_targets wt" - " ON (lo.h_payto = wt.h_normalized_payto)" + " JOIN kyc_targets kt" + " ON (lo.h_payto = kt.h_normalized_payto)" " LEFT JOIN aml_history ah" " USING (outcome_serial_id)" " WHERE (outcome_serial_id > $7)" @@ -219,10 +219,10 @@ TEH_PG_select_aml_decisions ( ",lo.to_investigate" ",lo.is_active" ",lo.jnew_rules" - ",wt.payto_uri" + ",kt.is_wallet" " FROM legitimization_outcomes lo" - " JOIN wire_targets wt" - " ON (lo.h_payto = wt.h_normalized_payto)" + " JOIN kyc_targets kt" + " ON (lo.h_payto = kt.h_normalized_payto)" " LEFT JOIN aml_history ah" " USING (outcome_serial_id)" " WHERE lo.outcome_serial_id < $7" diff --git a/src/exchangedb/pg_select_aml_measures.c b/src/exchangedb/pg_select_aml_measures.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2024 Taler Systems SA + Copyright (C) 2024, 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 @@ -150,15 +150,15 @@ TEH_PG_select_aml_measures ( "select_aml_measures_inc", "SELECT" " lm.legitimization_measure_serial_id" - ",wt.h_normalized_payto" + ",kt.h_normalized_payto" ",lm.jmeasures" ",lm.start_time" ",lm.is_finished" - " FROM wire_targets wt" + " FROM kyc_targets kt" " JOIN legitimization_measures lm" " USING (access_token)" " WHERE (legitimization_measure_serial_id > $5)" - " AND ($1 OR (wt.h_normalized_payto = $2))" + " AND ($1 OR (kt.h_normalized_payto = $2))" " AND ($3 OR (lm.is_finished = $4))" " ORDER BY lm.legitimization_measure_serial_id ASC" " LIMIT $6"); @@ -166,15 +166,15 @@ TEH_PG_select_aml_measures ( "select_aml_measures_dec", "SELECT" " lm.legitimization_measure_serial_id" - ",wt.h_normalized_payto" + ",kt.h_normalized_payto" ",lm.jmeasures" ",lm.start_time" ",lm.is_finished" - " FROM wire_targets wt" + " FROM kyc_targets kt" " JOIN legitimization_measures lm" " USING (access_token)" " WHERE (legitimization_measure_serial_id < $5)" - " AND ($1 OR (wt.h_normalized_payto = $2))" + " AND ($1 OR (kt.h_normalized_payto = $2))" " AND ($3 OR (lm.is_finished = $4))" " ORDER BY lm.legitimization_measure_serial_id DESC" " LIMIT $6"); diff --git a/src/exchangedb/pg_select_reserve_close_info.c b/src/exchangedb/pg_select_reserve_close_info.c @@ -57,7 +57,7 @@ TEH_PG_select_reserve_close_info ( " USING (reserve_pub)" " LEFT JOIN wire_targets wt" " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)" - " WHERE reserve_pub=$1;"); + " WHERE r.reserve_pub=$1;"); return GNUNET_PQ_eval_prepared_singleton_select ( pg->conn, "select_reserve_close_info", diff --git a/src/exchangedb/pg_select_reserve_closed_above_serial_id.c b/src/exchangedb/pg_select_reserve_closed_above_serial_id.c @@ -154,22 +154,23 @@ TEH_PG_select_reserve_closed_above_serial_id ( ",reserves.reserve_pub" ",execution_date" ",wtid" - ",payto_uri AS receiver_account" + ",wt.payto_uri AS receiver_account" ",amount" ",closing_fee" ",close_request_row" " FROM reserves_close" - " JOIN wire_targets" - " USING (wire_target_h_payto)" - " JOIN reserves" - " USING (reserve_pub)" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " JOIN reserves" + " USING (reserve_pub)" " WHERE close_uuid>=$1" " ORDER BY close_uuid ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "reserves_close_get_incr", - params, - &reserve_closed_serial_helper_cb, - &rcsc); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "reserves_close_get_incr", + params, + &reserve_closed_serial_helper_cb, + &rcsc); if (GNUNET_OK != rcsc.status) return GNUNET_DB_STATUS_HARD_ERROR; return qs; diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id.c b/src/exchangedb/pg_select_reserves_in_above_serial_id.c @@ -138,26 +138,27 @@ TEH_PG_select_reserves_in_above_serial_id ( enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "audit_reserves_in_get_transactions_incr", + "select_reserves_in_above_serial_id", "SELECT" " reserves.reserve_pub" ",wire_reference" ",credit" ",execution_date" - ",payto_uri AS sender_account_details" + ",wt.payto_uri AS sender_account_details" ",reserve_in_serial_id" " FROM reserves_in" " JOIN reserves" " USING (reserve_pub)" - " JOIN wire_targets" + " JOIN wire_targets wt" " ON (wire_source_h_payto = wire_target_h_payto)" " WHERE reserve_in_serial_id>=$1" " ORDER BY reserve_in_serial_id;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_reserves_in_get_transactions_incr", - params, - &reserves_in_serial_helper_cb, - &risc); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_reserves_in_above_serial_id", + params, + &reserves_in_serial_helper_cb, + &risc); if (GNUNET_DB_STATUS_SOFT_ERROR == qs) return qs; if (GNUNET_OK != risc.status) diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c b/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c @@ -141,25 +141,25 @@ TEH_PG_select_reserves_in_above_serial_id_by_account ( enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "audit_reserves_in_get_transactions_incr_by_account", + "select_reserves_in_above_serial_id_by_account", "SELECT" " reserves.reserve_pub" ",wire_reference" ",credit" ",execution_date" - ",payto_uri AS sender_account_details" + ",wt.payto_uri AS sender_account_details" ",reserve_in_serial_id" " FROM reserves_in" " JOIN reserves " " USING (reserve_pub)" - " JOIN wire_targets" + " JOIN wire_targets wt" " ON (wire_source_h_payto = wire_target_h_payto)" " WHERE reserve_in_serial_id>=$1" " AND exchange_account_section=$2" " ORDER BY reserve_in_serial_id ASC;"); qs = GNUNET_PQ_eval_prepared_multi_select ( pg->conn, - "audit_reserves_in_get_transactions_incr_by_account", + "select_reserves_in_above_serial_id_by_account", params, &reserves_in_serial_helper_cb, &risc); diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id.c b/src/exchangedb/pg_select_wire_out_above_serial_id.c @@ -134,23 +134,24 @@ TEH_PG_select_wire_out_above_serial_id ( enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "audit_get_wire_incr", + "select_wire_out_above_serial_id", "SELECT" - " wireout_uuid" - ",execution_date" - ",wtid_raw" - ",payto_uri" - ",amount" - " FROM wire_out" - " JOIN wire_targets" + " wo.wireout_uuid" + ",wo.execution_date" + ",wo.wtid_raw" + ",wt.payto_uri" + ",wo.amount" + " FROM wire_out wo" + " JOIN wire_targets wt" " USING (wire_target_h_payto)" " WHERE wireout_uuid>=$1" " ORDER BY wireout_uuid ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_get_wire_incr", - params, - &wire_out_serial_helper_cb, - &wosc); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_wire_out_above_serial_id", + params, + &wire_out_serial_helper_cb, + &wosc); if (GNUNET_OK != wosc.status) return GNUNET_DB_STATUS_HARD_ERROR; return qs; diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c @@ -136,25 +136,25 @@ TEH_PG_select_wire_out_above_serial_id_by_account ( enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "audit_get_wire_incr_by_account", + "select_wire_out_above_serial_id_by_account", "SELECT" - " wireout_uuid" - ",execution_date" - ",wtid_raw" - ",payto_uri" - ",amount" - " FROM wire_out" - " JOIN wire_targets" - " USING (wire_target_h_payto)" - " WHERE " - " wireout_uuid>=$1 " - " AND exchange_account_section=$2" - " ORDER BY wireout_uuid ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_get_wire_incr_by_account", - params, - &wire_out_serial_helper_cb, - &wosc); + " wo.wireout_uuid" + ",wo.execution_date" + ",wo.wtid_raw" + ",wt.payto_uri" + ",wo.amount" + " FROM wire_out wo" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " WHERE wo.wireout_uuid>=$1 " + " AND wo.exchange_account_section=$2" + " ORDER BY wo.wireout_uuid ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_wire_out_above_serial_id_by_account", + params, + &wire_out_serial_helper_cb, + &wosc); if (GNUNET_OK != wosc.status) return GNUNET_DB_STATUS_HARD_ERROR; return qs; diff --git a/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.c b/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.c @@ -133,7 +133,7 @@ TEH_PG_select_withdraw_amounts_for_kyc_check ( enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "select_kyc_relevant_withdraw_events", + "select_withdraw_amounts_for_kyc_check", "SELECT" " wd.amount_with_fee AS amount" ",wd.execution_date AS date" @@ -152,7 +152,7 @@ TEH_PG_select_withdraw_amounts_for_kyc_check ( " ORDER BY rh.reserve_history_serial_id DESC"); qs = GNUNET_PQ_eval_prepared_multi_select ( pg->conn, - "select_kyc_relevant_withdraw_events", + "select_withdraw_amounts_for_kyc_check", params, &get_kyc_amounts_cb, &ctx); diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h @@ -279,10 +279,10 @@ struct TALER_EXCHANGEDB_SignkeyMetaData */ enum TALER_EXCHANGEDB_ReplicatedTable { - /* From exchange-0002.sql: */ TALER_EXCHANGEDB_RT_DENOMINATIONS, TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS, TALER_EXCHANGEDB_RT_WIRE_TARGETS, + TALER_EXCHANGEDB_RT_KYC_TARGETS, TALER_EXCHANGEDB_RT_RESERVES, TALER_EXCHANGEDB_RT_RESERVES_IN, TALER_EXCHANGEDB_RT_RESERVES_CLOSE, @@ -328,7 +328,7 @@ enum TALER_EXCHANGEDB_ReplicatedTable TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES, TALER_EXCHANGEDB_RT_AML_HISTORY, TALER_EXCHANGEDB_RT_KYC_EVENTS, - TALER_EXCHANGEDB_RT_KYCAUTHS_IN, + TALER_EXCHANGEDB_RT_KYCAUTHS_IN }; @@ -379,10 +379,16 @@ struct TALER_EXCHANGEDB_TableData struct { struct TALER_FullPayto full_payto_uri; + } wire_targets; + + struct + { + struct TALER_NormalizedPaytoHashP h_normalized_payto; struct TALER_AccountAccessTokenP access_token; union TALER_AccountPublicKeyP target_pub; bool no_account; - } wire_targets; + bool is_wallet; + } kyc_targets; struct {