From 5dfa56727e8516f666bc2cba0ef707b7bc15a2d5 Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 27 Mar 2023 09:51:09 -0400 Subject: [PATCH 01/50] New spi files --- contrib/gana | 2 +- src/exchangedb/pg_reserves_in_insert.c | 67 ++++++++------------------ src/exchangedb/procedures.sql.in | 5 +- 3 files changed, 23 insertions(+), 51 deletions(-) diff --git a/contrib/gana b/contrib/gana index 59de2acb7..3a616a04f 160000 --- a/contrib/gana +++ b/contrib/gana @@ -1 +1 @@ -Subproject commit 59de2acb7c716c816ed15786b5369e56c325770c +Subproject commit 3a616a04f1cd946bf0641b54cd71f1b858174f74 diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c index 1c578478b..7221e3908 100644 --- a/src/exchangedb/pg_reserves_in_insert.c +++ b/src/exchangedb/pg_reserves_in_insert.c @@ -58,7 +58,6 @@ compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub) static enum GNUNET_DB_QueryStatus insert1 (struct PostgresClosure *pg, const struct TALER_EXCHANGEDB_ReserveInInfo reserves[1], - struct GNUNET_TIME_Timestamp expiry, struct GNUNET_TIME_Timestamp gc, struct TALER_PaytoHashP h_payto, char *const *notify_s, @@ -76,19 +75,18 @@ insert1 (struct PostgresClosure *pg, ",transaction_duplicate" ",ruuid AS reserve_uuid" " FROM exchange_do_batch_reserves_in_insert" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);"); + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);"); struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), - GNUNET_PQ_query_param_timestamp (&expiry), GNUNET_PQ_query_param_timestamp (&gc), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), TALER_PQ_query_param_amount (reserves[0].balance), GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_string (notify_s[0]), GNUNET_PQ_query_param_end }; @@ -132,7 +130,6 @@ insert1 (struct PostgresClosure *pg, static enum GNUNET_DB_QueryStatus insert2 (struct PostgresClosure *pg, const struct TALER_EXCHANGEDB_ReserveInInfo reserves[2], - struct GNUNET_TIME_Timestamp expiry, struct GNUNET_TIME_Timestamp gc, struct TALER_PaytoHashP h_payto, char *const*notify_s, @@ -153,20 +150,19 @@ insert2 (struct PostgresClosure *pg, ",ruuid AS reserve_uuid" ",ruuid2 AS reserve_uuid2" " FROM exchange_do_batch2_reserves_insert" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22);"); + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20);"); struct GNUNET_PQ_QueryParam params[] = { - - GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), - GNUNET_PQ_query_param_timestamp (&expiry), GNUNET_PQ_query_param_timestamp (&gc), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), TALER_PQ_query_param_amount (reserves[0].balance), GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_string (notify_s[0]), GNUNET_PQ_query_param_string (notify_s[1]), @@ -177,7 +173,6 @@ insert2 (struct PostgresClosure *pg, GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[1].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { @@ -238,7 +233,6 @@ insert2 (struct PostgresClosure *pg, static enum GNUNET_DB_QueryStatus insert4 (struct PostgresClosure *pg, const struct TALER_EXCHANGEDB_ReserveInInfo reserves[4], - struct GNUNET_TIME_Timestamp expiry, struct GNUNET_TIME_Timestamp gc, struct TALER_PaytoHashP h_payto, char *const*notify_s, @@ -265,19 +259,19 @@ insert4 (struct PostgresClosure *pg, ",ruuid3 AS reserve_uuid3" ",ruuid4 AS reserve_uuid4" " FROM exchange_do_batch4_reserves_insert" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39, $40, $41,$42);"); + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38);"); struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), - GNUNET_PQ_query_param_timestamp (&expiry), GNUNET_PQ_query_param_timestamp (&gc), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), TALER_PQ_query_param_amount (reserves[0].balance), GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_string (notify_s[0]), GNUNET_PQ_query_param_string (notify_s[1]), GNUNET_PQ_query_param_string (notify_s[2]), @@ -290,7 +284,6 @@ insert4 (struct PostgresClosure *pg, GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[1].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference), @@ -299,7 +292,6 @@ insert4 (struct PostgresClosure *pg, GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[2].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference), @@ -308,7 +300,6 @@ insert4 (struct PostgresClosure *pg, GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[3].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_end }; @@ -385,7 +376,6 @@ insert4 (struct PostgresClosure *pg, static enum GNUNET_DB_QueryStatus insert8 (struct PostgresClosure *pg, const struct TALER_EXCHANGEDB_ReserveInInfo reserves[8], - struct GNUNET_TIME_Timestamp expiry, struct GNUNET_TIME_Timestamp gc, struct TALER_PaytoHashP h_payto, char *const*notify_s, @@ -398,8 +388,8 @@ insert8 (struct PostgresClosure *pg, enum GNUNET_DB_QueryStatus qs3; PREPARE (pg, "batch8_reserve_create", - "SELECT " - "out_reserve_found AS conflicted" + "SELECT" + " out_reserve_found AS conflicted" ",out_reserve_found2 AS conflicted2" ",out_reserve_found3 AS conflicted3" ",out_reserve_found4 AS conflicted4" @@ -424,19 +414,18 @@ insert8 (struct PostgresClosure *pg, ",ruuid7 AS reserve_uuid7" ",ruuid8 AS reserve_uuid8" " FROM exchange_do_batch8_reserves_insert" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39, $40, $41,$42,$43,$44,$45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$80,$81,$82);"); + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39, $40, $41,$42,$43,$44,$45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$70,$71,$72,$73,$74);"); struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), - GNUNET_PQ_query_param_timestamp (&expiry), GNUNET_PQ_query_param_timestamp (&gc), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), TALER_PQ_query_param_amount (reserves[0].balance), GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_string (notify_s[0]), GNUNET_PQ_query_param_string (notify_s[1]), GNUNET_PQ_query_param_string (notify_s[2]), @@ -453,7 +442,6 @@ insert8 (struct PostgresClosure *pg, GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[1].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference), @@ -462,7 +450,6 @@ insert8 (struct PostgresClosure *pg, GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[2].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference), @@ -471,7 +458,6 @@ insert8 (struct PostgresClosure *pg, GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[3].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_auto_from_type (reserves[4].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[4].wire_reference), @@ -489,7 +475,6 @@ insert8 (struct PostgresClosure *pg, GNUNET_PQ_query_param_timestamp (&reserves[5].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[5].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_auto_from_type (reserves[6].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[6].wire_reference), @@ -498,7 +483,6 @@ insert8 (struct PostgresClosure *pg, GNUNET_PQ_query_param_timestamp (&reserves[6].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[6].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_auto_from_type (reserves[7].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[7].wire_reference), @@ -507,7 +491,6 @@ insert8 (struct PostgresClosure *pg, GNUNET_PQ_query_param_timestamp (&reserves[7].execution_time), GNUNET_PQ_query_param_auto_from_type (&h_payto), GNUNET_PQ_query_param_string (reserves[7].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_end }; @@ -633,8 +616,6 @@ TEH_PG_reserves_in_insert (void *cls, enum GNUNET_DB_QueryStatus qs2; enum GNUNET_DB_QueryStatus qs4; enum GNUNET_DB_QueryStatus qs5; - struct GNUNET_TIME_Timestamp expiry; - struct GNUNET_TIME_Timestamp gc; struct TALER_PaytoHashP h_payto; uint64_t reserve_uuid[reserves_length]; bool transaction_duplicate[reserves_length]; @@ -642,6 +623,8 @@ TEH_PG_reserves_in_insert (void *cls, bool t_duplicate = false; 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 conflicts[reserves_length]; char *notify_s[reserves_length]; @@ -652,12 +635,6 @@ TEH_PG_reserves_in_insert (void *cls, return GNUNET_DB_STATUS_HARD_ERROR; } - expiry = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_add (reserves->execution_time.abs_time, - pg->idle_reserve_expiration_time)); - gc = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), - pg->legal_reserve_expiration_time)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating reserve %s with expiration in %s\n", TALER_B2S (&(reserves->reserve_pub)), @@ -694,7 +671,6 @@ TEH_PG_reserves_in_insert (void *cls, { qs1 = insert8 (pg, &reserves[i], - expiry, gc, h_payto, ¬ify_s[i], @@ -738,7 +714,6 @@ TEH_PG_reserves_in_insert (void *cls, case 4: qs4 = insert4 (pg, &reserves[i], - expiry, gc, h_payto, ¬ify_s[i], @@ -769,7 +744,6 @@ TEH_PG_reserves_in_insert (void *cls, case 2: qs5 = insert2 (pg, &reserves[i], - expiry, gc, h_payto, ¬ify_s[i], @@ -797,7 +771,6 @@ TEH_PG_reserves_in_insert (void *cls, case 1: qs2 = insert1 (pg, &reserves[i], - expiry, gc, h_payto, ¬ify_s[i], @@ -806,6 +779,7 @@ TEH_PG_reserves_in_insert (void *cls, &conflicts[i], &reserve_uuid[i], &results[i]); + fprintf(stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], conflicts[i], transaction_duplicate[i]); if (qs2<0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -815,6 +789,7 @@ TEH_PG_reserves_in_insert (void *cls, } need_update |= conflicts[i]; t_duplicate |= transaction_duplicate[i]; + i += 1; break; case 0: @@ -864,7 +839,7 @@ TEH_PG_reserves_in_insert (void *cls, bool duplicate; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub), - GNUNET_PQ_query_param_timestamp (&expiry), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference), TALER_PQ_query_param_amount (reserves[i].balance), GNUNET_PQ_query_param_string (reserves[i].exchange_account_name), diff --git a/src/exchangedb/procedures.sql.in b/src/exchangedb/procedures.sql.in index a53396c36..27a5b3bb3 100644 --- a/src/exchangedb/procedures.sql.in +++ b/src/exchangedb/procedures.sql.in @@ -39,11 +39,8 @@ 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_batch_reserves_in_insert.sql" +#include "exchange_do_reserves_in_insert.sql" #include "exchange_do_batch_reserves_update.sql" -#include "exchange_do_batch2_reserves_in_insert.sql" -#include "exchange_do_batch4_reserves_in_insert.sql" -#include "exchange_do_batch8_reserves_in_insert.sql" #include "exchange_do_refund_by_coin.sql" #include "exchange_do_get_ready_deposit.sql" #include "exchange_do_get_link_data.sql" From 39f2d441f738f0e37d49673533040eac9a936dc9 Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 27 Mar 2023 09:53:51 -0400 Subject: [PATCH 02/50] Spi files --- .../exchange_do_batch2_reserves_in_insert.sql | 186 --- .../exchange_do_batch4_reserves_in_insert.sql | 287 ----- .../exchange_do_batch8_reserves_in_insert.sql | 509 -------- .../exchange_do_batch_reserves_in_insert.sql | 120 -- .../exchange_do_reserves_in_insert.sql | 1065 +++++++++++++++++ 5 files changed, 1065 insertions(+), 1102 deletions(-) delete mode 100644 src/exchangedb/exchange_do_batch2_reserves_in_insert.sql delete mode 100644 src/exchangedb/exchange_do_batch4_reserves_in_insert.sql delete mode 100644 src/exchangedb/exchange_do_batch8_reserves_in_insert.sql delete mode 100644 src/exchangedb/exchange_do_batch_reserves_in_insert.sql create mode 100644 src/exchangedb/exchange_do_reserves_in_insert.sql diff --git a/src/exchangedb/exchange_do_batch2_reserves_in_insert.sql b/src/exchangedb/exchange_do_batch2_reserves_in_insert.sql deleted file mode 100644 index 6df8b7554..000000000 --- a/src/exchangedb/exchange_do_batch2_reserves_in_insert.sql +++ /dev/null @@ -1,186 +0,0 @@ --- --- This file is part of TALER --- Copyright (C) 2014--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 --- - -DROP FUNCTION IF EXISTS exchange_do_batch2_reserves_insert; -CREATE OR REPLACE FUNCTION exchange_do_batch2_reserves_insert( - IN in_reserve_pub BYTEA, - IN in_expiration_date INT8, - IN in_gc_date INT8, - IN in_wire_ref INT8, - IN in_credit_val INT8, - IN in_credit_frac INT4, - IN in_exchange_account_name VARCHAR, - IN in_execution_date INT8, - IN in_wire_source_h_payto BYTEA, ---h_payto - IN in_payto_uri VARCHAR, - IN in_reserve_expiration INT8, - IN in_notify text, - IN in2_notify text, - IN in2_reserve_pub BYTEA, - IN in2_wire_ref INT8, - IN in2_credit_val INT8, - IN in2_credit_frac INT4, - IN in2_exchange_account_name VARCHAR, - IN in2_execution_date INT8, - IN in2_wire_source_h_payto BYTEA, ---h_payto - IN in2_payto_uri VARCHAR, - IN in2_reserve_expiration INT8, - OUT out_reserve_found BOOLEAN, - OUT out_reserve_found2 BOOLEAN, - OUT transaction_duplicate BOOLEAN, - OUT transaction_duplicate2 BOOLEAN, - OUT ruuid INT8, - OUT ruuid2 INT8) -LANGUAGE plpgsql -AS $$ -DECLARE - curs_reserve_exist REFCURSOR; -DECLARE - curs_transaction_exist refcursor; -DECLARE - i RECORD; -DECLARE - r RECORD; -DECLARE - k INT8; -BEGIN - transaction_duplicate=TRUE; - transaction_duplicate2=TRUE; - out_reserve_found = TRUE; - out_reserve_found2 = TRUE; - ruuid=0; - ruuid2=0; - k=0; - INSERT INTO wire_targets - (wire_target_h_payto - ,payto_uri) - VALUES - (in_wire_source_h_payto - ,in_payto_uri), - (in2_wire_source_h_payto - ,in2_payto_uri) - ON CONFLICT DO NOTHING; - - OPEN curs_reserve_exist FOR - WITH reserve_changes AS ( - INSERT INTO reserves - (reserve_pub - ,current_balance_val - ,current_balance_frac - ,expiration_date - ,gc_date) - VALUES - (in_reserve_pub - ,in_credit_val - ,in_credit_frac - ,in_expiration_date - ,in_gc_date), - (in2_reserve_pub - ,in2_credit_val - ,in2_credit_frac - ,in_expiration_date - ,in_gc_date) - ON CONFLICT DO NOTHING - RETURNING reserve_uuid,reserve_pub) - SELECT * FROM reserve_changes; - WHILE k < 2 LOOP - FETCH FROM curs_reserve_exist INTO i; - IF FOUND - THEN - IF in_reserve_pub = i.reserve_pub - THEN - ruuid = i.reserve_uuid; - IF in_reserve_pub <> in2_reserve_pub - THEN - out_reserve_found = FALSE; - END IF; - END IF; - IF in2_reserve_pub = i.reserve_pub - THEN - out_reserve_found2 = FALSE; - ruuid2 = i.reserve_uuid; - END IF; - END IF; - k=k+1; - END LOOP; - CLOSE curs_reserve_exist; - --- FIXME: must be changed to EXECUTE FORMAT! - PERFORM pg_notify(in_notify, NULL); - PERFORM pg_notify(in2_notify, NULL); - - OPEN curs_transaction_exist FOR - WITH reserve_in_exist AS ( - INSERT INTO reserves_in - (reserve_pub - ,wire_reference - ,credit_val - ,credit_frac - ,exchange_account_section - ,wire_source_h_payto - ,execution_date) - VALUES - (in_reserve_pub - ,in_wire_ref - ,in_credit_val - ,in_credit_frac - ,in_exchange_account_name - ,in_wire_source_h_payto - ,in_execution_date), - (in2_reserve_pub - ,in2_wire_ref - ,in2_credit_val - ,in2_credit_frac - ,in2_exchange_account_name - ,in2_wire_source_h_payto - ,in_execution_date) - ON CONFLICT DO NOTHING - RETURNING reserve_pub) - SELECT * FROM reserve_in_exist; - FETCH FROM curs_transaction_exist INTO r; - IF FOUND - THEN - IF in_reserve_pub = r.reserve_pub - THEN - transaction_duplicate = FALSE; - END IF; - IF in2_reserve_pub = r.reserve_pub - THEN - transaction_duplicate2 = FALSE; - END IF; - FETCH FROM curs_transaction_exist INTO r; - IF FOUND - THEN - IF in_reserve_pub = r.reserve_pub - THEN - transaction_duplicate = FALSE; - END IF; - IF in2_reserve_pub = r.reserve_pub - THEN - transaction_duplicate2 = FALSE; - END IF; - END IF; - END IF; -/* IF transaction_duplicate - OR transaction_duplicate2 - THEN - CLOSE curs_transaction_exist; - ROLLBACK; - RETURN; - END IF;*/ - CLOSE curs_transaction_exist; - RETURN; -END $$; diff --git a/src/exchangedb/exchange_do_batch4_reserves_in_insert.sql b/src/exchangedb/exchange_do_batch4_reserves_in_insert.sql deleted file mode 100644 index 6a5707109..000000000 --- a/src/exchangedb/exchange_do_batch4_reserves_in_insert.sql +++ /dev/null @@ -1,287 +0,0 @@ --- --- This file is part of TALER --- Copyright (C) 2014--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 --- - -DROP FUNCTION IF EXISTS exchange_do_batch4_reserves_insert; -CREATE OR REPLACE FUNCTION exchange_do_batch4_reserves_insert( - IN in_reserve_pub BYTEA, - IN in_expiration_date INT8, - IN in_gc_date INT8, - IN in_wire_ref INT8, - IN in_credit_val INT8, - IN in_credit_frac INT4, - IN in_exchange_account_name VARCHAR, - IN in_execution_date INT8, - IN in_wire_source_h_payto BYTEA, ---h_payto - IN in_payto_uri VARCHAR, - IN in_reserve_expiration INT8, - IN in_notify text, - IN in2_notify text, - IN in3_notify text, - IN in4_notify text, - IN in2_reserve_pub BYTEA, - IN in2_wire_ref INT8, - IN in2_credit_val INT8, - IN in2_credit_frac INT4, - IN in2_exchange_account_name VARCHAR, - IN in2_execution_date INT8, - IN in2_wire_source_h_payto BYTEA, ---h_payto - IN in2_payto_uri VARCHAR, - IN in2_reserve_expiration INT8, - IN in3_reserve_pub BYTEA, - IN in3_wire_ref INT8, - IN in3_credit_val INT8, - IN in3_credit_frac INT4, - IN in3_exchange_account_name VARCHAR, - IN in3_execution_date INT8, - IN in3_wire_source_h_payto BYTEA, ---h_payto - IN in3_payto_uri VARCHAR, - IN in3_reserve_expiration INT8, - IN in4_reserve_pub BYTEA, - IN in4_wire_ref INT8, - IN in4_credit_val INT8, - IN in4_credit_frac INT4, - IN in4_exchange_account_name VARCHAR, - IN in4_execution_date INT8, - IN in4_wire_source_h_payto BYTEA, ---h_payto - IN in4_payto_uri VARCHAR, - IN in4_reserve_expiration INT8, - OUT out_reserve_found BOOLEAN, - OUT out_reserve_found2 BOOLEAN, - OUT out_reserve_found3 BOOLEAN, - OUT out_reserve_found4 BOOLEAN, - OUT transaction_duplicate BOOLEAN, - OUT transaction_duplicate2 BOOLEAN, - OUT transaction_duplicate3 BOOLEAN, - OUT transaction_duplicate4 BOOLEAN, - OUT ruuid INT8, - OUT ruuid2 INT8, - OUT ruuid3 INT8, - OUT ruuid4 INT8) -LANGUAGE plpgsql -AS $$ -DECLARE - curs_reserve_exist refcursor; -DECLARE - k INT8; -DECLARE - curs_transaction_exist refcursor; -DECLARE - i RECORD; - -BEGIN ---INITIALIZATION - transaction_duplicate=TRUE; - transaction_duplicate2=TRUE; - transaction_duplicate3=TRUE; - transaction_duplicate4=TRUE; - out_reserve_found = TRUE; - out_reserve_found2 = TRUE; - out_reserve_found3 = TRUE; - out_reserve_found4 = TRUE; - ruuid=0; - ruuid2=0; - ruuid3=0; - ruuid4=0; - k=0; - --SIMPLE INSERT ON CONFLICT DO NOTHING - INSERT INTO wire_targets - (wire_target_h_payto - ,payto_uri) - VALUES - (in_wire_source_h_payto - ,in_payto_uri), - (in2_wire_source_h_payto - ,in2_payto_uri), - (in3_wire_source_h_payto - ,in3_payto_uri), - (in4_wire_source_h_payto - ,in4_payto_uri) - ON CONFLICT DO NOTHING; - - OPEN curs_reserve_exist FOR - WITH reserve_changes AS ( - INSERT INTO reserves - (reserve_pub - ,current_balance_val - ,current_balance_frac - ,expiration_date - ,gc_date) - VALUES - (in_reserve_pub - ,in_credit_val - ,in_credit_frac - ,in_expiration_date - ,in_gc_date), - (in2_reserve_pub - ,in2_credit_val - ,in2_credit_frac - ,in_expiration_date - ,in_gc_date), - (in3_reserve_pub - ,in3_credit_val - ,in3_credit_frac - ,in_expiration_date - ,in_gc_date), - (in4_reserve_pub - ,in4_credit_val - ,in4_credit_frac - ,in_expiration_date - ,in_gc_date) - ON CONFLICT DO NOTHING - RETURNING reserve_uuid,reserve_pub) - SELECT * FROM reserve_changes; - - WHILE k < 4 LOOP - FETCH FROM curs_reserve_exist INTO i; - IF FOUND - THEN - IF in_reserve_pub = i.reserve_pub - THEN - ruuid = i.reserve_uuid; - IF in_reserve_pub - NOT IN (in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub) - THEN - out_reserve_found = FALSE; - END IF; - END IF; - IF in2_reserve_pub = i.reserve_pub - THEN - ruuid2 = i.reserve_uuid; - IF in2_reserve_pub - NOT IN (in_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub) - THEN - out_reserve_found2 = FALSE; - END IF; - END IF; - IF in3_reserve_pub = i.reserve_pub - THEN - ruuid3 = i.reserve_uuid; - IF in3_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in4_reserve_pub) - THEN - out_reserve_found3 = FALSE; - END IF; - END IF; - IF in4_reserve_pub = i.reserve_pub - THEN - ruuid4 = i.reserve_uuid; - IF in4_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub) - THEN - out_reserve_found4 = FALSE; - END IF; - END IF; - END IF; - k=k+1; - END LOOP; - CLOSE curs_reserve_exist; - - --- FIXME: must be changed to EXECUTE FORMAT! - PERFORM pg_notify(in_notify, NULL); - PERFORM pg_notify(in2_notify, NULL); - PERFORM pg_notify(in3_notify, NULL); - PERFORM pg_notify(in4_notify, NULL); - - k=0; - OPEN curs_transaction_exist FOR - WITH reserve_in_changes AS ( - INSERT INTO reserves_in - (reserve_pub - ,wire_reference - ,credit_val - ,credit_frac - ,exchange_account_section - ,wire_source_h_payto - ,execution_date) - VALUES - (in_reserve_pub - ,in_wire_ref - ,in_credit_val - ,in_credit_frac - ,in_exchange_account_name - ,in_wire_source_h_payto - ,in_execution_date), - (in2_reserve_pub - ,in2_wire_ref - ,in2_credit_val - ,in2_credit_frac - ,in2_exchange_account_name - ,in2_wire_source_h_payto - ,in_execution_date), - (in3_reserve_pub - ,in3_wire_ref - ,in3_credit_val - ,in3_credit_frac - ,in3_exchange_account_name - ,in3_wire_source_h_payto - ,in_execution_date), - (in4_reserve_pub - ,in4_wire_ref - ,in4_credit_val - ,in4_credit_frac - ,in4_exchange_account_name - ,in4_wire_source_h_payto - ,in_execution_date) - ON CONFLICT DO NOTHING - RETURNING reserve_pub) - SELECT * FROM reserve_in_changes; - WHILE k < 4 LOOP - FETCH FROM curs_transaction_exist INTO i; - IF FOUND - THEN - IF in_reserve_pub = i.reserve_pub - THEN - transaction_duplicate = FALSE; - END IF; - IF in2_reserve_pub = i.reserve_pub - THEN - transaction_duplicate2 = FALSE; - END IF; - IF in3_reserve_pub = i.reserve_pub - THEN - transaction_duplicate3 = FALSE; - END IF; - IF in4_reserve_pub = i.reserve_pub - THEN - transaction_duplicate4 = FALSE; - END IF; - END IF; - k=k+1; - END LOOP; - /**ROLLBACK TRANSACTION IN SORTED PROCEDURE IS IT PROSSIBLE ?**/ - /*IF transaction_duplicate - OR transaction_duplicate2 - OR transaction_duplicate3 - OR transaction_duplicate4 - THEN - RAISE EXCEPTION 'Reserve did not exist, but INSERT into reserves_in gave conflict'; - ROLLBACK; - CLOSE curs_transaction_exist; - RETURN; - END IF;*/ - CLOSE curs_transaction_exist; - RETURN; - -END $$; diff --git a/src/exchangedb/exchange_do_batch8_reserves_in_insert.sql b/src/exchangedb/exchange_do_batch8_reserves_in_insert.sql deleted file mode 100644 index a9f34b897..000000000 --- a/src/exchangedb/exchange_do_batch8_reserves_in_insert.sql +++ /dev/null @@ -1,509 +0,0 @@ --- --- This file is part of TALER --- Copyright (C) 2014--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 --- - -DROP FUNCTION IF EXISTS exchange_do_batch8_reserves_insert; -CREATE OR REPLACE FUNCTION exchange_do_batch8_reserves_insert( - IN in_reserve_pub BYTEA, - IN in_expiration_date INT8, - IN in_gc_date INT8, - IN in_wire_ref INT8, - IN in_credit_val INT8, - IN in_credit_frac INT4, - IN in_exchange_account_name VARCHAR, - IN in_execution_date INT8, - IN in_wire_source_h_payto BYTEA, ---h_payto - IN in_payto_uri VARCHAR, - IN in_reserve_expiration INT8, - IN in_notify text, - IN in2_notify text, - IN in3_notify text, - IN in4_notify text, - IN in5_notify text, - IN in6_notify text, - IN in7_notify text, - IN in8_notify text, - IN in2_reserve_pub BYTEA, - IN in2_wire_ref INT8, - IN in2_credit_val INT8, - IN in2_credit_frac INT4, - IN in2_exchange_account_name VARCHAR, - IN in2_execution_date INT8, - IN in2_wire_source_h_payto BYTEA, ---h_payto - IN in2_payto_uri VARCHAR, - IN in2_reserve_expiration INT8, - IN in3_reserve_pub BYTEA, - IN in3_wire_ref INT8, - IN in3_credit_val INT8, - IN in3_credit_frac INT4, - IN in3_exchange_account_name VARCHAR, - IN in3_execution_date INT8, - IN in3_wire_source_h_payto BYTEA, ---h_payto - IN in3_payto_uri VARCHAR, - IN in3_reserve_expiration INT8, - IN in4_reserve_pub BYTEA, - IN in4_wire_ref INT8, - IN in4_credit_val INT8, - IN in4_credit_frac INT4, - IN in4_exchange_account_name VARCHAR, - IN in4_execution_date INT8, - IN in4_wire_source_h_payto BYTEA, ---h_payto - IN in4_payto_uri VARCHAR, - IN in4_reserve_expiration INT8, - IN in5_reserve_pub BYTEA, - IN in5_wire_ref INT8, - IN in5_credit_val INT8, - IN in5_credit_frac INT4, - IN in5_exchange_account_name VARCHAR, - IN in5_execution_date INT8, - IN in5_wire_source_h_payto BYTEA, ---h_payto - IN in5_payto_uri VARCHAR, - IN in5_reserve_expiration INT8, - IN in6_reserve_pub BYTEA, - IN in6_wire_ref INT8, - IN in6_credit_val INT8, - IN in6_credit_frac INT4, - IN in6_exchange_account_name VARCHAR, - IN in6_execution_date INT8, - IN in6_wire_source_h_payto BYTEA, ---h_payto - IN in6_payto_uri VARCHAR, - IN in6_reserve_expiration INT8, - IN in7_reserve_pub BYTEA, - IN in7_wire_ref INT8, - IN in7_credit_val INT8, - IN in7_credit_frac INT4, - IN in7_exchange_account_name VARCHAR, - IN in7_execution_date INT8, - IN in7_wire_source_h_payto BYTEA, ---h_payto - IN in7_payto_uri VARCHAR, - IN in7_reserve_expiration INT8, - IN in8_reserve_pub BYTEA, - IN in8_wire_ref INT8, - IN in8_credit_val INT8, - IN in8_credit_frac INT4, - IN in8_exchange_account_name VARCHAR, - IN in8_execution_date INT8, - IN in8_wire_source_h_payto BYTEA, ---h_payto - IN in8_payto_uri VARCHAR, - IN in8_reserve_expiration INT8, - OUT out_reserve_found BOOLEAN, - OUT out_reserve_found2 BOOLEAN, - OUT out_reserve_found3 BOOLEAN, - OUT out_reserve_found4 BOOLEAN, - OUT out_reserve_found5 BOOLEAN, - OUT out_reserve_found6 BOOLEAN, - OUT out_reserve_found7 BOOLEAN, - OUT out_reserve_found8 BOOLEAN, - OUT transaction_duplicate BOOLEAN, - OUT transaction_duplicate2 BOOLEAN, - OUT transaction_duplicate3 BOOLEAN, - OUT transaction_duplicate4 BOOLEAN, - OUT transaction_duplicate5 BOOLEAN, - OUT transaction_duplicate6 BOOLEAN, - OUT transaction_duplicate7 BOOLEAN, - OUT transaction_duplicate8 BOOLEAN, - OUT ruuid INT8, - OUT ruuid2 INT8, - OUT ruuid3 INT8, - OUT ruuid4 INT8, - OUT ruuid5 INT8, - OUT ruuid6 INT8, - OUT ruuid7 INT8, - OUT ruuid8 INT8) -LANGUAGE plpgsql -AS $$ -DECLARE - curs_reserve_existed refcursor; -DECLARE - k INT8; -DECLARE - curs_transaction_existed refcursor; - -DECLARE - i RECORD; -DECLARE - r RECORD; - -BEGIN ---INITIALIZATION - transaction_duplicate=TRUE; - transaction_duplicate2=TRUE; - transaction_duplicate3=TRUE; - transaction_duplicate4=TRUE; - transaction_duplicate5=TRUE; - transaction_duplicate6=TRUE; - transaction_duplicate7=TRUE; - transaction_duplicate8=TRUE; - out_reserve_found = TRUE; - out_reserve_found2 = TRUE; - out_reserve_found3 = TRUE; - out_reserve_found4 = TRUE; - out_reserve_found5 = TRUE; - out_reserve_found6 = TRUE; - out_reserve_found7 = TRUE; - out_reserve_found8 = TRUE; - ruuid=0; - ruuid2=0; - ruuid3=0; - ruuid4=0; - ruuid5=0; - ruuid6=0; - ruuid7=0; - ruuid8=0; - k=0; - - --SIMPLE INSERT ON CONFLICT DO NOTHING - INSERT INTO wire_targets - (wire_target_h_payto - ,payto_uri) - VALUES - (in_wire_source_h_payto - ,in_payto_uri), - (in2_wire_source_h_payto - ,in2_payto_uri), - (in3_wire_source_h_payto - ,in3_payto_uri), - (in4_wire_source_h_payto - ,in4_payto_uri), - (in5_wire_source_h_payto - ,in5_payto_uri), - (in6_wire_source_h_payto - ,in6_payto_uri), - (in7_wire_source_h_payto - ,in7_payto_uri), - (in8_wire_source_h_payto - ,in8_payto_uri) - ON CONFLICT DO NOTHING; - - OPEN curs_reserve_existed FOR - WITH reserve_changes AS ( - INSERT INTO reserves - (reserve_pub - ,current_balance_val - ,current_balance_frac - ,expiration_date - ,gc_date) - VALUES - (in_reserve_pub - ,in_credit_val - ,in_credit_frac - ,in_expiration_date - ,in_gc_date), - (in2_reserve_pub - ,in2_credit_val - ,in2_credit_frac - ,in_expiration_date - ,in_gc_date), - (in3_reserve_pub - ,in3_credit_val - ,in3_credit_frac - ,in_expiration_date - ,in_gc_date), - (in4_reserve_pub - ,in4_credit_val - ,in4_credit_frac - ,in_expiration_date - ,in_gc_date), - (in5_reserve_pub - ,in5_credit_val - ,in5_credit_frac - ,in_expiration_date - ,in_gc_date), - (in6_reserve_pub - ,in6_credit_val - ,in6_credit_frac - ,in_expiration_date - ,in_gc_date), - (in7_reserve_pub - ,in7_credit_val - ,in7_credit_frac - ,in_expiration_date - ,in_gc_date), - (in8_reserve_pub - ,in8_credit_val - ,in8_credit_frac - ,in_expiration_date - ,in_gc_date) - ON CONFLICT DO NOTHING - RETURNING reserve_uuid,reserve_pub) - SELECT * FROM reserve_changes; - - WHILE k < 8 LOOP - - FETCH FROM curs_reserve_existed INTO i; - IF FOUND - THEN - IF in_reserve_pub = i.reserve_pub - THEN - ruuid = i.reserve_uuid; - IF in_reserve_pub - NOT IN (in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found = FALSE; - END IF; - END IF; - IF in2_reserve_pub = i.reserve_pub - THEN - ruuid2 = i.reserve_uuid; - IF in2_reserve_pub - NOT IN (in_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found2 = FALSE; - END IF; - END IF; - IF in3_reserve_pub = i.reserve_pub - THEN - ruuid3 = i.reserve_uuid; - IF in3_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found3 = FALSE; - END IF; - END IF; - IF in4_reserve_pub = i.reserve_pub - THEN - ruuid4 = i.reserve_uuid; - IF in4_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found4 = FALSE; - END IF; - END IF; - IF in5_reserve_pub = i.reserve_pub - THEN - ruuid5 = i.reserve_uuid; - IF in5_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found5 = FALSE; - END IF; - END IF; - IF in6_reserve_pub = i.reserve_pub - THEN - ruuid6 = i.reserve_uuid; - IF in6_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found6 = FALSE; - END IF; - END IF; - IF in7_reserve_pub = i.reserve_pub - THEN - ruuid7 = i.reserve_uuid; - IF in7_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found7 = FALSE; - END IF; - END IF; - IF in8_reserve_pub = i.reserve_pub - THEN - ruuid8 = i.reserve_uuid; - IF in8_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub) - THEN - out_reserve_found8 = FALSE; - END IF; - END IF; - END IF; - k=k+1; - END LOOP; - - CLOSE curs_reserve_existed; - --- FIXME: must be changed to EXECUTE FORMAT! - PERFORM pg_notify(in_notify, NULL); - PERFORM pg_notify(in2_notify, NULL); - PERFORM pg_notify(in3_notify, NULL); - PERFORM pg_notify(in4_notify, NULL); - PERFORM pg_notify(in5_notify, NULL); - PERFORM pg_notify(in6_notify, NULL); - PERFORM pg_notify(in7_notify, NULL); - PERFORM pg_notify(in8_notify, NULL); - k=0; - OPEN curs_transaction_existed FOR - WITH reserve_in_changes AS ( - INSERT INTO reserves_in - (reserve_pub - ,wire_reference - ,credit_val - ,credit_frac - ,exchange_account_section - ,wire_source_h_payto - ,execution_date) - VALUES - (in_reserve_pub - ,in_wire_ref - ,in_credit_val - ,in_credit_frac - ,in_exchange_account_name - ,in_wire_source_h_payto - ,in_execution_date), - (in2_reserve_pub - ,in2_wire_ref - ,in2_credit_val - ,in2_credit_frac - ,in2_exchange_account_name - ,in2_wire_source_h_payto - ,in_execution_date), - (in3_reserve_pub - ,in3_wire_ref - ,in3_credit_val - ,in3_credit_frac - ,in3_exchange_account_name - ,in3_wire_source_h_payto - ,in_execution_date), - (in4_reserve_pub - ,in4_wire_ref - ,in4_credit_val - ,in4_credit_frac - ,in4_exchange_account_name - ,in4_wire_source_h_payto - ,in_execution_date), - (in5_reserve_pub - ,in5_wire_ref - ,in5_credit_val - ,in5_credit_frac - ,in5_exchange_account_name - ,in5_wire_source_h_payto - ,in_execution_date), - (in6_reserve_pub - ,in6_wire_ref - ,in6_credit_val - ,in6_credit_frac - ,in6_exchange_account_name - ,in6_wire_source_h_payto - ,in_execution_date), - (in7_reserve_pub - ,in7_wire_ref - ,in7_credit_val - ,in7_credit_frac - ,in7_exchange_account_name - ,in7_wire_source_h_payto - ,in_execution_date), - (in8_reserve_pub - ,in8_wire_ref - ,in8_credit_val - ,in8_credit_frac - ,in8_exchange_account_name - ,in8_wire_source_h_payto - ,in_execution_date) - ON CONFLICT DO NOTHING - RETURNING reserve_pub) - SELECT * FROM reserve_in_changes; - - WHILE k < 8 LOOP - FETCH FROM curs_transaction_existed INTO r; - IF FOUND - THEN - IF in_reserve_pub = r.reserve_pub - THEN - transaction_duplicate = FALSE; - END IF; - IF in2_reserve_pub = r.reserve_pub - THEN - transaction_duplicate2 = FALSE; - END IF; - IF in3_reserve_pub = r.reserve_pub - THEN - transaction_duplicate3 = FALSE; - END IF; - IF in4_reserve_pub = r.reserve_pub - THEN - transaction_duplicate4 = FALSE; - END IF; - IF in5_reserve_pub = r.reserve_pub - THEN - transaction_duplicate5 = FALSE; - END IF; - IF in6_reserve_pub = r.reserve_pub - THEN - transaction_duplicate6 = FALSE; - END IF; - IF in7_reserve_pub = r.reserve_pub - THEN - transaction_duplicate7 = FALSE; - END IF; - IF in8_reserve_pub = r.reserve_pub - THEN - transaction_duplicate8 = FALSE; - END IF; - END IF; - k=k+1; - END LOOP; - /* IF transaction_duplicate - OR transaction_duplicate2 - OR transaction_duplicate3 - OR transaction_duplicate4 - OR transaction_duplicate5 - OR transaction_duplicate6 - OR transaction_duplicate7 - OR transaction_duplicate8 - THEN - CLOSE curs_transaction_existed; - ROLLBACK; - RETURN; - END IF;*/ - CLOSE curs_transaction_existed; - RETURN; -END $$; diff --git a/src/exchangedb/exchange_do_batch_reserves_in_insert.sql b/src/exchangedb/exchange_do_batch_reserves_in_insert.sql deleted file mode 100644 index 5ee819229..000000000 --- a/src/exchangedb/exchange_do_batch_reserves_in_insert.sql +++ /dev/null @@ -1,120 +0,0 @@ --- --- This file is part of TALER --- Copyright (C) 2014--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 --- - -DROP FUNCTION IF EXISTS exchange_do_batch_reserves_in_insert; -CREATE OR REPLACE FUNCTION exchange_do_batch_reserves_in_insert( - IN in_reserve_pub BYTEA, - IN in_expiration_date INT8, - IN in_gc_date INT8, - IN in_wire_ref INT8, - IN in_credit_val INT8, - IN in_credit_frac INT4, - IN in_exchange_account_name VARCHAR, - IN in_execution_date INT8, - IN in_wire_source_h_payto BYTEA, ---h_payto - IN in_payto_uri VARCHAR, - IN in_reserve_expiration INT8, - IN in_notify text, - OUT out_reserve_found BOOLEAN, - OUT transaction_duplicate BOOLEAN, - OUT ruuid INT8) -LANGUAGE plpgsql -AS $$ -DECLARE - curs refcursor; -DECLARE - i RECORD; -DECLARE - curs_trans refcursor; -BEGIN - ruuid = 0; - out_reserve_found = TRUE; - transaction_duplicate = TRUE; - ---SIMPLE INSERT ON CONFLICT DO NOTHING - INSERT INTO wire_targets - (wire_target_h_payto - ,payto_uri) - VALUES - (in_wire_source_h_payto - ,in_payto_uri) - ON CONFLICT DO NOTHING; - - OPEN curs FOR - WITH reserve_changes AS ( - INSERT INTO reserves - (reserve_pub - ,current_balance_val - ,current_balance_frac - ,expiration_date - ,gc_date) - VALUES - (in_reserve_pub - ,in_credit_val - ,in_credit_frac - ,in_expiration_date - ,in_gc_date) - ON CONFLICT DO NOTHING - RETURNING reserve_uuid, reserve_pub) - SELECT * FROM reserve_changes; - FETCH FROM curs INTO i; - IF FOUND - THEN - -- We made a change, so the reserve did not previously exist. - IF in_reserve_pub = i.reserve_pub - THEN - out_reserve_found = FALSE; - ruuid = i.reserve_uuid; - END IF; - END IF; - CLOSE curs; - - OPEN curs_trans FOR - WITH reserve_transaction AS( - INSERT INTO reserves_in - (reserve_pub - ,wire_reference - ,credit_val - ,credit_frac - ,exchange_account_section - ,wire_source_h_payto - ,execution_date) - VALUES - (in_reserve_pub - ,in_wire_ref - ,in_credit_val - ,in_credit_frac - ,in_exchange_account_name - ,in_wire_source_h_payto - ,in_execution_date) - ON CONFLICT DO NOTHING - RETURNING reserve_pub) - SELECT * FROM reserve_transaction; - FETCH FROM curs_trans INTO i; - IF FOUND - THEN - IF i.reserve_pub = in_reserve_pub - THEN - -- HAPPY PATH THERE IS NO DUPLICATE TRANS - transaction_duplicate = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in_notify); - END IF; - END IF; - CLOSE curs_trans; - RETURN; -END $$; diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql new file mode 100644 index 000000000..3a217accf --- /dev/null +++ b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -0,0 +1,1065 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2014--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 +-- + +CREATE OR REPLACE FUNCTION exchange_do_batch_reserves_in_insert( + IN in_gc_date INT8, + IN in_reserve_expiration INT8, + IN in_reserve_pub BYTEA, + IN in_wire_ref INT8, + IN in_credit_val INT8, + IN in_credit_frac INT4, + IN in_exchange_account_name VARCHAR, + IN in_execution_date INT8, + IN in_wire_source_h_payto BYTEA, ---h_payto + IN in_payto_uri VARCHAR, + IN in_notify text, + OUT out_reserve_found BOOLEAN, + OUT transaction_duplicate BOOLEAN, + OUT ruuid INT8) +LANGUAGE plpgsql +AS $$ +DECLARE + curs refcursor; +DECLARE + i RECORD; +DECLARE + curs_trans refcursor; +BEGIN + ruuid = 0; + out_reserve_found = TRUE; + transaction_duplicate = TRUE; + +--SIMPLE INSERT ON CONFLICT DO NOTHING + INSERT INTO wire_targets + (wire_target_h_payto + ,payto_uri) + VALUES + (in_wire_source_h_payto + ,in_payto_uri) + ON CONFLICT DO NOTHING; + + OPEN curs FOR + WITH reserve_changes AS ( + INSERT INTO reserves + (reserve_pub + ,current_balance_val + ,current_balance_frac + ,expiration_date + ,gc_date) + VALUES + (in_reserve_pub + ,in_credit_val + ,in_credit_frac + ,in_reserve_expiration + ,in_gc_date) + ON CONFLICT DO NOTHING + RETURNING reserve_uuid, reserve_pub) + SELECT * FROM reserve_changes; + FETCH FROM curs INTO i; + IF FOUND + THEN + -- We made a change, so the reserve did not previously exist. + IF in_reserve_pub = i.reserve_pub + THEN + out_reserve_found = FALSE; + ruuid = i.reserve_uuid; + END IF; + END IF; + CLOSE curs; + + OPEN curs_trans FOR + WITH reserve_transaction AS( + INSERT INTO reserves_in + (reserve_pub + ,wire_reference + ,credit_val + ,credit_frac + ,exchange_account_section + ,wire_source_h_payto + ,execution_date) + VALUES + (in_reserve_pub + ,in_wire_ref + ,in_credit_val + ,in_credit_frac + ,in_exchange_account_name + ,in_wire_source_h_payto + ,in_execution_date) + ON CONFLICT DO NOTHING + RETURNING reserve_pub) + SELECT * FROM reserve_transaction; + FETCH FROM curs_trans INTO i; + IF FOUND + THEN + IF i.reserve_pub = in_reserve_pub + THEN + -- HAPPY PATH THERE IS NO DUPLICATE TRANS + transaction_duplicate = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in_notify); + END IF; + END IF; + CLOSE curs_trans; + RETURN; +END $$; + +CREATE OR REPLACE FUNCTION exchange_do_batch2_reserves_insert( + IN in_gc_date INT8, + IN in_reserve_expiration INT8, + IN in_reserve_pub BYTEA, + IN in_wire_ref INT8, + IN in_credit_val INT8, + IN in_credit_frac INT4, + IN in_exchange_account_name VARCHAR, + IN in_execution_date INT8, + IN in_wire_source_h_payto BYTEA, ---h_payto + IN in_payto_uri VARCHAR, + IN in_notify text, + IN in2_notify text, + IN in2_reserve_pub BYTEA, + IN in2_wire_ref INT8, + IN in2_credit_val INT8, + IN in2_credit_frac INT4, + IN in2_exchange_account_name VARCHAR, + IN in2_execution_date INT8, + IN in2_wire_source_h_payto BYTEA, ---h_payto + IN in2_payto_uri VARCHAR, + OUT out_reserve_found BOOLEAN, + OUT out_reserve_found2 BOOLEAN, + OUT transaction_duplicate BOOLEAN, + OUT transaction_duplicate2 BOOLEAN, + OUT ruuid INT8, + OUT ruuid2 INT8) +LANGUAGE plpgsql +AS $$ +DECLARE + curs_reserve_exist REFCURSOR; +DECLARE + curs_transaction_exist refcursor; +DECLARE + i RECORD; +DECLARE + r RECORD; +DECLARE + k INT8; +BEGIN + transaction_duplicate=TRUE; + transaction_duplicate2=TRUE; + out_reserve_found = TRUE; + out_reserve_found2 = TRUE; + ruuid=0; + ruuid2=0; + k=0; + INSERT INTO wire_targets + (wire_target_h_payto + ,payto_uri) + VALUES + (in_wire_source_h_payto + ,in_payto_uri), + (in2_wire_source_h_payto + ,in2_payto_uri) + ON CONFLICT DO NOTHING; + + OPEN curs_reserve_exist FOR + WITH reserve_changes AS ( + INSERT INTO reserves + (reserve_pub + ,current_balance_val + ,current_balance_frac + ,expiration_date + ,gc_date) + VALUES + (in_reserve_pub + ,in_credit_val + ,in_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in2_reserve_pub + ,in2_credit_val + ,in2_credit_frac + ,in_reserve_expiration + ,in_gc_date) + ON CONFLICT DO NOTHING + RETURNING reserve_uuid,reserve_pub) + SELECT * FROM reserve_changes; + WHILE k < 2 LOOP + FETCH FROM curs_reserve_exist INTO i; + IF FOUND + THEN + IF in_reserve_pub = i.reserve_pub + THEN + ruuid = i.reserve_uuid; + IF in_reserve_pub <> in2_reserve_pub + THEN + out_reserve_found = FALSE; + END IF; + END IF; + IF in2_reserve_pub = i.reserve_pub + THEN + out_reserve_found2 = FALSE; + ruuid2 = i.reserve_uuid; + END IF; + END IF; + k=k+1; + END LOOP; + CLOSE curs_reserve_exist; + + OPEN curs_transaction_exist FOR + WITH reserve_in_exist AS ( + INSERT INTO reserves_in + (reserve_pub + ,wire_reference + ,credit_val + ,credit_frac + ,exchange_account_section + ,wire_source_h_payto + ,execution_date) + VALUES + (in_reserve_pub + ,in_wire_ref + ,in_credit_val + ,in_credit_frac + ,in_exchange_account_name + ,in_wire_source_h_payto + ,in_execution_date), + (in2_reserve_pub + ,in2_wire_ref + ,in2_credit_val + ,in2_credit_frac + ,in2_exchange_account_name + ,in2_wire_source_h_payto + ,in2_execution_date) + ON CONFLICT DO NOTHING + RETURNING reserve_pub) + SELECT * FROM reserve_in_exist; + FETCH FROM curs_transaction_exist INTO r; + IF FOUND + THEN + IF in_reserve_pub = r.reserve_pub + THEN + transaction_duplicate = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in_notify); + END IF; + IF in2_reserve_pub = r.reserve_pub + THEN + transaction_duplicate2 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in2_notify); + END IF; + FETCH FROM curs_transaction_exist INTO r; + IF FOUND + THEN + IF in_reserve_pub = r.reserve_pub + THEN + transaction_duplicate = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in_notify); + END IF; + IF in2_reserve_pub = r.reserve_pub + THEN + transaction_duplicate2 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in2_notify); + END IF; + END IF; + END IF; +/* IF transaction_duplicate + OR transaction_duplicate2 + THEN + CLOSE curs_transaction_exist; + ROLLBACK; + RETURN; + END IF;*/ + CLOSE curs_transaction_exist; + RETURN; +END $$; + +CREATE OR REPLACE FUNCTION exchange_do_batch4_reserves_insert( + IN in_gc_date INT8, + IN in_reserve_expiration INT8, + IN in_reserve_pub BYTEA, + IN in_wire_ref INT8, + IN in_credit_val INT8, + IN in_credit_frac INT4, + IN in_exchange_account_name VARCHAR, + IN in_execution_date INT8, + IN in_wire_source_h_payto BYTEA, ---h_payto + IN in_payto_uri VARCHAR, + IN in_notify text, + IN in2_notify text, + IN in3_notify text, + IN in4_notify text, + IN in2_reserve_pub BYTEA, + IN in2_wire_ref INT8, + IN in2_credit_val INT8, + IN in2_credit_frac INT4, + IN in2_exchange_account_name VARCHAR, + IN in2_execute_date INT8, + IN in2_wire_source_h_payto BYTEA, ---h_payto + IN in2_payto_uri VARCHAR, + IN in3_reserve_pub BYTEA, + IN in3_wire_ref INT8, + IN in3_credit_val INT8, + IN in3_credit_frac INT4, + IN in3_exchange_account_name VARCHAR, + IN in3_execute_date INT8, + IN in3_wire_source_h_payto BYTEA, ---h_payto + IN in3_payto_uri VARCHAR, + IN in4_reserve_pub BYTEA, + IN in4_wire_ref INT8, + IN in4_credit_val INT8, + IN in4_credit_frac INT4, + IN in4_exchange_account_name VARCHAR, + IN in4_execution_date INT8, + IN in4_wire_source_h_payto BYTEA, ---h_payto + IN in4_payto_uri VARCHAR, + OUT out_reserve_found BOOLEAN, + OUT out_reserve_found2 BOOLEAN, + OUT out_reserve_found3 BOOLEAN, + OUT out_reserve_found4 BOOLEAN, + OUT transaction_duplicate BOOLEAN, + OUT transaction_duplicate2 BOOLEAN, + OUT transaction_duplicate3 BOOLEAN, + OUT transaction_duplicate4 BOOLEAN, + OUT ruuid INT8, + OUT ruuid2 INT8, + OUT ruuid3 INT8, + OUT ruuid4 INT8) +LANGUAGE plpgsql +AS $$ +DECLARE + curs_reserve_exist refcursor; +DECLARE + k INT8; +DECLARE + curs_transaction_exist refcursor; +DECLARE + i RECORD; + +BEGIN +--INITIALIZATION + transaction_duplicate=TRUE; + transaction_duplicate2=TRUE; + transaction_duplicate3=TRUE; + transaction_duplicate4=TRUE; + out_reserve_found = TRUE; + out_reserve_found2 = TRUE; + out_reserve_found3 = TRUE; + out_reserve_found4 = TRUE; + ruuid=0; + ruuid2=0; + ruuid3=0; + ruuid4=0; + k=0; + --SIMPLE INSERT ON CONFLICT DO NOTHING + INSERT INTO wire_targets + (wire_target_h_payto + ,payto_uri) + VALUES + (in_wire_source_h_payto + ,in_payto_uri), + (in2_wire_source_h_payto + ,in2_payto_uri), + (in3_wire_source_h_payto + ,in3_payto_uri), + (in4_wire_source_h_payto + ,in4_payto_uri) + ON CONFLICT DO NOTHING; + + OPEN curs_reserve_exist FOR + WITH reserve_changes AS ( + INSERT INTO reserves + (reserve_pub + ,current_balance_val + ,current_balance_frac + ,expiration_date + ,gc_date) + VALUES + (in_reserve_pub + ,in_credit_val + ,in_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in2_reserve_pub + ,in2_credit_val + ,in2_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in3_reserve_pub + ,in3_credit_val + ,in3_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in4_reserve_pub + ,in4_credit_val + ,in4_credit_frac + ,in_reserve_expiration + ,in_gc_date) + ON CONFLICT DO NOTHING + RETURNING reserve_uuid,reserve_pub) + SELECT * FROM reserve_changes; + + WHILE k < 4 LOOP + FETCH FROM curs_reserve_exist INTO i; + IF FOUND + THEN + IF in_reserve_pub = i.reserve_pub + THEN + ruuid = i.reserve_uuid; + IF in_reserve_pub + NOT IN (in2_reserve_pub + ,in3_reserve_pub + ,in4_reserve_pub) + THEN + out_reserve_found = FALSE; + END IF; + END IF; + IF in2_reserve_pub = i.reserve_pub + THEN + ruuid2 = i.reserve_uuid; + IF in2_reserve_pub + NOT IN (in_reserve_pub + ,in3_reserve_pub + ,in4_reserve_pub) + THEN + out_reserve_found2 = FALSE; + END IF; + END IF; + IF in3_reserve_pub = i.reserve_pub + THEN + ruuid3 = i.reserve_uuid; + IF in3_reserve_pub + NOT IN (in_reserve_pub + ,in2_reserve_pub + ,in4_reserve_pub) + THEN + out_reserve_found3 = FALSE; + END IF; + END IF; + IF in4_reserve_pub = i.reserve_pub + THEN + ruuid4 = i.reserve_uuid; + IF in4_reserve_pub + NOT IN (in_reserve_pub + ,in2_reserve_pub + ,in3_reserve_pub) + THEN + out_reserve_found4 = FALSE; + END IF; + END IF; + END IF; + k=k+1; + END LOOP; + CLOSE curs_reserve_exist; + + k=0; + OPEN curs_transaction_exist FOR + WITH reserve_in_changes AS ( + INSERT INTO reserves_in + (reserve_pub + ,wire_reference + ,credit_val + ,credit_frac + ,exchange_account_section + ,wire_source_h_payto + ,execution_date) + VALUES + (in_reserve_pub + ,in_wire_ref + ,in_credit_val + ,in_credit_frac + ,in_exchange_account_name + ,in_wire_source_h_payto + ,in_execution_date), + (in2_reserve_pub + ,in2_wire_ref + ,in2_credit_val + ,in2_credit_frac + ,in2_exchange_account_name + ,in2_wire_source_h_payto + ,in2_execution_date), + (in3_reserve_pub + ,in3_wire_ref + ,in3_credit_val + ,in3_credit_frac + ,in3_exchange_account_name + ,in3_wire_source_h_payto + ,in3_execution_date), + (in4_reserve_pub + ,in4_wire_ref + ,in4_credit_val + ,in4_credit_frac + ,in4_exchange_account_name + ,in4_wire_source_h_payto + ,in4_execution_date) + ON CONFLICT DO NOTHING + RETURNING reserve_pub) + SELECT * FROM reserve_in_changes; + WHILE k < 4 LOOP + FETCH FROM curs_transaction_exist INTO i; + IF FOUND + THEN + IF in_reserve_pub = i.reserve_pub + THEN + transaction_duplicate = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in_notify); + END IF; + IF in2_reserve_pub = i.reserve_pub + THEN + transaction_duplicate2 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in2_notify); + END IF; + IF in3_reserve_pub = i.reserve_pub + THEN + transaction_duplicate3 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in3_notify); + END IF; + IF in4_reserve_pub = i.reserve_pub + THEN + transaction_duplicate4 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in4_notify); + END IF; + END IF; + k=k+1; + END LOOP; + /**ROLLBACK TRANSACTION IN SORTED PROCEDURE IS IT PROSSIBLE ?**/ + /*IF transaction_duplicate + OR transaction_duplicate2 + OR transaction_duplicate3 + OR transaction_duplicate4 + THEN + RAISE EXCEPTION 'Reserve did not exist, but INSERT into reserves_in gave conflict'; + ROLLBACK; + CLOSE curs_transaction_exist; + RETURN; + END IF;*/ + CLOSE curs_transaction_exist; + RETURN; + +END $$; + +CREATE OR REPLACE FUNCTION exchange_do_batch8_reserves_insert( + IN in_gc_date INT8, + IN in_reserve_expiration INT8, + IN in_reserve_pub BYTEA, + IN in_wire_ref INT8, + IN in_credit_val INT8, + IN in_credit_frac INT4, + IN in_exchange_account_name VARCHAR, + IN in_execution_date INT8, + IN in_wire_source_h_payto BYTEA, ---h_payto + IN in_payto_uri VARCHAR, + IN in_notify text, + IN in2_notify text, + IN in3_notify text, + IN in4_notify text, + IN in5_notify text, + IN in6_notify text, + IN in7_notify text, + IN in8_notify text, + IN in2_reserve_pub BYTEA, + IN in2_wire_ref INT8, + IN in2_credit_val INT8, + IN in2_credit_frac INT4, + IN in2_exchange_account_name VARCHAR, + IN in2_execution_date INT8, + IN in2_wire_source_h_payto BYTEA, ---h_payto + IN in2_payto_uri VARCHAR, + IN in3_reserve_pub BYTEA, + IN in3_wire_ref INT8, + IN in3_credit_val INT8, + IN in3_credit_frac INT4, + IN in3_exchange_account_name VARCHAR, + IN in3_execution_date INT8, + IN in3_wire_source_h_payto BYTEA, ---h_payto + IN in3_payto_uri VARCHAR, + IN in4_reserve_pub BYTEA, + IN in4_wire_ref INT8, + IN in4_credit_val INT8, + IN in4_credit_frac INT4, + IN in4_exchange_account_name VARCHAR, + IN in4_execution_date INT8, + IN in4_wire_source_h_payto BYTEA, ---h_payto + IN in4_payto_uri VARCHAR, + IN in5_reserve_pub BYTEA, + IN in5_wire_ref INT8, + IN in5_credit_val INT8, + IN in5_credit_frac INT4, + IN in5_exchange_account_name VARCHAR, + IN in5_execution_date INT8, + IN in5_wire_source_h_payto BYTEA, ---h_payto + IN in5_payto_uri VARCHAR, + IN in6_reserve_pub BYTEA, + IN in6_wire_ref INT8, + IN in6_credit_val INT8, + IN in6_credit_frac INT4, + IN in6_exchange_account_name VARCHAR, + IN in6_execution_date INT8, + IN in6_wire_source_h_payto BYTEA, ---h_payto + IN in6_payto_uri VARCHAR, + IN in7_reserve_pub BYTEA, + IN in7_wire_ref INT8, + IN in7_credit_val INT8, + IN in7_credit_frac INT4, + IN in7_exchange_account_name VARCHAR, + IN in7_execution_date INT8, + IN in7_wire_source_h_payto BYTEA, ---h_payto + IN in7_payto_uri VARCHAR, + IN in8_reserve_pub BYTEA, + IN in8_wire_ref INT8, + IN in8_credit_val INT8, + IN in8_credit_frac INT4, + IN in8_exchange_account_name VARCHAR, + IN in8_execution_date INT8, + IN in8_wire_source_h_payto BYTEA, ---h_payto + IN in8_payto_uri VARCHAR, + OUT out_reserve_found BOOLEAN, + OUT out_reserve_found2 BOOLEAN, + OUT out_reserve_found3 BOOLEAN, + OUT out_reserve_found4 BOOLEAN, + OUT out_reserve_found5 BOOLEAN, + OUT out_reserve_found6 BOOLEAN, + OUT out_reserve_found7 BOOLEAN, + OUT out_reserve_found8 BOOLEAN, + OUT transaction_duplicate BOOLEAN, + OUT transaction_duplicate2 BOOLEAN, + OUT transaction_duplicate3 BOOLEAN, + OUT transaction_duplicate4 BOOLEAN, + OUT transaction_duplicate5 BOOLEAN, + OUT transaction_duplicate6 BOOLEAN, + OUT transaction_duplicate7 BOOLEAN, + OUT transaction_duplicate8 BOOLEAN, + OUT ruuid INT8, + OUT ruuid2 INT8, + OUT ruuid3 INT8, + OUT ruuid4 INT8, + OUT ruuid5 INT8, + OUT ruuid6 INT8, + OUT ruuid7 INT8, + OUT ruuid8 INT8) +LANGUAGE plpgsql +AS $$ +DECLARE + curs_reserve_existed refcursor; +DECLARE + k INT8; +DECLARE + curs_transaction_existed refcursor; +DECLARE + i RECORD; +DECLARE + r RECORD; + +BEGIN +--INITIALIZATION + transaction_duplicate=TRUE; + transaction_duplicate2=TRUE; + transaction_duplicate3=TRUE; + transaction_duplicate4=TRUE; + transaction_duplicate5=TRUE; + transaction_duplicate6=TRUE; + transaction_duplicate7=TRUE; + transaction_duplicate8=TRUE; + out_reserve_found = TRUE; + out_reserve_found2 = TRUE; + out_reserve_found3 = TRUE; + out_reserve_found4 = TRUE; + out_reserve_found5 = TRUE; + out_reserve_found6 = TRUE; + out_reserve_found7 = TRUE; + out_reserve_found8 = TRUE; + ruuid=0; + ruuid2=0; + ruuid3=0; + ruuid4=0; + ruuid5=0; + ruuid6=0; + ruuid7=0; + ruuid8=0; + k=0; + + --SIMPLE INSERT ON CONFLICT DO NOTHING + INSERT INTO wire_targets + (wire_target_h_payto + ,payto_uri) + VALUES + (in_wire_source_h_payto + ,in_payto_uri), + (in2_wire_source_h_payto + ,in2_payto_uri), + (in3_wire_source_h_payto + ,in3_payto_uri), + (in4_wire_source_h_payto + ,in4_payto_uri), + (in5_wire_source_h_payto + ,in5_payto_uri), + (in6_wire_source_h_payto + ,in6_payto_uri), + (in7_wire_source_h_payto + ,in7_payto_uri), + (in8_wire_source_h_payto + ,in8_payto_uri) + ON CONFLICT DO NOTHING; + + OPEN curs_reserve_existed FOR + WITH reserve_changes AS ( + INSERT INTO reserves + (reserve_pub + ,current_balance_val + ,current_balance_frac + ,expiration_date + ,gc_date) + VALUES + (in_reserve_pub + ,in_credit_val + ,in_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in2_reserve_pub + ,in2_credit_val + ,in2_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in3_reserve_pub + ,in3_credit_val + ,in3_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in4_reserve_pub + ,in4_credit_val + ,in4_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in5_reserve_pub + ,in5_credit_val + ,in5_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in6_reserve_pub + ,in6_credit_val + ,in6_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in7_reserve_pub + ,in7_credit_val + ,in7_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in8_reserve_pub + ,in8_credit_val + ,in8_credit_frac + ,in_reserve_expiration + ,in_gc_date) + ON CONFLICT DO NOTHING + RETURNING reserve_uuid,reserve_pub) + SELECT * FROM reserve_changes; + + WHILE k < 8 LOOP + + FETCH FROM curs_reserve_existed INTO i; + IF FOUND + THEN + IF in_reserve_pub = i.reserve_pub + THEN + ruuid = i.reserve_uuid; + IF in_reserve_pub + NOT IN (in2_reserve_pub + ,in3_reserve_pub + ,in4_reserve_pub + ,in5_reserve_pub + ,in6_reserve_pub + ,in7_reserve_pub + ,in8_reserve_pub) + THEN + out_reserve_found = FALSE; + END IF; + END IF; + IF in2_reserve_pub = i.reserve_pub + THEN + ruuid2 = i.reserve_uuid; + IF in2_reserve_pub + NOT IN (in_reserve_pub + ,in3_reserve_pub + ,in4_reserve_pub + ,in5_reserve_pub + ,in6_reserve_pub + ,in7_reserve_pub + ,in8_reserve_pub) + THEN + out_reserve_found2 = FALSE; + END IF; + END IF; + IF in3_reserve_pub = i.reserve_pub + THEN + ruuid3 = i.reserve_uuid; + IF in3_reserve_pub + NOT IN (in_reserve_pub + ,in2_reserve_pub + ,in4_reserve_pub + ,in5_reserve_pub + ,in6_reserve_pub + ,in7_reserve_pub + ,in8_reserve_pub) + THEN + out_reserve_found3 = FALSE; + END IF; + END IF; + IF in4_reserve_pub = i.reserve_pub + THEN + ruuid4 = i.reserve_uuid; + IF in4_reserve_pub + NOT IN (in_reserve_pub + ,in2_reserve_pub + ,in3_reserve_pub + ,in5_reserve_pub + ,in6_reserve_pub + ,in7_reserve_pub + ,in8_reserve_pub) + THEN + out_reserve_found4 = FALSE; + END IF; + END IF; + IF in5_reserve_pub = i.reserve_pub + THEN + ruuid5 = i.reserve_uuid; + IF in5_reserve_pub + NOT IN (in_reserve_pub + ,in2_reserve_pub + ,in3_reserve_pub + ,in4_reserve_pub + ,in6_reserve_pub + ,in7_reserve_pub + ,in8_reserve_pub) + THEN + out_reserve_found5 = FALSE; + END IF; + END IF; + IF in6_reserve_pub = i.reserve_pub + THEN + ruuid6 = i.reserve_uuid; + IF in6_reserve_pub + NOT IN (in_reserve_pub + ,in2_reserve_pub + ,in3_reserve_pub + ,in4_reserve_pub + ,in5_reserve_pub + ,in7_reserve_pub + ,in8_reserve_pub) + THEN + out_reserve_found6 = FALSE; + END IF; + END IF; + IF in7_reserve_pub = i.reserve_pub + THEN + ruuid7 = i.reserve_uuid; + IF in7_reserve_pub + NOT IN (in_reserve_pub + ,in2_reserve_pub + ,in3_reserve_pub + ,in4_reserve_pub + ,in5_reserve_pub + ,in6_reserve_pub + ,in8_reserve_pub) + THEN + out_reserve_found7 = FALSE; + END IF; + END IF; + IF in8_reserve_pub = i.reserve_pub + THEN + ruuid8 = i.reserve_uuid; + IF in8_reserve_pub + NOT IN (in_reserve_pub + ,in2_reserve_pub + ,in3_reserve_pub + ,in4_reserve_pub + ,in5_reserve_pub + ,in6_reserve_pub + ,in7_reserve_pub) + THEN + out_reserve_found8 = FALSE; + END IF; + END IF; + END IF; + k=k+1; + END LOOP; + + CLOSE curs_reserve_existed; + + k=0; + OPEN curs_transaction_existed FOR + WITH reserve_in_changes AS ( + INSERT INTO reserves_in + (reserve_pub + ,wire_reference + ,credit_val + ,credit_frac + ,exchange_account_section + ,wire_source_h_payto + ,execution_date) + VALUES + (in_reserve_pub + ,in_wire_ref + ,in_credit_val + ,in_credit_frac + ,in_exchange_account_name + ,in_wire_source_h_payto + ,in_execution_date), + (in2_reserve_pub + ,in2_wire_ref + ,in2_credit_val + ,in2_credit_frac + ,in2_exchange_account_name + ,in2_wire_source_h_payto + ,in2_execution_date), + (in3_reserve_pub + ,in3_wire_ref + ,in3_credit_val + ,in3_credit_frac + ,in3_exchange_account_name + ,in3_wire_source_h_payto + ,in3_execution_date), + (in4_reserve_pub + ,in4_wire_ref + ,in4_credit_val + ,in4_credit_frac + ,in4_exchange_account_name + ,in4_wire_source_h_payto + ,in4_execution_date), + (in5_reserve_pub + ,in5_wire_ref + ,in5_credit_val + ,in5_credit_frac + ,in5_exchange_account_name + ,in5_wire_source_h_payto + ,in5_execution_date), + (in6_reserve_pub + ,in6_wire_ref + ,in6_credit_val + ,in6_credit_frac + ,in6_exchange_account_name + ,in6_wire_source_h_payto + ,in6_execution_date), + (in7_reserve_pub + ,in7_wire_ref + ,in7_credit_val + ,in7_credit_frac + ,in7_exchange_account_name + ,in7_wire_source_h_payto + ,in7_execution_date), + (in8_reserve_pub + ,in8_wire_ref + ,in8_credit_val + ,in8_credit_frac + ,in8_exchange_account_name + ,in8_wire_source_h_payto + ,in8_execution_date) + ON CONFLICT DO NOTHING + RETURNING reserve_pub) + SELECT * FROM reserve_in_changes; + + WHILE k < 8 LOOP + FETCH FROM curs_transaction_existed INTO r; + IF FOUND + THEN + IF in_reserve_pub = r.reserve_pub + THEN + transaction_duplicate = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in_notify); + END IF; + IF in2_reserve_pub = r.reserve_pub + THEN + transaction_duplicate2 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in2_notify); + END IF; + IF in3_reserve_pub = r.reserve_pub + THEN + transaction_duplicate3 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in3_notify); + END IF; + IF in4_reserve_pub = r.reserve_pub + THEN + transaction_duplicate4 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in4_notify); + END IF; + IF in5_reserve_pub = r.reserve_pub + THEN + transaction_duplicate5 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in5_notify); + END IF; + IF in6_reserve_pub = r.reserve_pub + THEN + transaction_duplicate6 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in6_notify); + END IF; + IF in7_reserve_pub = r.reserve_pub + THEN + transaction_duplicate7 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in7_notify); + END IF; + IF in8_reserve_pub = r.reserve_pub + THEN + transaction_duplicate8 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in8_notify); + END IF; + END IF; + k=k+1; + END LOOP; + /* IF transaction_duplicate + OR transaction_duplicate2 + OR transaction_duplicate3 + OR transaction_duplicate4 + OR transaction_duplicate5 + OR transaction_duplicate6 + OR transaction_duplicate7 + OR transaction_duplicate8 + THEN + CLOSE curs_transaction_existed; + ROLLBACK; + RETURN; + END IF;*/ + CLOSE curs_transaction_existed; + RETURN; +END $$; From 42258d5778fde385a78dd0e3420528f5f4583f6d Mon Sep 17 00:00:00 2001 From: Joseph Date: Thu, 9 Feb 2023 04:20:50 -0500 Subject: [PATCH 03/50] nothing to update --- src/exchangedb/pg_reserves_in_insert.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c index 7221e3908..16d30d41c 100644 --- a/src/exchangedb/pg_reserves_in_insert.c +++ b/src/exchangedb/pg_reserves_in_insert.c @@ -779,7 +779,7 @@ TEH_PG_reserves_in_insert (void *cls, &conflicts[i], &reserve_uuid[i], &results[i]); - fprintf(stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], conflicts[i], transaction_duplicate[i]); + fprintf(stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], conflicts[i], transaction_duplicate[i]); if (qs2<0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, From fb70814d46d5b92da45e2caa8c513263de7467b2 Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 20 Feb 2023 08:04:06 -0500 Subject: [PATCH 04/50] some changes for ensure known coin --- src/exchangedb/Makefile.am | 1 + src/exchangedb/plugin_exchangedb_postgres.c | 4 +++- src/exchangedb/procedures.sql.in | 1 + src/include/taler_exchangedb_plugin.h | 7 ++++++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am index 9757aefff..f07069f43 100644 --- a/src/exchangedb/Makefile.am +++ b/src/exchangedb/Makefile.am @@ -257,6 +257,7 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \ pg_select_purse_deposits_above_serial_id.h pg_select_purse_deposits_above_serial_id.c \ pg_select_account_merges_above_serial_id.h pg_select_account_merges_above_serial_id.c \ pg_select_all_purse_decisions_above_serial_id.h pg_select_all_purse_decisions_above_serial_id.c \ + pg_batch_ensure_coin_known.h pg_batch_ensure_coin_known.c \ pg_select_reserve_open_above_serial_id.c pg_select_reserve_open_above_serial_id.h libtaler_plugin_exchangedb_postgres_la_LIBADD = \ $(LTLIBINTL) diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 2ef250775..e67995188 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -216,7 +216,7 @@ #include "pg_select_aml_process.h" #include "pg_select_aml_history.h" #include "pg_insert_aml_decision.h" - +#include "pg_batch_ensure_coin_known.h" /** * Set to 1 to enable Postgres auto_explain module. This will @@ -773,6 +773,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) = &TEH_PG_select_aml_history; plugin->insert_aml_decision = &TEH_PG_insert_aml_decision; + plugin->batch_ensure_coin_known + = &TEH_PG_batch_ensure_coin_known; return plugin; } diff --git a/src/exchangedb/procedures.sql.in b/src/exchangedb/procedures.sql.in index 27a5b3bb3..12ec3656f 100644 --- a/src/exchangedb/procedures.sql.in +++ b/src/exchangedb/procedures.sql.in @@ -44,5 +44,6 @@ SET search_path TO exchange; #include "exchange_do_refund_by_coin.sql" #include "exchange_do_get_ready_deposit.sql" #include "exchange_do_get_link_data.sql" +#include "exchange_do_batch_coin_known.sql" COMMIT; diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 962bccaa2..02d7896a6 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -4026,7 +4026,12 @@ struct TALER_EXCHANGEDB_Plugin uint64_t *known_coin_id, struct TALER_DenominationHashP *denom_pub_hash, struct TALER_AgeCommitmentHash *age_hash); - + enum TALER_EXCHANGEDB_CoinKnownStatus + (*batch_ensure_coin_known)(void *cls, + const struct TALER_CoinPublicInfo *coin, + const struct TALER_CoinInfo *result, + unsigned int coin_length, + unsigned int batch_size); /** * Retrieve information about the given @a coin from the database. From d83c2539bcee852bb0ef6025900bfa7e67c32dff Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 3 Mar 2023 06:20:38 -0500 Subject: [PATCH 05/50] some changes for known coins --- src/exchangedb/Makefile.am | 1 - src/exchangedb/plugin_exchangedb_postgres.c | 5 ++--- src/include/taler_exchangedb_plugin.h | 7 +------ 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am index f07069f43..9757aefff 100644 --- a/src/exchangedb/Makefile.am +++ b/src/exchangedb/Makefile.am @@ -257,7 +257,6 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \ pg_select_purse_deposits_above_serial_id.h pg_select_purse_deposits_above_serial_id.c \ pg_select_account_merges_above_serial_id.h pg_select_account_merges_above_serial_id.c \ pg_select_all_purse_decisions_above_serial_id.h pg_select_all_purse_decisions_above_serial_id.c \ - pg_batch_ensure_coin_known.h pg_batch_ensure_coin_known.c \ pg_select_reserve_open_above_serial_id.c pg_select_reserve_open_above_serial_id.h libtaler_plugin_exchangedb_postgres_la_LIBADD = \ $(LTLIBINTL) diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index e67995188..2f3318184 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -216,7 +216,7 @@ #include "pg_select_aml_process.h" #include "pg_select_aml_history.h" #include "pg_insert_aml_decision.h" -#include "pg_batch_ensure_coin_known.h" + /** * Set to 1 to enable Postgres auto_explain module. This will @@ -773,8 +773,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) = &TEH_PG_select_aml_history; plugin->insert_aml_decision = &TEH_PG_insert_aml_decision; - plugin->batch_ensure_coin_known - = &TEH_PG_batch_ensure_coin_known; + return plugin; } diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 02d7896a6..962bccaa2 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -4026,12 +4026,7 @@ struct TALER_EXCHANGEDB_Plugin uint64_t *known_coin_id, struct TALER_DenominationHashP *denom_pub_hash, struct TALER_AgeCommitmentHash *age_hash); - enum TALER_EXCHANGEDB_CoinKnownStatus - (*batch_ensure_coin_known)(void *cls, - const struct TALER_CoinPublicInfo *coin, - const struct TALER_CoinInfo *result, - unsigned int coin_length, - unsigned int batch_size); + /** * Retrieve information about the given @a coin from the database. From cb87b6f646888bf62af31e8b23bb642de9a57344 Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 27 Mar 2023 07:23:27 -0400 Subject: [PATCH 06/50] New spi files --- .../exchange_do_batch_coin_known.sql | 477 ++++++++++ src/exchangedb/exchange_get_ready_deposit.sql | 60 ++ src/exchangedb/spi/README.md | 41 + src/exchangedb/spi/own_test.bc | Bin 0 -> 22876 bytes src/exchangedb/spi/own_test.c | 818 ++++++++++++++++++ src/exchangedb/spi/own_test.control | 4 + src/exchangedb/spi/own_test.so | Bin 0 -> 76824 bytes src/exchangedb/spi/own_test.sql | 216 +++++ src/exchangedb/spi/perf_own_test.c | 25 + src/exchangedb/spi/pg_aggregate.c | 389 +++++++++ 10 files changed, 2030 insertions(+) create mode 100644 src/exchangedb/exchange_do_batch_coin_known.sql create mode 100644 src/exchangedb/exchange_get_ready_deposit.sql create mode 100644 src/exchangedb/spi/README.md create mode 100644 src/exchangedb/spi/own_test.bc create mode 100644 src/exchangedb/spi/own_test.c create mode 100644 src/exchangedb/spi/own_test.control create mode 100755 src/exchangedb/spi/own_test.so create mode 100644 src/exchangedb/spi/own_test.sql create mode 100644 src/exchangedb/spi/perf_own_test.c create mode 100644 src/exchangedb/spi/pg_aggregate.c diff --git a/src/exchangedb/exchange_do_batch_coin_known.sql b/src/exchangedb/exchange_do_batch_coin_known.sql new file mode 100644 index 000000000..38d795959 --- /dev/null +++ b/src/exchangedb/exchange_do_batch_coin_known.sql @@ -0,0 +1,477 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2014--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 +-- + +CREATE OR REPLACE FUNCTION exchange_do_batch4_known_coin( + IN in_coin_pub1 BYTEA, + IN in_denom_pub_hash1 BYTEA, + IN in_h_age_commitment1 BYTEA, + IN in_denom_sig1 BYTEA, + IN in_coin_pub2 BYTEA, + IN in_denom_pub_hash2 BYTEA, + IN in_h_age_commitment2 BYTEA, + IN in_denom_sig2 BYTEA, + IN in_coin_pub3 BYTEA, + IN in_denom_pub_hash3 BYTEA, + IN in_h_age_commitment3 BYTEA, + IN in_denom_sig3 BYTEA, + IN in_coin_pub4 BYTEA, + IN in_denom_pub_hash4 BYTEA, + IN in_h_age_commitment4 BYTEA, + IN in_denom_sig4 BYTEA, + OUT existed1 BOOLEAN, + OUT existed2 BOOLEAN, + OUT existed3 BOOLEAN, + OUT existed4 BOOLEAN, + OUT known_coin_id1 INT8, + OUT known_coin_id2 INT8, + OUT known_coin_id3 INT8, + OUT known_coin_id4 INT8, + OUT denom_pub_hash1 BYTEA, + OUT denom_pub_hash2 BYTEA, + OUT denom_pub_hash3 BYTEA, + OUT denom_pub_hash4 BYTEA, + OUT age_commitment_hash1 BYTEA, + OUT age_commitment_hash2 BYTEA, + OUT age_commitment_hash3 BYTEA, + OUT age_commitment_hash4 BYTEA) +LANGUAGE plpgsql +AS $$ +BEGIN +WITH dd AS ( +SELECT + denominations_serial, + coin_val, coin_frac + FROM denominations + WHERE denom_pub_hash + IN + (in_denom_pub_hash1, + in_denom_pub_hash2, + in_denom_pub_hash3, + in_denom_pub_hash4) + ),--dd + input_rows AS ( + VALUES + (in_coin_pub1, + in_denom_pub_hash1, + in_h_age_commitment1, + in_denom_sig1), + (in_coin_pub2, + in_denom_pub_hash2, + in_h_age_commitment2, + in_denom_sig2), + (in_coin_pub3, + in_denom_pub_hash3, + in_h_age_commitment3, + in_denom_sig3), + (in_coin_pub4, + in_denom_pub_hash4, + in_h_age_commitment4, + in_denom_sig4) + ),--ir + ins AS ( + INSERT INTO known_coins ( + coin_pub, + denominations_serial, + age_commitment_hash, + denom_sig, + remaining_val, + remaining_frac + ) + SELECT + ir.coin_pub, + dd.denominations_serial, + ir.age_commitment_hash, + ir.denom_sig, + dd.coin_val, + dd.coin_frac + FROM input_rows ir + JOIN dd + ON dd.denom_pub_hash = ir.denom_pub_hash + ON CONFLICT DO NOTHING + RETURNING known_coin_id + ),--kc + exists AS ( + SELECT + CASE + WHEN + ins.known_coin_id IS NOT NULL + THEN + FALSE + ELSE + TRUE + END AS existed, + ins.known_coin_id, + dd.denom_pub_hash, + kc.age_commitment_hash + FROM input_rows ir + LEFT JOIN ins + ON ins.coin_pub = ir.coin_pub + LEFT JOIN known_coins kc + ON kc.coin_pub = ir.coin_pub + LEFT JOIN dd + ON dd.denom_pub_hash = ir.denom_pub_hash + )--exists +SELECT + exists.existed AS existed1, + exists.known_coin_id AS known_coin_id1, + exists.denom_pub_hash AS denom_pub_hash1, + exists.age_commitment_hash AS age_commitment_hash1, + ( + SELECT exists.existed + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash2 + ) AS existed2, + ( + SELECT exists.known_coin_id + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash2 + ) AS known_coin_id2, + ( + SELECT exists.denom_pub_hash + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash2 + ) AS denom_pub_hash2, + ( + SELECT exists.age_commitment_hash + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash2 + )AS age_commitment_hash2, + ( + SELECT exists.existed + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash3 + ) AS existed3, + ( + SELECT exists.known_coin_id + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash3 + ) AS known_coin_id3, + ( + SELECT exists.denom_pub_hash + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash3 + ) AS denom_pub_hash3, + ( + SELECT exists.age_commitment_hash + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash3 + )AS age_commitment_hash3, + ( + SELECT exists.existed + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash4 + ) AS existed4, + ( + SELECT exists.known_coin_id + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash4 + ) AS known_coin_id4, + ( + SELECT exists.denom_pub_hash + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash4 + ) AS denom_pub_hash4, + ( + SELECT exists.age_commitment_hash + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash4 + )AS age_commitment_hash4 +FROM exists; + +RETURN; +END $$; + + +CREATE OR REPLACE FUNCTION exchange_do_batch2_known_coin( + IN in_coin_pub1 BYTEA, + IN in_denom_pub_hash1 BYTEA, + IN in_h_age_commitment1 BYTEA, + IN in_denom_sig1 BYTEA, + IN in_coin_pub2 BYTEA, + IN in_denom_pub_hash2 BYTEA, + IN in_h_age_commitment2 BYTEA, + IN in_denom_sig2 BYTEA, + OUT existed1 BOOLEAN, + OUT existed2 BOOLEAN, + OUT known_coin_id1 INT8, + OUT known_coin_id2 INT8, + OUT denom_pub_hash1 BYTEA, + OUT denom_pub_hash2 BYTEA, + OUT age_commitment_hash1 BYTEA, + OUT age_commitment_hash2 BYTEA) +LANGUAGE plpgsql +AS $$ +BEGIN +WITH dd AS ( +SELECT + denominations_serial, + coin_val, coin_frac + FROM denominations + WHERE denom_pub_hash + IN + (in_denom_pub_hash1, + in_denom_pub_hash2) + ),--dd + input_rows AS ( + VALUES + (in_coin_pub1, + in_denom_pub_hash1, + in_h_age_commitment1, + in_denom_sig1), + (in_coin_pub2, + in_denom_pub_hash2, + in_h_age_commitment2, + in_denom_sig2) + ),--ir + ins AS ( + INSERT INTO known_coins ( + coin_pub, + denominations_serial, + age_commitment_hash, + denom_sig, + remaining_val, + remaining_frac + ) + SELECT + ir.coin_pub, + dd.denominations_serial, + ir.age_commitment_hash, + ir.denom_sig, + dd.coin_val, + dd.coin_frac + FROM input_rows ir + JOIN dd + ON dd.denom_pub_hash = ir.denom_pub_hash + ON CONFLICT DO NOTHING + RETURNING known_coin_id + ),--kc + exists AS ( + SELECT + CASE + WHEN ins.known_coin_id IS NOT NULL + THEN + FALSE + ELSE + TRUE + END AS existed, + ins.known_coin_id, + dd.denom_pub_hash, + kc.age_commitment_hash + FROM input_rows ir + LEFT JOIN ins + ON ins.coin_pub = ir.coin_pub + LEFT JOIN known_coins kc + ON kc.coin_pub = ir.coin_pub + LEFT JOIN dd + ON dd.denom_pub_hash = ir.denom_pub_hash + )--exists +SELECT + exists.existed AS existed1, + exists.known_coin_id AS known_coin_id1, + exists.denom_pub_hash AS denom_pub_hash1, + exists.age_commitment_hash AS age_commitment_hash1, + ( + SELECT exists.existed + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash2 + ) AS existed2, + ( + SELECT exists.known_coin_id + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash2 + ) AS known_coin_id2, + ( + SELECT exists.denom_pub_hash + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash2 + ) AS denom_pub_hash2, + ( + SELECT exists.age_commitment_hash + FROM exists + WHERE exists.denom_pub_hash = in_denom_pub_hash2 + )AS age_commitment_hash2 +FROM exists; + +RETURN; +END $$; + + +CREATE OR REPLACE FUNCTION exchange_do_batch1_known_coin( + IN in_coin_pub1 BYTEA, + IN in_denom_pub_hash1 BYTEA, + IN in_h_age_commitment1 BYTEA, + IN in_denom_sig1 BYTEA, + OUT existed1 BOOLEAN, + OUT known_coin_id1 INT8, + OUT denom_pub_hash1 BYTEA, + OUT age_commitment_hash1 BYTEA) +LANGUAGE plpgsql +AS $$ +BEGIN +WITH dd AS ( +SELECT + denominations_serial, + coin_val, coin_frac + FROM denominations + WHERE denom_pub_hash + IN + (in_denom_pub_hash1, + in_denom_pub_hash2) + ),--dd + input_rows AS ( + VALUES + (in_coin_pub1, + in_denom_pub_hash1, + in_h_age_commitment1, + in_denom_sig1) + ),--ir + ins AS ( + INSERT INTO known_coins ( + coin_pub, + denominations_serial, + age_commitment_hash, + denom_sig, + remaining_val, + remaining_frac + ) + SELECT + ir.coin_pub, + dd.denominations_serial, + ir.age_commitment_hash, + ir.denom_sig, + dd.coin_val, + dd.coin_frac + FROM input_rows ir + JOIN dd + ON dd.denom_pub_hash = ir.denom_pub_hash + ON CONFLICT DO NOTHING + RETURNING known_coin_id + ),--kc + exists AS ( + SELECT + CASE + WHEN ins.known_coin_id IS NOT NULL + THEN + FALSE + ELSE + TRUE + END AS existed, + ins.known_coin_id, + dd.denom_pub_hash, + kc.age_commitment_hash + FROM input_rows ir + LEFT JOIN ins + ON ins.coin_pub = ir.coin_pub + LEFT JOIN known_coins kc + ON kc.coin_pub = ir.coin_pub + LEFT JOIN dd + ON dd.denom_pub_hash = ir.denom_pub_hash + )--exists +SELECT + exists.existed AS existed1, + exists.known_coin_id AS known_coin_id1, + exists.denom_pub_hash AS denom_pub_hash1, + exists.age_commitment_hash AS age_commitment_hash1 +FROM exists; + +RETURN; +END $$; + +/*** THIS SQL CODE WORKS ***/ +/* +CREATE OR REPLACE FUNCTION exchange_do_batch2_known_coin( + IN in_coin_pub1 BYTEA, + IN in_denom_pub_hash1 TEXT, + IN in_h_age_commitment1 TEXT, + IN in_denom_sig1 TEXT, + IN in_coin_pub2 BYTEA, + IN in_denom_pub_hash2 TEXT, + IN in_h_age_commitment2 TEXT, + IN in_denom_sig2 TEXT, + OUT existed1 BOOLEAN, + OUT existed2 BOOLEAN, + OUT known_coin_id1 INT8, + OUT known_coin_id2 INT8, + OUT denom_pub_hash1 TEXT, + OUT denom_pub_hash2 TEXT, + OUT age_commitment_hash1 TEXT, + OUT age_commitment_hash2 TEXT) +LANGUAGE plpgsql +AS $$ +DECLARE + ins_values RECORD; +BEGIN + FOR i IN 1..2 LOOP + ins_values := ( + SELECT + in_coin_pub1 AS coin_pub, + in_denom_pub_hash1 AS denom_pub_hash, + in_h_age_commitment1 AS age_commitment_hash, + in_denom_sig1 AS denom_sig + WHERE i = 1 + UNION + SELECT + in_coin_pub2 AS coin_pub, + in_denom_pub_hash2 AS denom_pub_hash, + in_h_age_commitment2 AS age_commitment_hash, + in_denom_sig2 AS denom_sig + WHERE i = 2 + ); + WITH dd (denominations_serial, coin_val, coin_frac) AS ( + SELECT denominations_serial, coin_val, coin_frac + FROM denominations + WHERE denom_pub_hash = ins_values.denom_pub_hash + ), + input_rows(coin_pub) AS ( + VALUES (ins_values.coin_pub) + ), + ins AS ( + INSERT INTO known_coins ( + coin_pub, + denominations_serial, + age_commitment_hash, + denom_sig, + remaining_val, + remaining_frac + ) SELECT + input_rows.coin_pub, + dd.denominations_serial, + ins_values.age_commitment_hash, + ins_values.denom_sig, + coin_val, + coin_frac + FROM dd + CROSS JOIN input_rows + ON CONFLICT DO NOTHING + RETURNING known_coin_id, denom_pub_hash + ) + SELECT + CASE i + WHEN 1 THEN + COALESCE(ins.known_coin_id, 0) <> 0 AS existed1, + ins.known_coin_id AS known_coin_id1, + ins.denom_pub_hash AS denom_pub_hash1, + ins.age_commitment_hash AS age_commitment_hash1 + WHEN 2 THEN + COALESCE(ins.known_coin_id, 0) <> 0 AS existed2, + ins.known_coin_id AS known_coin_id2, + ins.denom_pub_hash AS denom_pub_hash2, + ins.age_commitment_hash AS age_commitment_hash2 + END + FROM ins; + END LOOP; +END; +$$;*/ diff --git a/src/exchangedb/exchange_get_ready_deposit.sql b/src/exchangedb/exchange_get_ready_deposit.sql new file mode 100644 index 000000000..4f76463fc --- /dev/null +++ b/src/exchangedb/exchange_get_ready_deposit.sql @@ -0,0 +1,60 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2014--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 +-- +CREATE OR REPLACE FUNCTION exchange_do_get_ready_deposit( + IN in_now INT8, + IN in_start_shard_now INT8, + IN in_end_shard_now INT8, + OUT out_payto_uri VARCHAR, + OUT out_merchant_pub BYTEA +) +LANGUAGE plpgsql +AS $$ +DECLARE + curs CURSOR + FOR + SELECT + coin_pub + ,deposit_serial_id + ,wire_deadline + ,shard + FROM deposits_by_ready dbr + WHERE wire_deadline <= in_now + AND shard >= in_start_shard_now + AND shard <=in_end_shard_now + ORDER BY + wire_deadline ASC + ,shard ASC + LIMIT 1; +DECLARE + i RECORD; +BEGIN +OPEN curs; +FETCH FROM curs INTO i; +SELECT + payto_uri + ,merchant_pub + INTO + out_payto_uri + ,out_merchant_pub + FROM deposits + JOIN wire_targets wt + USING (wire_target_h_payto) + WHERE + i.coin_pub = coin_pub + AND i.deposit_serial_id=deposit_serial_id; +CLOSE curs; +RETURN; +END $$; diff --git a/src/exchangedb/spi/README.md b/src/exchangedb/spi/README.md new file mode 100644 index 000000000..ec6a9016a --- /dev/null +++ b/src/exchangedb/spi/README.md @@ -0,0 +1,41 @@ + Server Programming Interface (SPI) + + +Dependencies: +============= + +These are the direct dependencies for running SPI functions : + + + +Step 1: +"postgresql-server-dev-" +-- sudo apt-get install libpq-dev postgresql-server-dev-13 + +Step 2: +To solve gssapi/gssapi.h, use the following command: +apt-get install libkrb5-dev + +Step 3: +apt-cache search openssl | grep -- -dev +apt-get install libssl-dev + +Compile: +======== +gcc -shared -o .so .c + +CALL FUNCTIONS: +=============== + +psql -c "SELECT ();" db_name + +Structure: +========== + +usr/include/postgres/ + +usr/include/postgres/13/server/ + +make +make install +psql \ No newline at end of file diff --git a/src/exchangedb/spi/own_test.bc b/src/exchangedb/spi/own_test.bc new file mode 100644 index 0000000000000000000000000000000000000000..240c78cf4b882a737e0907d58246419583dac593 GIT binary patch literal 22876 zcmdUX2~<*kAY=f9AR&f9M2i>(kVO()J9Pq`8y>TsRKXfbV|ojzRhcSL3ORATOCpsQ?h(!8zvdiXu1i(6`2{4qX{))? z_2jH}=3Wm`(m0*y1S!0{f=#w={jVO9gcj_xv#diNAH|B;L@piK$wPa{keONp=Z}kBU*CRPST_lnnn{d`+YD>@j za~_*@fqrYk#$jeF^u_u8+^y$Qr&q99u4`92Q>nL8MHO%3(_4tGys2`Mn2s0XomWh5 zD=|_B*4?L^^Y9~$<~5Qr64uxV>yg+#7?!HiZ@2W`JML5uV`{@d7fSYYi8LDFd5xqivD$gyk4R!wo7y7EBY z*ot(zlPiV|+a+_o8adV+?dmLZ!@48$RtGB{B#}#J-JYq_V|4%9Fzs=xC#2BIoj(y+ ztdNRLc`d=^49Q)^#N08@xBNE6kY%Es;puHgeFszGotqibxRdJ{<|!_jPTj&kIh>MK zO}pE{qo&+k<@aHtxh*}NYqlujJ?gb&{?C!_g_E`>jdtfv(5cjFwO{=-a~pLgi+5%L zuC1p`L1Dh9MSfYw=;Oz0f8M35UM-m`O>HjOikmLT6wNyp^G)(>cSgu-7}I(1`jA@o z24ul2f&5`D(YrS5=A+fHFfzGgYFb)ab!DYn%$tG8o4#%qo$VWQT4FHV3dS{XVMabE zX_hFRS)xB|G`2;P%;-k8M@nSV^dSM$XGQG}#{dj_1cuyzxPX|d#!s+*&t zDSk7~0la8DZd`yC`cdw4jMQo#RwEiE zq&maFEQ#T(0g2)3NU7mSJWFCQQl$n{GFxJ35l9WKC5eW%G^ydJ8&fvdDfi}HD%B$o z+j2N%i~q#BfpgwW4@`DF!Q!XYyj7FB4Ha$%GKpmJKej$}9qwgM8aC3Hp4%uvtEFUC zB01~wFr>uC<43ntM7uIVsyaPR(^HedFJr|cN0PWBBJ=h$#aqwMqz~r1JPILUl^g3B z#`19=V{++^O2b~P$uON9T%o2(M(p-98CB_3B)K8`3?=E)$|j{BNz@sRr5pA6QY-|U z_E|`oTo>iUJzaw=dxX5LG8YT%{K&k3rz{-)1sf~&Y<|O;@8yQM+#Xt$XiOg^WpeGZT*}f?ZJCl$6wD~fr4*$y-cE&UZB(7MRL>~Or4*~QQMp>B zfl-2W_z5}{!jmLXyPxk3KS7(?_hh~6O+Ud|weLl_phfKqtynRWvA9lKgfWZtT4k;l zWR{j{OO%YVV8&AHQn&A=dI47Mdr~31QSaI%6`oWG&VtN(*A9~KqMx9hB-SeB+NHq^ zRW9_>M#;5B(FloZ!Y2$f&()wAqWN@TA`o~{9s|547uwu(vV)2 z>-R=MuR_?PcKzPqdyzDxQ|@{L)C;$AP`IE67_cF|U2JTd@RCB0SsuNSn}yMnje z@k7@a<-)5{;msFYN~A5Rvl<9lDwVM~S5pYS1kPX^SJVOOtw&zh)$M!Mphqu@*EXKg?vT> z9$Wl(hCW{}ya@iL61GSMo%Mnn4lW1k`ddG_;pcnW!z8!qfEvWSV-=jPN!xrBF4R&j81ZN~aVXwM+Gk zsC3QZT*flFW^^5jP`Cw!7wHkhGNUFA)0HW;Fx6u4oEHViHspaYpUWnEAhqvhv{)kE z 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 pm^IWID?-=?>Wu}7AS6T0u_A +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils/array.h" +#include +#include "utils/numeric.h" +#include "utils/timestamp.h" +#include + +#ifdef PG_MODULE_MAGIC +PG_MODULE_MAGIC; +#endif + +typedef struct { + Datum col1; + Datum col2; +} valuest; + +void _PG_init(void); +void _PG_fini(void); + +void _PG_init(void) +{ +} + +PG_FUNCTION_INFO_V1(pg_spi_insert_int); +PG_FUNCTION_INFO_V1(pg_spi_select_from_x); +PG_FUNCTION_INFO_V1(pg_spi_select_pair_from_y); +//PG_FUNCTION_INFO_V1(pg_spi_select_with_cond); +PG_FUNCTION_INFO_V1(pg_spi_update_y); +PG_FUNCTION_INFO_V1(pg_spi_prepare_example); +PG_FUNCTION_INFO_V1(pg_spi_prepare_example_without_saveplan); +PG_FUNCTION_INFO_V1(pg_spi_prepare_insert); +PG_FUNCTION_INFO_V1(pg_spi_prepare_insert_without_saveplan); +//PG_FUNCTION_INFO_V1(pg_spi_prepare_select_with_cond); +PG_FUNCTION_INFO_V1(pg_spi_prepare_select_with_cond_without_saveplan); +PG_FUNCTION_INFO_V1(pg_spi_prepare_update); +PG_FUNCTION_INFO_V1(pg_spi_get_dep_ref_fees); +// SIMPLE SELECT +Datum +pg_spi_prepare_example(PG_FUNCTION_ARGS) +{ + static SPIPlanPtr prepared_plan; + int ret; + int64 result; + char * value; + SPIPlanPtr new_plan; + + ret=SPI_connect(); + if (ret != SPI_OK_CONNECT) { + elog(ERROR, "DB connexion failed ! \n"); + } + { + if (prepared_plan == NULL) + { + new_plan = SPI_prepare("SELECT 1 FROM joseph_test.X", 0, NULL); + prepared_plan = SPI_saveplan(new_plan); + + if (prepared_plan == NULL) + { + elog(ERROR, "FAIL TO SAVE !\n"); + } + } + + ret = SPI_execute_plan(prepared_plan, NULL, 0,false, 0); + if (ret != SPI_OK_SELECT) { + elog(ERROR, "SELECT FAILED %d !\n", ret); + } + + if (SPI_tuptable != NULL && SPI_tuptable->vals != NULL && SPI_tuptable->tupdesc != NULL) + { + value = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1); + result = atoi(value); + } + else + { + elog(ERROR, "EMPTY TABLE !\n"); + } + } + SPI_finish(); + PG_RETURN_INT64(result); +} + + + +Datum +pg_spi_prepare_example_without_saveplan(PG_FUNCTION_ARGS) +{ + int ret; + int64 result; + char * value; + SPIPlanPtr new_plan; + + ret=SPI_connect(); + if (ret != SPI_OK_CONNECT) { + elog(ERROR, "DB connexion failed ! \n"); + } + + { + new_plan = SPI_prepare("SELECT 1 FROM joseph_test.X", 0, NULL); + ret = SPI_execute_plan(new_plan, NULL, 0,false, 0); + if (ret != SPI_OK_SELECT) { + elog(ERROR, "SELECT FAILED %d !\n", ret); + } + + if (SPI_tuptable != NULL + && SPI_tuptable->vals != NULL + && SPI_tuptable->tupdesc != NULL) + { + value = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1); + result = atoi(value); + } + else + { + elog(ERROR, "EMPTY TABLE !\n"); + } + } + SPI_finish(); + PG_RETURN_INT64(result);// PG_RETURN_INT64(result); +} + + +//SELECT 1 FROM X +//V1 +Datum +pg_spi_select_from_x(PG_FUNCTION_ARGS) +{ + int ret; + char *query = "SELECT 1 FROM joseph_test.X"; + uint64 proc; + ret = SPI_connect(); + + if (ret != SPI_OK_CONNECT) + { + elog(ERROR, "SPI_connect failed"); + } + + ret = SPI_exec(query, 10); + proc = SPI_processed; + if (ret != SPI_OK_SELECT) + { + elog(ERROR, "SPI_exec failed"); + } + + SPI_finish(); + + PG_RETURN_INT64(proc); +} + +//INSERT INTO X VALUES (1) +Datum +pg_spi_insert_int(PG_FUNCTION_ARGS) +{ + int ret; + int nargs; + Oid argtypes[1]; + Datum values[1]; + char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; + + ret = SPI_connect(); + if (ret != SPI_OK_CONNECT) + { + elog(ERROR, "SPI_connect failed"); + } + + nargs = 1; + argtypes[0] = INT4OID; + values[0] = Int32GetDatum(3); + + ret = SPI_execute_with_args(query, nargs, argtypes, values, NULL, false, 0); + if (ret != SPI_OK_INSERT) + { + elog(ERROR, "SPI_execute_with_args failed"); + } + + SPI_finish(); + + PG_RETURN_VOID(); +} + + +Datum +pg_spi_prepare_insert(PG_FUNCTION_ARGS) +{ + static SPIPlanPtr prepared_plan = NULL; + int ret; + int nargs; + Oid argtypes[1]; + Datum values[1]; + char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; + SPIPlanPtr new_plan; + ret = SPI_connect(); + if (ret != SPI_OK_CONNECT) + { + elog(ERROR, "SPI_connect failed ! \n"); + } + if (prepared_plan == NULL) { + + argtypes[0] = INT4OID; + nargs = 1; + values[0] = Int32GetDatum(3); + new_plan = SPI_prepare(query, nargs, argtypes); + if (new_plan== NULL) + { + elog(ERROR, "SPI_prepare failed ! \n"); + } + prepared_plan = SPI_saveplan(new_plan); + if (prepared_plan == NULL) + { + elog(ERROR, "SPI_saveplan failed ! \n"); + } + } + + ret = SPI_execute_plan(prepared_plan, values, NULL, false, 0); + if (ret != SPI_OK_INSERT) + { + elog(ERROR, "SPI_execute_plan failed ! \n"); + } + + SPI_finish(); + + PG_RETURN_VOID(); +} +/* +Datum +pg_spi_prepare_insert_bytea(PG_FUNCTION_ARGS) +{ + static SPIPlanPtr prepared_plan = NULL; + int ret; + int nargs; + Oid argtypes[1]; + Datum values[1]; + Oid argtypes2[1]; + Datum val[1]; + char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; + SPIPlanPtr new_plan; + ret = SPI_connect(); + if (ret != SPI_OK_CONNECT) + { + elog(ERROR, "SPI_connect failed ! \n"); + } + if (prepared_plan == NULL) { + argtypes2[0] = BOOLOID; + val[0] = BoolGetDatum(); + argtypes[0] = BYTEAOID; + nargs = 1; + values[0] = Int32GetDatum(3); + new_plan = SPI_prepare(query, nargs, argtypes); + if (new_plan== NULL) + { + elog(ERROR, "SPI_prepare failed ! \n"); + } + prepared_plan = SPI_saveplan(new_plan); + if (prepared_plan == NULL) + { + elog(ERROR, "SPI_saveplan failed ! \n"); + } + } + + ret = SPI_execute_plan(prepared_plan, values, NULL, false, 0); + if (ret != SPI_OK_INSERT) + { + elog(ERROR, "SPI_execute_plan failed ! \n"); + } + + SPI_finish(); + + PG_RETURN_VOID(); +} +*/ + +Datum +pg_spi_prepare_insert_without_saveplan(PG_FUNCTION_ARGS) +{ + int ret; + int nargs; + Oid argtypes[1]; + Datum values[1]; + char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; + SPIPlanPtr new_plan; + ret = SPI_connect(); + if (ret != SPI_OK_CONNECT) + { + elog(ERROR, "SPI_connect failed"); + } + { + argtypes[0] = INT4OID; + nargs = 1; + values[0] = Int32GetDatum(3); + new_plan = SPI_prepare(query, nargs, argtypes); + if (new_plan== NULL) + { + elog(ERROR, "SPI_prepare failed"); + } + } + + ret = SPI_execute_plan(new_plan, values, NULL, false, 0); + if (ret != SPI_OK_INSERT) + { + elog(ERROR, "SPI_execute_plan failed"); + } + + SPI_finish(); + + PG_RETURN_VOID(); +} + + + + + + +/* +Datum +pg_spi_select_pair_from_y(PG_FUNCTION_ARGS) +{ + int ret; + valuest result; + bool isnull; + char *query = "SELECT 1,1 FROM joseph_test.Y"; + result.col1 = 0; + result.col2 = 0; + + if ((ret = SPI_connect()) < 0) { + fprintf(stderr, "SPI_connect returned %d\n", ret); + exit(1); + } + ret = SPI_exec(query, 0); + if (ret == SPI_OK_SELECT && SPI_processed > 0) { + int i; + SPITupleTable *tuptable = SPI_tuptable; + TupleDesc tupdesc = tuptable->tupdesc; + for (i = 0; i < SPI_processed; i++) { + HeapTuple tuple = tuptable->vals[i]; + result.col1 = SPI_getbinval(tuple, tupdesc, 1, &isnull); + result.col2 = SPI_getbinval(tuple, tupdesc, 2, &isnull); + } + } + SPI_finish(); + PG_RETURN_TEXT_P(result); +} +*/ + +//SELECT X FROM Y WHERE Z=$1 +/* +Datum +pg_spi_select_with_cond(PG_FUNCTION_ARGS) +{ + int ret; + char *query; + int nargs; + Oid argtypes[1]; + Datum values[1]; + uint64 proc; + query = "SELECT col1 FROM joseph_test.Y WHERE col2 = $1"; + + ret = SPI_connect(); + if (ret != SPI_OK_CONNECT) { + elog(ERROR, "SPI_connect failed: %d", ret); + } + nargs = 1; + argtypes[0] = INT4OID; + values[0] = Int32GetDatum(2); + + ret = SPI_execute_with_args(query, nargs, argtypes, values, NULL, false, 0); + proc = SPI_processed; + if (ret != SPI_OK_SELECT) + { + elog(ERROR, "SPI_execute_with_args failed"); + } + + SPI_finish(); + + + PG_RETURN_INT64(proc); + }*/ + +////////SELECT WITH COND +/* +Datum pg_spi_prepare_select_with_cond(PG_FUNCTION_ARGS) { + static SPIPlanPtr prepared_plan = NULL; + SPIPlanPtr new_plan; + int ret; + Datum values[1]; + uint64 proc; + int nargs; + Oid argtypes[1]; + char *query = "SELECT col1 FROM joseph_test.Y WHERE col1 = $1"; + int result = 0; + + ret = SPI_connect(); + if (ret != SPI_OK_CONNECT) + elog(ERROR, "SPI_connect failed ! \n"); + + if (prepared_plan == NULL) { + + argtypes[0] = INT4OID; + nargs = 1; + values[0] = DatumGetByteaP(SPI_getbinval(tuptable->vals[0], tupdesc, 1, &isnull)); //Value col2 + + new_plan = SPI_prepare(query, nargs, argtypes); + if (new_plan == NULL) + elog(ERROR, "SPI_prepare failed ! \n"); + + prepared_plan = SPI_saveplan(new_plan); + if (prepared_plan == NULL) + elog(ERROR, "SPI_saveplan failed ! \n"); + } + + + ret = SPI_execute_plan(prepared_plan, values, NULL, false, 0); + + if (ret != SPI_OK_SELECT) { + elog(ERROR, "SPI_execute_plan failed: %d \n", ret); + } + + proc = SPI_processed; + + if (proc > 0) { + SPITupleTable *tuptable = SPI_tuptable; + TupleDesc tupdesc = tuptable->tupdesc; + HeapTuple tuple; + int i; + + for (i = 0; i < proc; i++) { + tuple = tuptable->vals[i]; + for (int j = 1; j <= tupdesc->natts; j++) { + char * value = SPI_getvalue(tuple, tupdesc, j); + result += atoi(value); + } + } + } + SPI_finish(); + PG_RETURN_INT64(result); +} +*/ + +Datum pg_spi_prepare_select_with_cond_without_saveplan(PG_FUNCTION_ARGS) { + + SPIPlanPtr new_plan; + int ret; + Datum values[1]; + uint64 proc; + int nargs; + Oid argtypes[1]; + char *query = "SELECT col1 FROM joseph_test.Y WHERE col2 = $1"; + int result = 0; + + ret = SPI_connect(); + if (ret != SPI_OK_CONNECT) + elog(ERROR, "SPI_connect failed ! \n"); + + { + + argtypes[0] = INT4OID; + nargs = 1; + values[0] = Int32GetDatum(2); //Value col2 + + new_plan = SPI_prepare(query, nargs, argtypes); + if (new_plan == NULL) + elog(ERROR, "SPI_prepare failed ! \n"); + + } + + + ret = SPI_execute_plan(new_plan, values, NULL, false, 0); + + if (ret != SPI_OK_SELECT) { + elog(ERROR, "SPI_execute_plan failed: %d \n", ret); + } + + proc = SPI_processed; + + if (proc > 0) { + SPITupleTable *tuptable = SPI_tuptable; + TupleDesc tupdesc = tuptable->tupdesc; + HeapTuple tuple; + int i; + + for (i = 0; i < proc; i++) { + tuple = tuptable->vals[i]; + for (int j = 1; j <= tupdesc->natts; j++) { + char * value = SPI_getvalue(tuple, tupdesc, j); + result += atoi(value); + } + } + } + SPI_finish(); + PG_RETURN_INT64(result); +} + + + + +Datum +pg_spi_update_y(PG_FUNCTION_ARGS) +{ + int ret; + int nargs; + Oid argtypes[1]; + Datum values[1]; + char *query = "UPDATE joseph_test.Y SET col1 = 4 WHERE (col2 = $1)"; + + ret = SPI_connect(); + if (ret != SPI_OK_CONNECT) + { + elog(ERROR, "SPI_connect failed ! \n"); + } + + nargs = 1; + argtypes[0] = INT4OID; + values[0] = Int32GetDatum(0); + + ret = SPI_execute_with_args(query, nargs, argtypes, values, NULL, false, 0); + if (ret != SPI_OK_UPDATE) + { + elog(ERROR, "SPI_execute_with_args failed ! \n"); + } + + SPI_finish(); + + PG_RETURN_VOID(); +} + +Datum +pg_spi_prepare_update(PG_FUNCTION_ARGS) +{ + static SPIPlanPtr prepared_plan = NULL; + SPIPlanPtr new_plan; + int ret; + int nargs; + Oid argtypes[1]; + Datum values[1]; + char *query = "UPDATE joseph_test.Y SET col1 = 4 WHERE (col2 = $1)"; + + ret = SPI_connect(); + if (ret != SPI_OK_CONNECT) + { + elog(ERROR, "SPI_connect failed ! \n"); + } + + if ( prepared_plan == NULL) + { + argtypes[0] = INT4OID; + nargs = 1; + values[0] = Int32GetDatum(3); + //PREPARE + new_plan = SPI_prepare(query, nargs, argtypes); + if (new_plan == NULL) + elog(ERROR, "SPI_prepare failed ! \n"); + //SAVEPLAN + prepared_plan = SPI_saveplan(new_plan); + if(prepared_plan == NULL) + elog(ERROR, "SPI_saveplan failed ! \n"); + } + ret = SPI_execute_plan(prepared_plan, values, NULL, false, 0); + if (ret != SPI_OK_UPDATE) + elog(ERROR, "SPI_execute_plan failed ! \n"); + + SPI_finish(); + PG_RETURN_VOID(); +} +/* +Datum +pg_spi_prepare_update_without_saveplan(PG_FUNCTION_ARGS) +{}*/ +void _PG_fini(void) +{ +} + +/* + +*/ + +Datum +pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) { + /* Define plan to save */ + static SPIPlanPtr deposit_plan; + static SPIPlanPtr ref_plan; + static SPIPlanPtr fees_plan; + static SPIPlanPtr dummy_plan; + /* Define variables to update */ + Timestamp refund_deadline = PG_GETARG_TIMESTAMP(0); + bytea *merchant_pub = PG_GETARG_BYTEA_P(1); + bytea *wire_target_h_payto = PG_GETARG_BYTEA_P(2); + bytea *wtid_raw = PG_GETARG_BYTEA_P(3); + bool is_null; + /* Define variables to store the results of each SPI query */ + uint64_t sum_deposit_val = 0; + uint32_t sum_deposit_frac = 0; + uint64_t s_refund_val = 0; + uint32_t s_refund_frac = 0; + uint64_t sum_dep_fee_val = 0; + uint32_t sum_dep_fee_frac = 0; + uint64_t norm_refund_val = 0; + uint32_t norm_refund_frac = 0; + uint64_t sum_refund_val = 0; + uint32_t sum_refund_frac = 0; + /* Define variables to store the Tuptable */ + SPITupleTable *dep_res; + SPITupleTable *ref_res; + SPITupleTable *ref_by_coin_res; + SPITupleTable *norm_ref_by_coin_res; + SPITupleTable *fully_refunded_coins_res; + SPITupleTable *fees_res; + SPITupleTable *dummys_res; + /* Define variable to update */ + Datum values_refund[2]; + Datum values_deposit[3]; + Datum values_fees[2]; + Datum values_dummys[2]; + TupleDesc tupdesc; + /* Define variables to replace some tables */ + bytea *ref_by_coin_coin_pub; + int64 ref_by_coin_deposit_serial_id = 0; + bytea *norm_ref_by_coin_coin_pub; + int64_t norm_ref_by_coin_deposit_serial_id = 0; + bytea *new_dep_coin_pub = NULL; + int res = SPI_connect(); + + /* Connect to SPI */ + if (res < 0) { + elog(ERROR, "Could not connect to SPI manager"); + } + if (deposit_plan == NULL) + { + const char *dep_sql; + SPIPlanPtr new_plan; + + // Execute first query and store results in variables + dep_sql = + "UPDATE deposits SET done=TRUE " + "WHERE NOT (done OR policy_blocked) " + "AND refund_deadline=$1 " + "AND merchant_pub=$2 " + "AND wire_target_h_payto=$3 " + "RETURNING " + "deposit_serial_id," + "coin_pub," + "amount_with_fee_val," + "amount_with_fee_frac;"; + fprintf(stderr, "dep sql %d\n", 1); + new_plan = + SPI_prepare(dep_sql, 4,(Oid[]){INT8OID, BYTEAOID, BYTEAOID}); + fprintf(stderr, "dep sql %d\n", 2); + if (new_plan == NULL) + elog(ERROR, "SPI_prepare failed for dep \n"); + deposit_plan = SPI_saveplan(new_plan); + if (deposit_plan == NULL) + elog(ERROR, "SPI_saveplan failed for dep \n"); + } + fprintf(stdout, "dep sql %d\n", 3); + + values_deposit[0] = Int64GetDatum(refund_deadline); + values_deposit[1] = PointerGetDatum(merchant_pub); + values_deposit[2] = PointerGetDatum(wire_target_h_payto); + + res = SPI_execute_plan (deposit_plan, + values_deposit, + NULL, + true, + 0); + fprintf(stdout, "dep sql %d\n", 4); + if (res != SPI_OK_UPDATE) + { + elog(ERROR, "Failed to execute subquery 1 \n"); + } + // STORE TUPTABLE deposit + dep_res = SPI_tuptable; + + for (unsigned int i = 0; i < SPI_processed; i++) { + int64 dep_deposit_serial_ids = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &is_null)); + bytea *dep_coin_pub = DatumGetByteaP(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &is_null)); + int64 dep_amount_val = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 3, &is_null)); + int32 dep_amount_frac = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 4, &is_null)); + + if (is_null) + elog(ERROR, "Failed to retrive data from deposit \n"); + if (ref_plan == NULL) + { + // Execute second query with parameters from first query and store results in variables + const char * ref_sql = + "SELECT amount_with_fee_val, amount_with_fee_frac, coin_pub, deposit_serial_id " + "FROM refunds " + "WHERE coin_pub=$1 " + "AND deposit_serial_id=$2;"; + SPIPlanPtr new_plan = SPI_prepare(ref_sql, 3, (Oid[]){BYTEAOID, INT8OID}); + if (new_plan == NULL) + elog(ERROR, "SPI_prepare failed for refund\n"); + ref_plan = SPI_saveplan(new_plan); + if (ref_plan == NULL) + elog(ERROR, "SPI_saveplan failed for refund\n"); + } + values_refund[0] = PointerGetDatum(dep_coin_pub); + values_refund[1] = Int64GetDatum(dep_deposit_serial_ids); + res = SPI_execute_plan(ref_plan, + values_refund, + NULL, + false, + 0); + if (res != SPI_OK_SELECT) + elog(ERROR, "Failed to execute subquery 2\n"); + // STORE TUPTABLE refund + ref_res = SPI_tuptable; + for (unsigned int j = 0; j < SPI_processed; j++) { + int64 ref_refund_val = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 1, &is_null)); + int32 ref_refund_frac = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 2, &is_null)); + bytea *ref_coin_pub = DatumGetByteaP(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 3, &is_null)); + int64 ref_deposit_serial_id = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 4, &is_null)); + // Execute third query with parameters from second query and store results in variables + ref_by_coin_coin_pub = ref_coin_pub; + ref_by_coin_deposit_serial_id = ref_deposit_serial_id; + // LOOP TO GET THE SUM FROM REFUND BY COIN + for (unsigned int i = 0; ivals[i], SPI_tuptable->tupdesc, 1, &is_null))) + && + (ref_by_coin_deposit_serial_id == + DatumGetUInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &is_null))) + ) + { + sum_refund_val += ref_refund_val; + sum_refund_frac += ref_refund_frac; + norm_ref_by_coin_coin_pub = ref_by_coin_coin_pub; + norm_ref_by_coin_deposit_serial_id = ref_by_coin_deposit_serial_id; + } + }// END SUM CALCULATION + //NORMALIZE REFUND VAL FRAC + norm_refund_val = + (sum_refund_val + sum_refund_frac ) / 100000000; + norm_refund_frac = + sum_refund_frac % 100000000; + // Get refund values + s_refund_val += sum_refund_val; + s_refund_frac = sum_refund_frac; + }//END REFUND + if (norm_ref_by_coin_coin_pub == dep_coin_pub + && ref_by_coin_deposit_serial_id == dep_deposit_serial_ids + && norm_refund_val == dep_amount_val + && norm_refund_frac == dep_amount_frac) + { + new_dep_coin_pub = dep_coin_pub; + } + // Ensure we get the fee for each coin and not only once per denomination + if (fees_plan == NULL ) + { + const char * fees_sql = + "SELECT " + " denom.fee_deposit_val AS fee_val, " + " denom.fee_deposit_frac AS fee_frac, " + "FROM known_coins kc" + "JOIN denominations denom USING (denominations_serial) " + "WHERE kc.coin_pub = $1 AND kc.coin_pub != $2;"; + SPIPlanPtr new_plan = SPI_prepare(fees_sql, 3, (Oid[]){BYTEAOID, BYTEAOID}); + if (new_plan == NULL) + { + elog(ERROR, "SPI_prepare for fees failed ! \n"); + } + fees_plan = SPI_saveplan(new_plan); + if (fees_plan == NULL) + { + elog(ERROR, "SPI_saveplan for fees failed ! \n"); + } + } + values_fees[0] = PointerGetDatum(dep_coin_pub); + values_fees[1] = PointerGetDatum(new_dep_coin_pub); + res = SPI_execute_plan(fees_plan, values_fees, NULL, false, 0); + if (res != SPI_OK_SELECT) + elog(ERROR, "SPI_execute_plan failed for fees \n"); + fees_res = SPI_tuptable; + tupdesc = fees_res->tupdesc; + for (unsigned int i = 0; ivals[i]; + bool is_null; + uint64_t fee_val = DatumGetUInt64(SPI_getbinval(tuple, tupdesc, 1, &is_null)); + uint32_t fee_frac = DatumGetUInt32(SPI_getbinval(tuple, tupdesc, 2, &is_null)); + uint64_t fees_deposit_serial_id = DatumGetUInt64(SPI_getbinval(tuple, tupdesc, 3, &is_null)); + if (dummy_plan == NULL) + { + const char *insert_dummy_sql = + "INSERT INTO " + "aggregation_tracking(deposit_serial_id, wtid_raw)" + " VALUES ($1, $2)"; + + SPIPlanPtr new_plan = SPI_prepare(insert_dummy_sql, 2, (Oid[]){INT8OID, BYTEAOID}); + if (new_plan == NULL) + elog(ERROR, "FAILED to prepare aggregation tracking \n"); + dummy_plan = SPI_saveplan(new_plan); + if ( dummy_plan == NULL ) + elog(ERROR, "FAILED to saveplan aggregation tracking\n"); + } + values_dummys[0] = Int64GetDatum(dep_deposit_serial_ids); + values_dummys[1] = PointerGetDatum(wtid_raw); + res = SPI_execute_plan(dummy_plan, values_dummys, NULL, false, 0); + if (res != SPI_OK_INSERT) + elog(ERROR, "Failed to insert dummy\n"); + dummys_res = SPI_tuptable; + // Calculation of deposit fees for not fully refunded deposits + sum_dep_fee_val += fee_val; + sum_dep_fee_frac += fee_frac; + } + // Get deposit values + sum_deposit_val += dep_amount_val; + sum_deposit_frac += dep_amount_frac; + }//END DEPOSIT + SPI_finish(); + PG_RETURN_VOID(); +} diff --git a/src/exchangedb/spi/own_test.control b/src/exchangedb/spi/own_test.control new file mode 100644 index 000000000..4e73e207f --- /dev/null +++ b/src/exchangedb/spi/own_test.control @@ -0,0 +1,4 @@ +comment = 'Example extension for testing purposes' +default_version = '1.0' +module_pathname = '$libdir/own_test' +relocatable = true diff --git a/src/exchangedb/spi/own_test.so b/src/exchangedb/spi/own_test.so new file mode 100755 index 0000000000000000000000000000000000000000..fda70c9d0896756a7915d4b81b1cab58fbc661eb GIT binary patch literal 76824 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 Q4=GfxBtS>+EjLaF$8bghZ_>pdaw8gm^O z2I(n7Maf388AZ#))n#yHp~occ!jEay6M<2dOmTf&O)Kr zk9b$w=#A0GULWu3;dg?+LI1zMr5(p0j$XV1PpRGQCG!|nkNC0Pn7o1yy-MHx5cJ*O zr|*u^tra((cuW5Hm(LBNp7Hs+#I#rNdrpHFU2|||Dw0%>s|#m2PR1k8I*I-b+d#B$ z{|7b(aR2aIot>??K8Ne;*ev?P+nt>%Hc^JX)7iNa*B!V%fa`a-eueAf?{;<$#O}nx z_c}Xw;QA%5&*3`%eQYOS%K0^lZr+S><=iTpN?xe zY)vmu8V9{wyd0@?7cWx6<}|fU}VFUfV~dbOSqRRQk@rArlllI z+h*Ntv$Q9{)-#g1ovFLK57Y$bX4?gpZB}L@;`P-Vot^Y19~~~7kAt@xcDt4U-FaUI z){KsPumL{2hH!9@Prn1*9?;DufI&B7n{@+-sGpAGWMPtUe~~OtgJ(U%%p@FJpV$3F`i3^XC?8Z*jY+_h`s0Nio=DI za=aC})=q#J-G-PfM7M)Z(9!#vbPU5uHGy)s1ony1&ArrmiEX>GEn#z_wU10ZDrju7 z0UgKbvpEr#O4zPkV!IUVn2f~xQH*8yz=if&bZ$dlpU7S$BfagIhni)!^B&Os6LkO0 zCe5Im2|B|j#H#~z&8Qos8XY9lFMu@x#{O-eVW$~f-?>cTR~1s&4TXuvcQ_vcUwUEe z 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 literal 0 HcmV?d00001 diff --git a/src/exchangedb/spi/own_test.sql b/src/exchangedb/spi/own_test.sql new file mode 100644 index 000000000..369c56a60 --- /dev/null +++ b/src/exchangedb/spi/own_test.sql @@ -0,0 +1,216 @@ + +DROP TABLE joseph_test.X; +CREATE TABLE joseph_test.X ( + a integer +); + +INSERT INTO joseph_test.X (a) VALUES (1), (2), (3), (4), (5), (6), (7); + +DROP TABLE joseph_test.Y; +CREATE TABLE joseph_test.Y (col1 INT, col2 INT); +INSERT INTO joseph_test.Y (col1,col2) VALUES (1,2), (2,0), (0,4), (4,0), (0,6), (6,7), (7,8); + +DROP TABLE joseph_test.Z; +CREATE TABLE joseph_test.Z(col1 BYTEA); +DROP TABLE deposits; +/*CREATE TABLE deposits( + deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY + ,shard INT8 NOT NULL + ,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32) + ,known_coin_id INT8 NOT NULL + ,amount_with_fee_val INT8 NOT NULL + ,amount_with_fee_frac INT4 NOT NULL + ,wallet_timestamp INT8 NOT NULL + ,exchange_timestamp INT8 NOT NULL + ,refund_deadline INT8 NOT NULL + ,wire_deadline INT8 NOT NULL + ,merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32) + ,h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64) + ,coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64) + ,wire_salt BYTEA NOT NULL CHECK (LENGTH(wire_salt)=16) + ,wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32) + ,done BOOLEAN NOT NULL DEFAULT FALSE + ,policy_blocked BOOLEAN NOT NULL DEFAULT FALSE + ,policy_details_serial_id INT8); +*/ +--INSERT INTO deposits VALUES (); + + + +CREATE TABLE deposits( + deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY + ,shard INT8 NOT NULL + ,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32) + ,known_coin_id INT8 NOT NULL + ,amount_with_fee_val INT8 NOT NULL + ,amount_with_fee_frac INT4 NOT NULL + ,wallet_timestamp INT8 NOT NULL + ,exchange_timestamp INT8 NOT NULL + ,refund_deadline INT8 NOT NULL + ,wire_deadline INT8 NOT NULL + ,merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32) + ,h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64) + ,coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64) + ,wire_salt BYTEA NOT NULL CHECK (LENGTH(wire_salt)=16) + ,wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32) + ,done BOOLEAN NOT NULL DEFAULT FALSE + ,policy_blocked BOOLEAN NOT NULL DEFAULT FALSE + ,policy_details_serial_id INT8); + + +CREATE OR REPLACE FUNCTION pg_spi_insert_int() + RETURNS VOID + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_insert_int'; +DROP FUNCTION pg_spi_select_from_x(); +CREATE OR REPLACE FUNCTION pg_spi_select_from_x() + RETURNS INT8 + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_select_from_x'; + +/*DROP FUNCTION pg_spi_select_pair_from_y(); +CREATE OR REPLACE FUNCTION pg_spi_select_pair_from_y() + RETURNS valuest + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_select_pair_from_y'; +*/ +/*CREATE OR REPLACE FUNCTION pg_spi_select_with_cond() + RETURNS INT8 + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_select_with_cond'; +*/ +DROP FUNCTION pg_spi_update_y(); +CREATE OR REPLACE FUNCTION pg_spi_update_y() + RETURNS VOID + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_update_y'; +DROP FUNCTION pg_spi_prepare_example(); + +CREATE OR REPLACE FUNCTION pg_spi_prepare_example() + RETURNS INT8 + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_prepare_example'; + +DROP FUNCTION pg_spi_prepare_example_without_saveplan(); +CREATE OR REPLACE FUNCTION pg_spi_prepare_example_without_saveplan() + RETURNS INT8 + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_prepare_example_without_saveplan'; + +CREATE OR REPLACE FUNCTION pg_spi_prepare_insert() + RETURNS VOID + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_prepare_insert'; + +CREATE OR REPLACE FUNCTION pg_spi_prepare_insert_without_saveplan() + RETURNS VOID + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_prepare_insert_without_saveplan'; + +/*DROP FUNCTION pg_spi_prepare_select_with_cond(); +CREATE OR REPLACE FUNCTION pg_spi_prepare_select_with_cond() + RETURNS INT8 + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_prepare_select_with_cond'; +*/ +DROP FUNCTION pg_spi_prepare_select_with_cond_without_saveplan(); +CREATE OR REPLACE FUNCTION pg_spi_prepare_select_with_cond_without_saveplan() + RETURNS INT8 + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_prepare_select_with_cond_without_saveplan'; + +DROP FUNCTION pg_spi_prepare_update(); +CREATE OR REPLACE FUNCTION pg_spi_prepare_update() + RETURNS VOID + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_prepare_update'; + +DROP FUNCTION pg_spi_get_dep_ref_fees( + IN in_timestamp INT8 + ,IN merchant_pub BYTEA + ,IN wire_target_h_payto BYTEA + ,IN wtid BYTEA); +CREATE OR REPLACE FUNCTION pg_spi_get_dep_ref_fees( + IN in_timestamp INT8 + ,IN merchant_pub BYTEA + ,IN wire_target_h_payto BYTEA + ,IN wtid BYTEA +) + RETURNS VOID + LANGUAGE c COST 100 +AS '$libdir/own_test', 'pg_spi_get_dep_ref_fees'; + +CREATE OR REPLACE FUNCTION update_pg_spi_get_dep_ref_fees( + IN in_refund_deadline INT8, + IN in_merchant_pub BYTEA, + IN in_wire_target_h_payto BYTEA +) +RETURNS SETOF record +LANGUAGE plpgsql VOLATILE +AS $$ +DECLARE + +BEGIN +RETURN QUERY + UPDATE deposits + SET done = TRUE + WHERE NOT (done OR policy_blocked) + AND refund_deadline < in_refund_deadline + AND merchant_pub = in_merchant_pub + AND wire_target_h_payto = in_wire_target_h_payto + RETURNING + deposit_serial_id, + coin_pub, + amount_with_fee_val, + amount_with_fee_frac; +END $$; + +CREATE OR REPLACE FUNCTION stored_procedure_update( +IN in_number INT8 +) +RETURNS VOID +LANGUAGE plpgsql +AS $$ +BEGIN + UPDATE joseph_test.Y + SET col1 = 4 + WHERE col2 = in_number; +END $$; + +CREATE OR REPLACE FUNCTION stored_procedure_select(OUT out_value INT8) +RETURNS INT8 +LANGUAGE plpgsql +AS $$ +BEGIN + SELECT 1 + INTO out_value + FROM joseph_test.X; + RETURN; +END $$; + + +CREATE OR REPLACE FUNCTION stored_procedure_insert( +IN in_number INT8, +OUT out_number INT8) +RETURNS INT8 +LANGUAGE plpgsql +AS $$ +BEGIN + INSERT INTO joseph_test.X (a) + VALUES (in_number) + RETURNING a INTO out_number; +END $$; + +CREATE OR REPLACE FUNCTION stored_procedure_select_with_cond( +IN in_number INT8, +OUT out_number INT8 +) +RETURNS INT8 +LANGUAGE plpgsql +AS $$ +BEGIN + SELECT col1 INTO out_number + FROM joseph_test.Y + WHERE col2 = in_number; + RETURN; +END $$; diff --git a/src/exchangedb/spi/perf_own_test.c b/src/exchangedb/spi/perf_own_test.c new file mode 100644 index 000000000..92be2235e --- /dev/null +++ b/src/exchangedb/spi/perf_own_test.c @@ -0,0 +1,25 @@ +/* + This file is part of TALER + Copyright (C) 2014-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 +*/ +/** + * @file exchangedb/spi/perf_own_test.c + * @brief benchmark for 'own_test' + * @author Joseph Xu + */ +#include "exchangedb/platform.h" +#include "exchangedb/taler_exchangedb_lib.h" +#include "exchangedb/taler_json_lib.h" +#include "exchangedb/taler_exchangedb_plugin.h" +#include "own_test.sql" diff --git a/src/exchangedb/spi/pg_aggregate.c b/src/exchangedb/spi/pg_aggregate.c new file mode 100644 index 000000000..262100ce8 --- /dev/null +++ b/src/exchangedb/spi/pg_aggregate.c @@ -0,0 +1,389 @@ +#include "postgres.h" +#include "fmgr.h" +#include "utils/numeric.h" +#include "utils/builtins.h" +#include "executor/spi.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(get_deposit_summary); + +Datum get_deposit_summary(PG_FUNCTION_ARGS) +{ + + static SPIPlanPtr deposit_plan; + static SPIPlanPtr refund_plan; + static SPIPlanPtr refund_by_coin_plan; + static SPIPlanPtr norm_refund_by_coin_plan; + static SPIPlanPtr fully_refunded_by_coins_plan; + static SPIPlanPtr fees_plan; + + int shard = PG_GETARG_INT32(0); + char * sql; + char *merchant_pub = text_to_cstring(PG_GETARG_TEXT_P(1)); + char *wire_target_h_payto = text_to_cstring(PG_GETARG_TEXT_P(2)); + char *wtid_raw = text_to_cstring(PG_GETARG_TEXT_P(3)); + int refund_deadline = PG_GETARG_INT32(4); + int conn = SPI_connect(); + if (conn != SPI_OK_CONNECT) + { + elog(ERROR, "DB connexion failed ! \n"); + } + + if ( deposit_plan == NULL + || refund_plan == NULL + || refund_by_coin_plan == NULL + || norm_refund_by_coin_plan = NULL + || fully_refunded_coins_plan = NULL + || fees_plan == NULL ) + { + if (deposit_plan == NULL) + { + int nargs = 3; + Oid argtypes[3]; + argtypes[0] = INT8OID; + argtypes[1] = BYTEAOID; + argtypes[2] = BYTEAOID; + const char *dep_sql = + " UPDATE deposits" + " SET done=TRUE" + " WHERE NOT (done OR policy_blocked)" + " AND refund_deadline < $1" + " AND merchant_pub = $2" + " AND wire_target_h_payto = $3" + " RETURNING" + " deposit_serial_id" + " ,coin_pub" + " ,amount_with_fee_val AS amount_val" + " ,amount_with_fee_frac AS amount_frac"; + SPIPlanPtr new_plan = + SPI_prepare(dep_sql, 4, argtypes}); + if (new_plan == NULL) + { + elog(ERROR, "SPI_prepare for deposit failed ! \n"); + } + deposit_plan = SPI_saveplan(new_plan); + if (deposit_plan == NULL) + { + elog(ERROR, "SPI_saveplan for deposit failed ! \n"); + } + } + + Datum values[4]; + values[0] = Int64GetDatum(refund_deadline); + values[1] = CStringGetDatum(merchant_pub); + values[2] = CStringGetDatum(wire_target_h_payto); + int ret = SPI_execute_plan (deposit_plan, + values, + NULL, + true, + 0); + if (ret != SPI_OK_UPDATE) + { + elog(ERROR, "Failed to execute subquery 1\n"); + } + uint64_t *dep_deposit_serial_ids = palloc(sizeof(uint64_t) * SPI_processed); + BYTEA **dep_coin_pubs = palloc(sizeof(BYTEA *) * SPI_processed); + uint64_t *dep_amount_vals = palloc(sizeof(uint64_t) * SPI_processed); + uint32_t *dep_amount_fracs = palloc(sizeof(uint32_t) * SPI_processed); + for (unsigned int i = 0; i < SPI_processed; i++) { + HeapTuple tuple = SPI_tuptable->vals[i]; + dep_deposit_serial_ids[i] = + DatumGetInt64(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 1, &ret)); + dep_coin_pubs[i] = + DatumGetByteaP(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 2, &ret)); + dep_amount_vals[i] = + DatumGetInt64(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 3, &ret)); + dep_amount_fracs[i] = + DatumGetInt32(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 4, &ret)); + } + + + if (refund_plan == NULL) + { + const char *ref_sql = + "ref AS (" + " SELECT" + " amount_with_fee_val AS refund_val" + " ,amount_with_fee_frac AS refund_frac" + " ,coin_pub" + " ,deposit_serial_id" + " FROM refunds" + " WHERE coin_pub IN (SELECT coin_pub FROM dep)" + " AND deposit_serial_id IN (SELECT deposit_serial_id FROM dep)) "; + SPIPlanPtr new_plan = SPI_prepare(ref_sql, 0, NULL); + if (new_plan == NULL) + elog (ERROR, "SPI_prepare for refund failed ! \n"); + refund_plan = SPI_saveplan(new_plan); + if (refund_plan == NULL) + { + elog(ERROR, "SPI_saveplan for refund failed ! \n"); + } + } + + int64t_t *ref_deposit_serial_ids = palloc(sizeof(int64_t) * SPI_processed); + + int res = SPI_execute_plan (refund_plan, NULL, NULL, false, 0); + if (res != SPI_OK_SELECT) + { + elog(ERROR, "Failed to execute subquery 2\n"); + } + SPITupleTable *tuptable = SPI_tuptable; + TupleDesc tupdesc = tuptable->tupdesc; + for (unsigned int i = 0; i < SPI_processed; i++) + { + HeapTuple tuple = tuptable->vals[i]; + Datum refund_val = SPI_getbinval(tuple, tupdesc, 1, &refund_val_isnull); + Datum refund_frac = SPI_getbinval(tuple, tupdesc, 2, &refund_frac_isnull); + Datum coin_pub = SPI_getbinval(tuple, tupdesc, 3, &coin_pub_isnull); + Datum deposit_serial_id = SPI_getbinval(tuple, tupdesc, 4, &deposit_serial_id_isnull); + if (refund_val_isnull + || refund_frac_isnull + || coin_pub_isnull + || deposit_serial_id_isnull ) + { + elog(ERROR, "Failed to retrieve data from subquery 2"); + } + uint64_t refund_val_int = DatumGetUInt64(refund_val); + uint32_t refund_frac_int = DatumGetUInt32(refund_frac); + BYTEA coin_pub = DatumGetByteaP(coin_pub); + ref_deposit_serial_ids = DatumGetInt64(deposit_serial_id); + + refund *new_refund = (refund*) palloc(sizeof(refund)); + new_refund->coin_pub = coin_pub_str; + new_refund->deposit_serial_id = deposit_serial_id_int; + new_refund->amount_with_fee_val = refund_val_int; + new_refund->amount_with_fee_frac = refund_frac_int; + } + + + if (refund_by_coin_plan == NULL) + { + const char *ref_by_coin_sql = + "ref_by_coin AS (" + " SELECT" + " SUM(refund_val) AS sum_refund_val" + " ,SUM(refund_frac) AS sum_refund_frac" + " ,coin_pub" + " ,deposit_serial_id" + " FROM ref" + " GROUP BY coin_pub, deposit_serial_id) "; + SPIPlanPtr new_plan = SPI_prepare (ref_by_coin_sql, 0, NULL); + if (new_plan == NULL) + elog(ERROR, "SPI_prepare for refund by coin failed ! \n"); + refund_by_coin_plan = SPI_saveplan (new_plan); + if (refund_by_coin_plan == NULL) + elog(ERROR, "SPI_saveplan for refund failed"); + } + + + int res = SPI_execute_plan (refund_by_coin_plan, NULL, NULL, false, 0); + if (res != SPI_OK_SELECT) + { + elog(ERROR, "Failed to execute subquery 2\n"); + } + + SPITupleTable *tuptable = SPI_tuptable; + TupleDesc tupdesc = tuptable->tupdesc; + for (unsigned int i = 0; i < SPI_processed; i++) + { + HeapTuple tuple = tuptable->vals[i]; + Datum sum_refund_val = SPI_getbinval(tuple, tupdesc, 1, &refund_val_isnull); + Datum sum_refund_frac = SPI_getbinval(tuple, tupdesc, 2, &refund_frac_isnull); + Datum coin_pub = SPI_getbinval(tuple, tupdesc, 3, &coin_pub_isnull); + Datum deposit_serial_id_int = SPI_getbinval(tuple, tupdesc, 4, &deposit_serial_id_isnull); + if (refund_val_isnull + || refund_frac_isnull + || coin_pub_isnull + || deposit_serial_id_isnull ) + { + elog(ERROR, "Failed to retrieve data from subquery 2"); + } + uint64_t s_refund_val_int = DatumGetUInt64(sum_refund_val); + uint32_t s_refund_frac_int = DatumGetUInt32(sum_refund_frac); + BYTEA coin_pub = DatumGetByteaP(coin_pub); + uint64_t deposit_serial_id_int = DatumGetInt64(deposit_serial_id_int); + refund *new_refund_by_coin = (refund*) palloc(sizeof(refund)); + new_refund_by_coin->coin_pub = coin_pub; + new_refund_by_coin->deposit_serial_id = deposit_serial_id_int; + new_refund_by_coin->refund_amount_with_fee_val = s_refund_val_int; + new_refund_by_coin->refund_amount_with_fee_frac = s_refund_frac_int; + } + + + if (norm_refund_by_coin_plan == NULL) + { + const char *norm_ref_by_coin_sql = + "norm_ref_by_coin AS (" + " SELECT" + " coin_pub" + " ,deposit_serial_id" + " FROM ref_by_coin) "; + SPIPlanPtr new_plan = SPI_prepare (norm_ref_by_coin_sql, 0, NULL); + if (new_plan == NULL) + elog(ERROR, "SPI_prepare for norm refund by coin failed ! \n"); + norm_refund_by_coin_plan = SPI_saveplan(new_plan); + if (norm_refund_by_coin_plan == NULL) + elog(ERROR, "SPI_saveplan for norm refund by coin failed ! \n"); + } + + double norm_refund_val = + ((double)new_refund_by_coin->refund_amount_with_fee_val + + (double)new_refund_by_coin->refund_amount_with_fee_frac) / 100000000; + double norm_refund_frac = + (double)new_refund_by_coin->refund_amount_with_fee_frac % 100000000; + + if (fully_refunded_coins_plan == NULL) + { + const char *fully_refunded_coins_sql = + "fully_refunded_coins AS (" + " SELECT" + " dep.coin_pub" + " FROM norm_ref_by_coin norm" + " JOIN dep" + " ON (norm.coin_pub = dep.coin_pub" + " AND norm.deposit_serial_id = dep.deposit_serial_id" + " AND norm.norm_refund_val = dep.amount_val" + " AND norm.norm_refund_frac = dep.amount_frac)) "; + SPIPlanPtr new_plan = + SPI_prepare(fully_refunded_coins_sql, 0, NULL); + if (new_plan == NULL) + elog (ERROR, "SPI_prepare for fully refunded coins failed ! \n"); + fully_refunded_coins_plan = SPI_saveplan(new_plan); + if (fully_refunded_coins_plan == NULL) + elog (ERROR, "SPI_saveplan for fully refunded coins failed ! \n"); + } + + int res = SPI_execute_plan(fully_refunded_coins_sql); + if ( res != SPI_OK_SELECT) + elog(ERROR, "Failed to execute subquery 4\n"); + SPITupleTable * tuptable = SPI_tuptable; + TupleDesc tupdesc = tuptable->tupdesc; + + BYTEA coin_pub = SPI_getbinval(tuple, tupdesc, 1, &coin_pub_isnull); + if (fees_plan == NULL) + { + const char *fees_sql = + "SELECT " + " denom.fee_deposit_val AS fee_val, " + " denom.fee_deposit_frac AS fee_frac, " + " cs.deposit_serial_id " + "FROM dep cs " + "JOIN known_coins kc USING (coin_pub) " + "JOIN denominations denom USING (denominations_serial) " + "WHERE coin_pub NOT IN (SELECT coin_pub FROM fully_refunded_coins)"; + SPIPlanPtr new_plan = + SPI_prepare(fees_sql, 0, NULL); + if (new_plan == NULL) + { + elog(ERROR, "SPI_prepare for fees failed ! \n"); + } + fees_plan = SPI_saveplan(new_plan); + if (fees_plan == NULL) + { + elog(ERROR, "SPI_saveplan for fees failed ! \n"); + } + } + } + int fees_ntuples; + SPI_execute(fees_sql, true, 0); + if (SPI_result_code() != SPI_OK_SELECT) + { + ereport( + ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("deposit fee query failed: error code %d \n", SPI_result_code()))); + } + fees_ntuples = SPI_processed; + + if (fees_ntuples > 0) + { + for (i = 0; i < fees_ntuples; i++) + { + Datum fee_val_datum = + SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &fee_null); + Datum fee_frac_datum = + SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &fee_null); + Datum deposit_id_datum = + SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 3, &deposit_null); + if (!fee_null && !deposit_null) + { + int64 fee_val = DatumGetInt64(fee_val_datum); + int32 fee_frac = DatumGetInt32(fee_frac_datum); + int64 deposit_id = DatumGetInt64(deposit_id_datum); + sum_fee_value += fee_val; + sum_fee_fraction += fee_frac; + char *insert_agg_sql = + psprintf( + "INSERT INTO " + "aggregation_tracking(deposit_serial_id, wtid_raw)" + " VALUES (%lld, '%s')", + deposit_id, wtid_raw); + SPI_execute(insert_agg_sql, false, 0); + } + } + } + + TupleDesc tupdesc; + SPITupleTable *tuptable = SPI_tuptable; + HeapTuple tuple; + Datum result; + + if (tuptable == NULL || SPI_processed != 1) + { + ereport( + ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("Unexpected result \n"))); + } + tupdesc = SPI_tuptable->tupdesc; + tuple = SPI_tuptable->vals[0]; + result = HeapTupleGetDatum(tuple); + + TupleDesc result_desc = CreateTemplateTupleDesc(6, false); + TupleDescInitEntry(result_desc, (AttrNumber) 1, "sum_deposit_value", INT8OID, -1, 0); + TupleDescInitEntry(result_desc, (AttrNumber) 2, "sum_deposit_fraction", INT4OID, -1, 0); + TupleDescInitEntry(result_desc, (AttrNumber) 3, "sum_refund_value", INT8OID, -1, 0); + TupleDescInitEntry(result_desc, (AttrNumber) 4, "sum_refund_fraction", INT4OID, -1, 0); + TupleDescInitEntry(result_desc, (AttrNumber) 5, "sum_fee_value", INT8OID, -1, 0); + TupleDescInitEntry(result_desc, (AttrNumber) 6, "sum_fee_fraction", INT4OID, -1, 0); + + int ret = SPI_prepare(sql, 4, argtypes); + if (ret != SPI_OK_PREPARE) + { + elog(ERROR, "Failed to prepare statement: %s \n", sql); + } + + ret = SPI_execute_plan(plan, args, nulls, true, 0); + if (ret != SPI_OK_SELECT) + { + elog(ERROR, "Failed to execute statement: %s \n", sql); + } + + if (SPI_processed > 0) + { + HeapTuple tuple; + Datum values[6]; + bool nulls[6] = {false}; + values[0] = + SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &nulls[0]); + values[1] = + SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 2, &nulls[1]); + values[2] = + SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 3, &nulls[2]); + values[3] = + SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 4, &nulls[3]); + values[4] = + SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 5, &nulls[4]); + values[5] = + SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 6, &nulls[5]); + tuple = heap_form_tuple(result_desc, values, nulls); + PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); + } + SPI_finish(); + + PG_RETURN_NULL(); +} + + + From 6af9fd66fbfe30dba89bc530a0a272db2d23a17e Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 27 Mar 2023 08:57:29 -0400 Subject: [PATCH 07/50] New spi files --- src/exchangedb/.gitignore | 6 ++++++ src/exchangedb/spi/own_test.c | 8 ++++++++ src/exchangedb/spi/own_test.so | Bin 76824 -> 76824 bytes src/exchangedb/spi/own_test.sql | 2 +- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/exchangedb/.gitignore b/src/exchangedb/.gitignore index 264217a3d..fa833d81f 100644 --- a/src/exchangedb/.gitignore +++ b/src/exchangedb/.gitignore @@ -7,3 +7,9 @@ perf_select_refunds_by_coin-postgres exchange-0002.sql procedures.sql exchange-0003.sql +perf-exchangedb-reserves-in-insert-postgres +test-exchangedb-batch-reserves-in-insert-postgres +test-exchangedb-by-j-postgres +test-exchangedb-populate-link-data-postgres +test-exchangedb-populate-ready-deposit-postgres +test-exchangedb-populate-select-refunds-by-coin-postgres \ No newline at end of file diff --git a/src/exchangedb/spi/own_test.c b/src/exchangedb/spi/own_test.c index 04798bfa7..10af02e31 100644 --- a/src/exchangedb/spi/own_test.c +++ b/src/exchangedb/spi/own_test.c @@ -530,6 +530,11 @@ pg_spi_update_y(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } + + + + + Datum pg_spi_prepare_update(PG_FUNCTION_ARGS) { @@ -580,6 +585,9 @@ void _PG_fini(void) */ + + + Datum pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) { /* Define plan to save */ diff --git a/src/exchangedb/spi/own_test.so b/src/exchangedb/spi/own_test.so index fda70c9d0896756a7915d4b81b1cab58fbc661eb..09ae99597ba0f40cd2dcde4e7cea30fd6f6eccc8 100755 GIT binary patch delta 1618 zcmXw33rt&87(VCR4k)FhuuDsM6;|$Tq2tkQfn+czjV2i5g35$VCRgpqMBWrAkI{mQ z8aJopL_6oEWb>76PDViu#yt#1qmE<`6Ie{PB{~*DwmILMF@9$kZt{Ki{@?%KbN+MA zfBt>5hJCY!u}UV-UaY9>9{svucf7xLBDZ?oVSm}NXdQcXC3W+K6fZ5~8CEY{%Qt~b zc^DkxS;`OT zgczl4ZOM5s1I}u`x5ZkpdD&@Ma;iQvoHfjxihs`HhckeBJpp1ZKi49cZ(;FbT7m>_ zQ@CdH;o7Q;Z$o?oP_AV|e3Hf8i6ulDxi+ZYp95hV&uNuCPqBm&iIA6p0YE(%4_7@) z@WIHyS}cJ21y({euC>acr*&7y3PKtHbv^~IXY@g0VhFh-#1fIzqRL~&NDkS@L-1r6@CQY`?;xe9Cd!OQv*8! zne-FBAz=56F_Xw`I*E|a0rjXz-~>w$rB|0sNEM)_IUtVnp@2-I{LMffuG#5;2F~en z&?#QgCDT*K%qa~>7dr#pQrY>+} ziH(GwW43arX{b6GD7pfl`U)0E&oi^gu@h=Dpw5dkyugQgWa~wiC^9wR7XAm9OA(d$ zBR|^XpqKdfJy&f1GFfcW-w3!3=$j--{Hvf_G=;@ry?8y+n~!!8?A5??y?*qD`}#ES zyM387g@4&+580%ok5I2ZocMY`zj&!qf`0Ml2VE1Gp4uggxLvNB!bp=W;{Lf_#D6qh z_Y{ud(yd#KM5q&LmXsp0JA@J60rc#gk}Uej4G0TBz8(FBZ|=8Jg*WwU;IsW6^s0aG z?dDqt{OD(=1~gh2&E6SeIS;TH=Ve9As5h`Sv4aPu)+{%$bbdM{7i2ECqhd`z3VrG< zmMEs)i5YtVR9=8k2d81VB%8(VLFj{Ngj4{^TEx*D7Ar<(BX!E}qVcR^#_#UgnsQwD zo&4eOMr64=EOK28d(gO3hcs~SkO%GieSDYlm|+jv`kG;lmPPsSoP%DEHXq6{Ns^KB z*FOGYZD z=Rg19$(X~FF~cQH{${gcOY8gZ$K3tL*X|m%?fa^uJ3U&)UQVMfKAY~Nex9lLXg=Qn zF60q#6CVMO^IyP2TrvCTC%gnK@mBC>`~$O(-DUi;xq!aHO%@+jc>tWiL*PUFeeeLE z1Uq?x)kp2oBJ1Ce=an#OG7!?w2%&v9@(EcMh{0zG%P6oCVj}wEZdM?!Y46PAIyTVg=baE-cpw2mk46Dv9W~Q5u#rt_@o~BF2rs?{c9=2 zGClG-GWiKmW0pbOp-0Zf6LJYqd&Tch>5=is=O(t;vlB$MFiV}oR(Qhq!g_kaD09Jh zX2IAhj9m-HcOtA@H`F;9Mul!DiG(Br>I*`w)WvoP&4BwIGsI_^;ZJO>)N`}L?GocW z#|%rVR|us)?5{Gt&zR8EHMVIgQ$fFpdN*v*6D-fCKDn9*>x55gw}Is zZ4qjHN38}vUF%TVSjrS?Ab=Ar0@Poz!L*(KQJaH0x7TUljyf+Y`~SVic!%v=OD163yjE3Uw&?#BY@d1e$j)F!^SM5qg@BBhJ$1~B4VfS#RAl0_f64q+C^wW8nfEo}<5^WAM4c%sdV zUiB}&oqT(HIr`a|c8#i0=iV^ODrT{+%Wg5Y-oR?a4)&cYTx?(pKO2_wEQ{@^K$|~_ zg{iG9SxmhbGqwPzybz%ooJM57jl~^A=tCKVtO4BjA&zFUI59HoDRbWzjmORm=jUzB zJtX`~`MO9k8ux*S2EG>YqH$X~HE>I(7w!8!d>8WAE-%`8VV6ezQQkG>pwrPk16hew z;XNPzOp~L*q1jk|X4J?l#$5DV^rbQHwv!{tblgT~dvS0pX=(3AxwM#8_Wmwj=X!l! GI`co=5o%um diff --git a/src/exchangedb/spi/own_test.sql b/src/exchangedb/spi/own_test.sql index 369c56a60..9fe42c0a4 100644 --- a/src/exchangedb/spi/own_test.sql +++ b/src/exchangedb/spi/own_test.sql @@ -137,7 +137,7 @@ CREATE OR REPLACE FUNCTION pg_spi_get_dep_ref_fees( ,IN wtid BYTEA ) RETURNS VOID - LANGUAGE c COST 100 + LANGUAGE c VOLATILE COST 100 AS '$libdir/own_test', 'pg_spi_get_dep_ref_fees'; CREATE OR REPLACE FUNCTION update_pg_spi_get_dep_ref_fees( From 0c2d5bba55d55981f50da3f822a6f45ff5d74cd3 Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 27 Mar 2023 10:19:44 -0400 Subject: [PATCH 08/50] Remove binary files --- src/exchangedb/spi/own_test.bc | Bin 22876 -> 0 bytes src/exchangedb/spi/own_test.so | Bin 76824 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/exchangedb/spi/own_test.bc delete mode 100755 src/exchangedb/spi/own_test.so diff --git a/src/exchangedb/spi/own_test.bc b/src/exchangedb/spi/own_test.bc deleted file mode 100644 index 240c78cf4b882a737e0907d58246419583dac593..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22876 zcmdUX2~<*kAY=f9AR&f9M2i>(kVO()J9Pq`8y>TsRKXfbV|ojzRhcSL3ORATOCpsQ?h(!8zvdiXu1i(6`2{4qX{))? z_2jH}=3Wm`(m0*y1S!0{f=#w={jVO9gcj_xv#diNAH|B;L@piK$wPa{keONp=Z}kBU*CRPST_lnnn{d`+YD>@j za~_*@fqrYk#$jeF^u_u8+^y$Qr&q99u4`92Q>nL8MHO%3(_4tGys2`Mn2s0XomWh5 zD=|_B*4?L^^Y9~$<~5Qr64uxV>yg+#7?!HiZ@2W`JML5uV`{@d7fSYYi8LDFd5xqivD$gyk4R!wo7y7EBY z*ot(zlPiV|+a+_o8adV+?dmLZ!@48$RtGB{B#}#J-JYq_V|4%9Fzs=xC#2BIoj(y+ ztdNRLc`d=^49Q)^#N08@xBNE6kY%Es;puHgeFszGotqibxRdJ{<|!_jPTj&kIh>MK zO}pE{qo&+k<@aHtxh*}NYqlujJ?gb&{?C!_g_E`>jdtfv(5cjFwO{=-a~pLgi+5%L zuC1p`L1Dh9MSfYw=;Oz0f8M35UM-m`O>HjOikmLT6wNyp^G)(>cSgu-7}I(1`jA@o z24ul2f&5`D(YrS5=A+fHFfzGgYFb)ab!DYn%$tG8o4#%qo$VWQT4FHV3dS{XVMabE zX_hFRS)xB|G`2;P%;-k8M@nSV^dSM$XGQG}#{dj_1cuyzxPX|d#!s+*&t zDSk7~0la8DZd`yC`cdw4jMQo#RwEiE zq&maFEQ#T(0g2)3NU7mSJWFCQQl$n{GFxJ35l9WKC5eW%G^ydJ8&fvdDfi}HD%B$o z+j2N%i~q#BfpgwW4@`DF!Q!XYyj7FB4Ha$%GKpmJKej$}9qwgM8aC3Hp4%uvtEFUC zB01~wFr>uC<43ntM7uIVsyaPR(^HedFJr|cN0PWBBJ=h$#aqwMqz~r1JPILUl^g3B z#`19=V{++^O2b~P$uON9T%o2(M(p-98CB_3B)K8`3?=E)$|j{BNz@sRr5pA6QY-|U z_E|`oTo>iUJzaw=dxX5LG8YT%{K&k3rz{-)1sf~&Y<|O;@8yQM+#Xt$XiOg^WpeGZT*}f?ZJCl$6wD~fr4*$y-cE&UZB(7MRL>~Or4*~QQMp>B zfl-2W_z5}{!jmLXyPxk3KS7(?_hh~6O+Ud|weLl_phfKqtynRWvA9lKgfWZtT4k;l zWR{j{OO%YVV8&AHQn&A=dI47Mdr~31QSaI%6`oWG&VtN(*A9~KqMx9hB-SeB+NHq^ zRW9_>M#;5B(FloZ!Y2$f&()wAqWN@TA`o~{9s|547uwu(vV)2 z>-R=MuR_?PcKzPqdyzDxQ|@{L)C;$AP`IE67_cF|U2JTd@RCB0SsuNSn}yMnje z@k7@a<-)5{;msFYN~A5Rvl<9lDwVM~S5pYS1kPX^SJVOOtw&zh)$M!Mphqu@*EXKg?vT> z9$Wl(hCW{}ya@iL61GSMo%Mnn4lW1k`ddG_;pcnW!z8!qfEvWSV-=jPN!xrBF4R&j81ZN~aVXwM+Gk zsC3QZT*flFW^^5jP`Cw!7wHkhGNUFA)0HW;Fx6u4oEHViHspaYpUWnEAhqvhv{)kE z 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 From 9cce35d27027e1e72e44ac8965ae687d75f1c93d Mon Sep 17 00:00:00 2001 From: Joseph Date: Wed, 29 Mar 2023 11:18:20 -0400 Subject: [PATCH 09/50] New sql code for batch ensure coin known --- contrib/gana | 2 +- src/exchangedb/pg_batch_ensure_coin_known.c | 483 ++++++++++++++++++++ src/exchangedb/pg_batch_ensure_coin_known.h | 35 ++ src/exchangedb/plugin_exchangedb_postgres.c | 5 +- src/include/taler_exchangedb_plugin.h | 36 +- 5 files changed, 558 insertions(+), 3 deletions(-) create mode 100644 src/exchangedb/pg_batch_ensure_coin_known.c create mode 100644 src/exchangedb/pg_batch_ensure_coin_known.h diff --git a/contrib/gana b/contrib/gana index 3a616a04f..59de2acb7 160000 --- a/contrib/gana +++ b/contrib/gana @@ -1 +1 @@ -Subproject commit 3a616a04f1cd946bf0641b54cd71f1b858174f74 +Subproject commit 59de2acb7c716c816ed15786b5369e56c325770c diff --git a/src/exchangedb/pg_batch_ensure_coin_known.c b/src/exchangedb/pg_batch_ensure_coin_known.c new file mode 100644 index 000000000..d246e6228 --- /dev/null +++ b/src/exchangedb/pg_batch_ensure_coin_known.c @@ -0,0 +1,483 @@ +/* + 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 + */ +/** + * @file exchangedb/pg_batch_ensure_coin_known.c + * @brief Implementation of the batch_ensure_coin_known 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_batch_ensure_coin_known.h" +#include "pg_helper.h" + + + + + + +static enum TALER_EXCHANGEDB_CoinKnownStatus +insert1 (struct PosgresClosure *pg, + const struct TALER_CoinPublicInfo *coin[1], + const struct TALER_EXCHANGEDB_CoinInfo *result[1]) +{ + enum GNUNET_DB_QueryStatus qs; + bool is_denom_pub_hash_null = false; + bool is_age_hash_null = false; + PREPARE (pg, + "batch1_known_coin", + "SELECT" + " existed1 AS existed" + ",known_coin_id1 AS known_coin_id" + ",denom_pub_hash1 AS denom_hash" + ",age_commitment_hash1 AS h_age_commitment" + " FROM exchange_do_batch1_known_coin" + " ($1, $2, $3, $4);" + ); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("existed", + result[0].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + result[0].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + result[0].denom_hash), + &is_denom_pub_hash_null), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + result[0].h_age_commitment), + &is_age_hash_null), + GNUNET_PQ_result_spec_end + }; + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "batch1_known_coin", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return TALER_EXCHANGEDB_CKS_HARD_FAIL; + case GNUNET_DB_STATUS_SOFT_ERROR: + return TALER_EXCHANGEDB_CKS_SOFT_FAIL; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); /* should be impossible */ + return TALER_EXCHANGEDB_CKS_HARD_FAIL; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + if (! existed) + return TALER_EXCHANGEDB_CKS_ADDED; + break; /* continued below */ + } + + if ( (! is_denom_pub_hash_null) && + (0 != GNUNET_memcmp (&denom_hash->hash, + &coin->denom_pub_hash.hash)) ) + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + } + + if ( (! is_age_hash_null) && + (0 != GNUNET_memcmp (h_age_commitment, + &coin->h_age_commitment)) ) + { + GNUNET_break (GNUNET_is_zero (h_age_commitment)); + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + } + return TALER_EXCHANGEDB_CKS_PRESENT; +} + +static enum TALER_EXCHANGEDB_CoinKnownStatus +insert2 (struct PosgresClosure *pg, + const struct TALER_CoinPublicInfo *coin[2], + const struct TALER_EXCHANGEDB_CoinInfo *result[2]) +{ + enum GNUNET_DB_QueryStatus qs; + bool is_denom_pub_hash_null = false; + bool is_age_hash_null = false; + bool is_denom_pub_hash_null2 = false; + bool is_age_hash_null2 = false; + PREPARE (pg, + "batch2_known_coin", + "SELECT" + " existed1 AS existed" + ",known_coin_id1 AS known_coin_id" + ",denom_pub_hash1 AS denom_hash" + ",age_commitment_hash1 AS h_age_commitment" + ",existed2 AS existed2" + ",known_coin_id2 AS known_coin_id2" + ",denom_pub_hash2 AS denom_hash2" + ",age_commitment_hash2 AS h_age_commitment2" + " FROM exchange_do_batch2_known_coin" + " ($1, $2, $3, $4, $5, $6, $7, $8);" + ); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + + GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("existed", + result[0].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + result[0].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + result[0].denom_hash), + &is_denom_pub_hash_null), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + result[0].h_age_commitment[0]), + &is_age_hash_null), + GNUNET_PQ_result_spec_bool ("existed2", + result[1].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id2", + result[1].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2", + &result[1].denom_hash), + &is_denom_pub_hash_null2), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2", + &result[1].h_age_commitment), + &is_age_hash_null2), + GNUNET_PQ_result_spec_end + }; + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "batch2_known_coin", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return TALER_EXCHANGEDB_CKS_HARD_FAIL; + case GNUNET_DB_STATUS_SOFT_ERROR: + return TALER_EXCHANGEDB_CKS_SOFT_FAIL; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); /* should be impossible */ + return TALER_EXCHANGEDB_CKS_HARD_FAIL; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + if (! existed) + return TALER_EXCHANGEDB_CKS_ADDED; + break; /* continued below */ + } + + if ( (! is_denom_pub_hash_null) && + (0 != GNUNET_memcmp (&denom_hash[0].hash, + &coin[0].denom_pub_hash.hash)) ) + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + } + + if ( (! is_age_hash_null) && + (0 != GNUNET_memcmp (h_age_commitment[0], + &coin[0].h_age_commitment)) ) + { + GNUNET_break (GNUNET_is_zero (h_age_commitment[0])); + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + } + if ( (! is_denom_pub_hash_null2) && + (0 != GNUNET_memcmp (&denom_hash[1].hash, + &coin[1].denom_pub_hash.hash)) ) + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + } + + if ( (! is_age_hash_null) && + (0 != GNUNET_memcmp (h_age_commitment[1], + &coin[1].h_age_commitment)) ) + { + GNUNET_break (GNUNET_is_zero (h_age_commitment[1])); + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + } + return TALER_EXCHANGEDB_CKS_PRESENT; +} + +static enum TALER_EXCHANGEDB_CoinKnownStatus +insert4 (struct PosgresClosure *pg, + const struct TALER_CoinPublicInfo *coin[4], + const struct TALER_EXCHANGEDB_CoinInfo *result[4]) +{ + enum GNUNET_DB_QueryStatus qs; + bool is_denom_pub_hash_null = false; + bool is_age_hash_null = false; + bool is_denom_pub_hash_null2 = false; + bool is_age_hash_null2 = false; + bool is_denom_pub_hash_null3 = false; + bool is_age_hash_null3 = false; + bool is_denom_pub_hash_null4 = false; + bool is_age_hash_null4 = false; + PREPARE (pg, + "batch4_known_coin", + "SELECT" + " existed1 AS existed" + ",known_coin_id1 AS known_coin_id" + ",denom_pub_hash1 AS denom_hash" + ",age_commitment_hash1 AS h_age_commitment" + ",existed2 AS existed2" + ",known_coin_id2 AS known_coin_id2" + ",denom_pub_hash2 AS denom_hash2" + ",age_commitment_hash2 AS h_age_commitment2" + ",existed3 AS existed3" + ",known_coin_id3 AS known_coin_id3" + ",denom_pub_hash3 AS denom_hash3" + ",age_commitment_hash3 AS h_age_commitment3" + ",existed4 AS existed4" + ",known_coin_id4 AS known_coin_id4" + ",denom_pub_hash4 AS denom_hash4" + ",age_commitment_hash4 AS h_age_commitment4" + " FROM exchange_do_batch2_known_coin" + " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16);" + ); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + + GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + + GNUNET_PQ_query_param_auto_from_type (&coin[2].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[2].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[2].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[2].denom_sig), + + GNUNET_PQ_query_param_auto_from_type (&coin[3].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[3].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[3].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[3].denom_sig), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("existed", + result[0].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + result[0].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + result[0].denom_hash), + &is_denom_pub_hash_null), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + result[0].h_age_commitment), + &is_age_hash_null), + GNUNET_PQ_result_spec_bool ("existed2", + result[1].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id2", + result[1].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2", + result[1].denom_hash), + &is_denom_pub_hash_null2), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2", + result[1].h_age_commitment), + &is_age_hash_null2), + GNUNET_PQ_result_spec_bool ("existed3", + result[2].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id3", + result[2].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash3", + result[2].denom_hash), + &is_denom_pub_hash_null3), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash3", + result[2].h_age_commitment), + &is_age_hash_null3), + GNUNET_PQ_result_spec_bool ("existed4", + result[3].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id4", + result[3].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash4", + result[3].denom_hash), + &is_denom_pub_hash_null4), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash4", + result[3].h_age_commitment), + &is_age_hash_null4), + GNUNET_PQ_result_spec_end + }; + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "batch4_known_coin", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return TALER_EXCHANGEDB_CKS_HARD_FAIL; + case GNUNET_DB_STATUS_SOFT_ERROR: + return TALER_EXCHANGEDB_CKS_SOFT_FAIL; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); /* should be impossible */ + return TALER_EXCHANGEDB_CKS_HARD_FAIL; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + if (! existed) + return TALER_EXCHANGEDB_CKS_ADDED; + break; /* continued below */ + } + + if ( (! is_denom_pub_hash_null) && + (0 != GNUNET_memcmp (result[0].denom_hash.hash, + &coin[0].denom_pub_hash.hash)) ) + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + } + if ( (! is_age_hash_null) && + (0 != GNUNET_memcmp (h_age_commitment[0], + &coin[0].h_age_commitment)) ) + { + GNUNET_break (GNUNET_is_zero (h_age_commitment[0])); + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + } + + if ( (! is_denom_pub_hash_null2) && + (0 != GNUNET_memcmp (&denom_hash[1].hash, + &coin[1].denom_pub_hash.hash)) ) + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + } + if ( (! is_age_hash_null2) && + (0 != GNUNET_memcmp (h_age_commitment[1], + &coin[1].h_age_commitment)) ) + { + GNUNET_break (GNUNET_is_zero (h_age_commitment[1])); + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + } + + if ( (! is_denom_pub_hash_null3) && + (0 != GNUNET_memcmp (&denom_hash[2].hash, + &coin[2].denom_pub_hash.hash)) ) + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + } + if ( (! is_age_hash_null3) && + (0 != GNUNET_memcmp (h_age_commitment[2], + &coin[2].h_age_commitment)) ) + { + GNUNET_break (GNUNET_is_zero (h_age_commitment[2])); + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + } + + if ( (! is_denom_pub_hash_null4) && + (0 != GNUNET_memcmp (&denom_hash[3].hash, + &coin[3].denom_pub_hash.hash)) ) + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + } + if ( (! is_age_hash_null4) && + (0 != GNUNET_memcmp (h_age_commitment[3], + &coin[3].h_age_commitment)) ) + { + GNUNET_break (GNUNET_is_zero (h_age_commitment[3])); + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + } + + return TALER_EXCHANGEDB_CKS_PRESENT; +} + + + +enum TALER_EXCHANGEDB_CoinKnownStatus +TEH_PG_batch_ensure_coin_known (void *cls, + const struct + TALER_CoinPublicInfo *coin, + const struct + TALER_EXCHANGEDB_CoinInfo *result, + unsigned int coin_length, + unsigned int batch_size) +{ + struct PostgresClosure *pg = cls; + enum TALER_EXCHANGEDB_CoinKnownStatus qs1; + enum TALER_EXCHANGEDB_CoinKnownStatus qs2; + enum TALER_EXCHANGEDB_CoinKnownStatus qs4; + unsigned int i = 0; + + while (i < coin_length) + { + unsigned int bs = GNUNET_MIN (batch_size, + coin_length - i); + bs = 1; + if (bs >= 4) + { + qs4 = insert4 (pg, + &coin[i], + &result[i] + ); + i += 4; + continue; + } + switch (bs) + { + case 3: + case 2: + qs2 = insert2 (pg, + &coin[i], + &result[i] + ); + i += 2; + break; + case 1: + qs1 = insert1 (pg, + &coin[i], + &result[i] + ); + i += 1; + break; + case 0: + GNUNET_assert (0); + break; + } + } /* end while */ + return TALER_EXCHANGEDB_CKS_PRESENT; +} diff --git a/src/exchangedb/pg_batch_ensure_coin_known.h b/src/exchangedb/pg_batch_ensure_coin_known.h new file mode 100644 index 000000000..ce2b2f4ce --- /dev/null +++ b/src/exchangedb/pg_batch_ensure_coin_known.h @@ -0,0 +1,35 @@ +/* + 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 + */ +/** + * @file exchangedb/pg_batch_ensure_coin_known.h + * @brief implementation of the batch_ensure_coin_known function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_BATCH_ENSURE_COIN_KNOWN_H +#define PG_BATCH_ENSURE_COIN_KNOWN_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" +enum TALER_EXCHANGEDB_CoinKnownStatus +TEH_PG_batch_ensure_coin_known (void *cls, + const struct + TALER_CoinPublicInfo *coin, + const struct + TALER_EXCHANGEDB_CoinInfo *result, + unsigned int coin_length, + unsigned int batch_size); +#endif diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 2f3318184..7e3aa2b1e 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -216,7 +216,7 @@ #include "pg_select_aml_process.h" #include "pg_select_aml_history.h" #include "pg_insert_aml_decision.h" - +#include "pg_batch_ensure_coin_known.h" /** * Set to 1 to enable Postgres auto_explain module. This will @@ -774,6 +774,9 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) plugin->insert_aml_decision = &TEH_PG_insert_aml_decision; + plugin->batch_ensure_coin_known + = &TEH_PG_batch_ensure_coin_known; + return plugin; } diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 962bccaa2..cee8fb883 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -29,6 +29,19 @@ #include "taler_extensions_policy.h" + + +struct TALER_EXCHANGEDB_CoinInfo +{ + uint64_t *known_coin_id; + struct TALER_DenominationHashP *denom_hash; + struct TALER_AgeCommitmentHash *h_age_commitment; + bool *existed; +}; + + + + /** * Information about a denomination key. */ @@ -887,6 +900,21 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData }; + + + + + + + + + + + + + + + /** * Signature of a function called with information about the exchange's * denomination keys. @@ -4027,7 +4055,13 @@ struct TALER_EXCHANGEDB_Plugin struct TALER_DenominationHashP *denom_pub_hash, struct TALER_AgeCommitmentHash *age_hash); - + enum TALER_EXCHANGEDB_CoinKnownStatus + (*batch_ensure_coin_known)(void *cls, + const struct TALER_CoinPublicInfo *coin, + const struct + TALER_EXCHANGEDB_CoinInfo *result, + unsigned int coin_length, + unsigned int batch_size); /** * Retrieve information about the given @a coin from the database. * From 6eed8917c37ad047ee95e964cd516d82aacac473 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 31 Mar 2023 13:50:32 +0200 Subject: [PATCH 10/50] fix exchangedb build errors --- src/exchangedb/Makefile.am | 1 + src/exchangedb/pg_abort_shard.h | 5 +- src/exchangedb/pg_add_denomination_key.c | 5 +- .../pg_add_policy_fulfillment_proof.c | 2 +- src/exchangedb/pg_batch_ensure_coin_known.c | 247 +++++++++--------- src/exchangedb/pg_batch_ensure_coin_known.h | 18 +- src/exchangedb/pg_begin_revolving_shard.c | 36 +-- src/exchangedb/pg_begin_revolving_shard.h | 9 +- src/exchangedb/pg_begin_shard.h | 8 +- src/exchangedb/pg_commit.c | 2 +- src/exchangedb/pg_complete_shard.h | 5 +- src/exchangedb/pg_count_known_coins.c | 4 +- src/exchangedb/pg_count_known_coins.h | 2 +- .../pg_create_aggregation_transient.c | 22 +- .../pg_delete_aggregation_transient.c | 2 - src/exchangedb/pg_delete_shard_locks.c | 1 - src/exchangedb/pg_do_batch_withdraw.c | 5 +- src/exchangedb/pg_do_batch_withdraw_insert.c | 6 +- src/exchangedb/pg_do_deposit.c | 4 +- src/exchangedb/pg_do_melt.c | 2 +- src/exchangedb/pg_do_purse_merge.c | 2 +- src/exchangedb/pg_do_recoup.c | 1 - src/exchangedb/pg_do_recoup_refresh.h | 1 + src/exchangedb/pg_do_refund.c | 2 +- src/exchangedb/pg_do_withdraw.c | 2 - src/exchangedb/pg_drain_kyc_alert.c | 4 +- src/exchangedb/pg_drain_kyc_alert.h | 2 +- src/exchangedb/pg_ensure_coin_known.c | 8 +- src/exchangedb/pg_ensure_coin_known.h | 6 +- src/exchangedb/pg_event_listen.c | 8 +- src/exchangedb/pg_event_listen.h | 6 +- src/exchangedb/pg_event_listen_cancel.c | 3 +- src/exchangedb/pg_event_notify.c | 6 +- src/exchangedb/pg_event_notify.h | 4 +- .../pg_find_aggregation_transient.c | 2 +- src/exchangedb/pg_gc.h | 1 + src/exchangedb/pg_get_coin_denomination.c | 8 +- .../pg_get_denomination_revocation.c | 18 +- .../pg_get_denomination_revocation.h | 1 + src/exchangedb/pg_get_extension_manifest.h | 3 +- src/exchangedb/pg_get_global_fee.c | 54 ++-- src/exchangedb/pg_get_global_fee.h | 14 +- src/exchangedb/pg_get_global_fees.c | 11 +- src/exchangedb/pg_get_global_fees.h | 3 +- src/exchangedb/pg_get_known_coin.c | 10 +- src/exchangedb/pg_get_known_coin.h | 2 +- src/exchangedb/pg_get_melt.c | 10 +- src/exchangedb/pg_get_melt.h | 4 +- src/exchangedb/pg_get_old_coin_by_h_blind.c | 3 +- src/exchangedb/pg_get_old_coin_by_h_blind.h | 1 + src/exchangedb/pg_get_policy_details.c | 1 - src/exchangedb/pg_get_purse_deposit.c | 2 +- src/exchangedb/pg_get_purse_request.c | 3 +- src/exchangedb/pg_get_ready_deposit.h | 6 +- src/exchangedb/pg_get_refresh_reveal.c | 13 +- src/exchangedb/pg_get_refresh_reveal.h | 4 +- src/exchangedb/pg_get_reserve_balance.c | 4 +- src/exchangedb/pg_get_reserve_balance.h | 2 +- src/exchangedb/pg_get_reserve_by_h_blind.c | 2 +- src/exchangedb/pg_get_wire_accounts.c | 18 +- src/exchangedb/pg_get_wire_accounts.h | 2 +- src/exchangedb/pg_get_wire_fee.c | 43 ++- src/exchangedb/pg_get_wire_fee.h | 10 +- src/exchangedb/pg_get_wire_fees.c | 6 +- src/exchangedb/pg_get_wire_fees.h | 4 +- src/exchangedb/pg_get_withdraw_info.c | 8 +- src/exchangedb/pg_have_deposit2.c | 44 ++-- .../pg_insert_aggregation_tracking.c | 1 - .../pg_insert_aggregation_tracking.h | 1 - src/exchangedb/pg_insert_auditor.c | 10 +- src/exchangedb/pg_insert_auditor.h | 6 +- src/exchangedb/pg_insert_contract.c | 30 +-- .../pg_insert_denomination_revocation.c | 2 +- src/exchangedb/pg_insert_deposit.h | 2 +- src/exchangedb/pg_insert_drain_profit.c | 2 +- src/exchangedb/pg_insert_global_fee.c | 32 +-- src/exchangedb/pg_insert_global_fee.h | 12 +- src/exchangedb/pg_insert_history_request.c | 2 +- .../pg_insert_kyc_requirement_for_account.c | 2 +- .../pg_insert_kyc_requirement_for_account.h | 1 + .../pg_insert_kyc_requirement_process.c | 2 +- .../pg_insert_kyc_requirement_process.h | 1 + src/exchangedb/pg_insert_partner.h | 12 +- src/exchangedb/pg_insert_refund.c | 4 +- src/exchangedb/pg_insert_reserve_closed.c | 30 +-- src/exchangedb/pg_insert_wire.h | 4 +- src/exchangedb/pg_insert_wire_fee.c | 24 +- src/exchangedb/pg_insert_wire_fee.h | 8 +- src/exchangedb/pg_iterate_active_auditors.h | 3 +- src/exchangedb/pg_iterate_active_signkeys.h | 2 +- .../pg_iterate_auditor_denominations.h | 1 + src/exchangedb/pg_iterate_denomination_info.h | 2 +- src/exchangedb/pg_iterate_denominations.h | 2 +- .../pg_kyc_provider_account_lookup.c | 3 +- .../pg_kyc_provider_account_lookup.h | 1 + src/exchangedb/pg_lookup_auditor_status.c | 2 +- src/exchangedb/pg_lookup_denomination_key.c | 2 +- src/exchangedb/pg_lookup_global_fee_by_time.h | 1 + .../pg_lookup_kyc_process_by_account.h | 1 + src/exchangedb/pg_lookup_signing_key.c | 1 - src/exchangedb/pg_lookup_wire_timestamp.c | 4 +- src/exchangedb/pg_lookup_wire_timestamp.h | 2 +- src/exchangedb/pg_profit_drains_get_pending.c | 2 +- .../pg_profit_drains_set_finished.c | 16 +- src/exchangedb/pg_release_revolving_shard.c | 6 +- src/exchangedb/pg_release_revolving_shard.h | 4 +- src/exchangedb/pg_reserves_get.c | 4 +- src/exchangedb/pg_reserves_get_origin.c | 2 +- src/exchangedb/pg_reserves_in_insert.c | 3 +- src/exchangedb/pg_reserves_update.c | 2 +- ...select_aggregation_amounts_for_kyc_check.c | 3 - ...select_aggregation_amounts_for_kyc_check.h | 1 + .../pg_select_aggregation_transient.c | 2 +- src/exchangedb/pg_select_auditor_denom_sig.c | 1 - src/exchangedb/pg_select_contract.c | 26 +- src/exchangedb/pg_select_contract.h | 8 +- src/exchangedb/pg_select_contract_by_purse.c | 2 +- .../pg_select_deposits_missing_wire.c | 19 +- .../pg_select_deposits_missing_wire.h | 6 +- ..._select_history_requests_above_serial_id.c | 2 - .../pg_select_merge_amounts_for_kyc_check.c | 4 +- ...g_select_purse_decisions_above_serial_id.c | 1 - ...g_select_purse_decisions_above_serial_id.h | 1 + src/exchangedb/pg_select_purse_merge.c | 2 +- .../pg_select_recoup_above_serial_id.c | 4 +- ...pg_select_recoup_refresh_above_serial_id.c | 5 +- .../pg_select_refreshes_above_serial_id.c | 8 +- src/exchangedb/pg_select_refunds_by_coin.h | 1 + .../pg_select_reserves_in_above_serial_id.c | 4 +- ...t_reserves_in_above_serial_id_by_account.c | 4 +- .../pg_select_wire_out_above_serial_id.c | 3 +- ...lect_wire_out_above_serial_id_by_account.c | 3 +- ...lect_wire_out_above_serial_id_by_account.h | 1 + ...pg_select_withdraw_amounts_for_kyc_check.c | 28 +- ...pg_select_withdraw_amounts_for_kyc_check.h | 1 + .../pg_select_withdrawals_above_serial_id.c | 3 +- .../pg_select_withdrawals_above_serial_id.h | 1 + src/exchangedb/pg_set_extension_manifest.c | 4 +- src/exchangedb/pg_set_extension_manifest.h | 2 +- src/exchangedb/pg_set_purse_balance.c | 3 - src/exchangedb/pg_setup_wire_target.c | 2 +- src/exchangedb/pg_setup_wire_target.h | 2 +- src/exchangedb/pg_store_wire_transfer_out.c | 2 +- .../pg_update_aggregation_transient.c | 3 +- src/exchangedb/pg_update_auditor.c | 30 +-- src/exchangedb/pg_update_auditor.h | 8 +- src/exchangedb/pg_update_wire.c | 8 +- src/exchangedb/pg_update_wire.h | 4 +- src/exchangedb/pg_wire_prepare_data_get.c | 10 +- src/exchangedb/pg_wire_prepare_data_get.h | 7 +- src/exchangedb/pg_wire_prepare_data_insert.c | 22 +- src/exchangedb/pg_wire_prepare_data_insert.h | 5 +- .../pg_wire_prepare_data_mark_failed.c | 2 +- .../pg_wire_prepare_data_mark_failed.h | 1 + .../pg_wire_prepare_data_mark_finished.c | 10 +- .../pg_wire_prepare_data_mark_finished.h | 1 + src/exchangedb/test_exchangedb_by_j.c | 131 +++++----- src/include/taler_exchangedb_plugin.h | 33 +-- 158 files changed, 696 insertions(+), 750 deletions(-) diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am index 9757aefff..de76997cb 100644 --- a/src/exchangedb/Makefile.am +++ b/src/exchangedb/Makefile.am @@ -116,6 +116,7 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \ pg_reserves_in_insert.h pg_reserves_in_insert.c \ pg_get_withdraw_info.h pg_get_withdraw_info.c \ pg_get_age_withdraw_info.c pg_get_age_withdraw_info.h \ + pg_batch_ensure_coin_known.h pg_batch_ensure_coin_known.c \ pg_do_batch_withdraw.h pg_do_batch_withdraw.c \ pg_get_policy_details.h pg_get_policy_details.c \ pg_persist_policy_details.h pg_persist_policy_details.c \ diff --git a/src/exchangedb/pg_abort_shard.h b/src/exchangedb/pg_abort_shard.h index 070b48dab..e52ace5f6 100644 --- a/src/exchangedb/pg_abort_shard.h +++ b/src/exchangedb/pg_abort_shard.h @@ -36,7 +36,8 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_abort_shard (void *cls, - const char *job_name, - uint64_t start_row, + const char *job_name, + uint64_t start_row, uint64_t end_row); + #endif diff --git a/src/exchangedb/pg_add_denomination_key.c b/src/exchangedb/pg_add_denomination_key.c index e115a44ec..fa6d92ed6 100644 --- a/src/exchangedb/pg_add_denomination_key.c +++ b/src/exchangedb/pg_add_denomination_key.c @@ -56,8 +56,8 @@ TEH_PG_add_denomination_key ( GNUNET_assert (GNUNET_YES == TALER_denom_fee_check_currency (meta->value.currency, &meta->fees)); - /* Used in #postgres_insert_denomination_info() and - #postgres_add_denomination_key() */ + /* Used in #postgres_insert_denomination_info() and + #postgres_add_denomination_key() */ PREPARE (pg, "denomination_insert", "INSERT INTO denominations " @@ -86,4 +86,3 @@ TEH_PG_add_denomination_key ( "denomination_insert", iparams); } - diff --git a/src/exchangedb/pg_add_policy_fulfillment_proof.c b/src/exchangedb/pg_add_policy_fulfillment_proof.c index bb06206ae..103de7ad2 100644 --- a/src/exchangedb/pg_add_policy_fulfillment_proof.c +++ b/src/exchangedb/pg_add_policy_fulfillment_proof.c @@ -94,7 +94,7 @@ TEH_PG_add_policy_fulfillment_proof ( GNUNET_PQ_result_spec_end }; - + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "insert_proof_into_policy_fulfillments", params, diff --git a/src/exchangedb/pg_batch_ensure_coin_known.c b/src/exchangedb/pg_batch_ensure_coin_known.c index d246e6228..e49813064 100644 --- a/src/exchangedb/pg_batch_ensure_coin_known.c +++ b/src/exchangedb/pg_batch_ensure_coin_known.c @@ -26,14 +26,10 @@ #include "pg_helper.h" - - - - -static enum TALER_EXCHANGEDB_CoinKnownStatus -insert1 (struct PosgresClosure *pg, - const struct TALER_CoinPublicInfo *coin[1], - const struct TALER_EXCHANGEDB_CoinInfo *result[1]) +static enum GNUNET_DB_QueryStatus +insert1 (struct PostgresClosure *pg, + const struct TALER_CoinPublicInfo coin[1], + struct TALER_EXCHANGEDB_CoinInfo result[1]) { enum GNUNET_DB_QueryStatus qs; bool is_denom_pub_hash_null = false; @@ -57,16 +53,16 @@ insert1 (struct PosgresClosure *pg, }; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_bool ("existed", - result[0].existed), + &result[0].existed), GNUNET_PQ_result_spec_uint64 ("known_coin_id", - result[0].known_coin_id), + &result[0].known_coin_id), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - result[0].denom_hash), + &result[0].denom_hash), &is_denom_pub_hash_null), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - result[0].h_age_commitment), + &result[0].h_age_commitment), &is_age_hash_null), GNUNET_PQ_result_spec_end }; @@ -79,47 +75,47 @@ insert1 (struct PosgresClosure *pg, { case GNUNET_DB_STATUS_HARD_ERROR: GNUNET_break (0); - return TALER_EXCHANGEDB_CKS_HARD_FAIL; + return qs; case GNUNET_DB_STATUS_SOFT_ERROR: - return TALER_EXCHANGEDB_CKS_SOFT_FAIL; + return qs; case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: GNUNET_break (0); /* should be impossible */ - return TALER_EXCHANGEDB_CKS_HARD_FAIL; + return GNUNET_DB_STATUS_HARD_ERROR; case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - if (! existed) - return TALER_EXCHANGEDB_CKS_ADDED; break; /* continued below */ } if ( (! is_denom_pub_hash_null) && - (0 != GNUNET_memcmp (&denom_hash->hash, - &coin->denom_pub_hash.hash)) ) + (0 != GNUNET_memcmp (&result[0].denom_hash, + &coin->denom_pub_hash)) ) { GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + result[0].denom_conflict = true; } if ( (! is_age_hash_null) && - (0 != GNUNET_memcmp (h_age_commitment, + (0 != GNUNET_memcmp (&result[0].h_age_commitment, &coin->h_age_commitment)) ) { - GNUNET_break (GNUNET_is_zero (h_age_commitment)); + GNUNET_break (GNUNET_is_zero (&result[0].h_age_commitment)); GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + result[0].age_conflict = true; } - return TALER_EXCHANGEDB_CKS_PRESENT; + return qs; } -static enum TALER_EXCHANGEDB_CoinKnownStatus -insert2 (struct PosgresClosure *pg, - const struct TALER_CoinPublicInfo *coin[2], - const struct TALER_EXCHANGEDB_CoinInfo *result[2]) + +static enum GNUNET_DB_QueryStatus +insert2 (struct PostgresClosure *pg, + const struct TALER_CoinPublicInfo coin[2], + struct TALER_EXCHANGEDB_CoinInfo result[2]) { enum GNUNET_DB_QueryStatus qs; bool is_denom_pub_hash_null = false; bool is_age_hash_null = false; bool is_denom_pub_hash_null2 = false; bool is_age_hash_null2 = false; + PREPARE (pg, "batch2_known_coin", "SELECT" @@ -148,21 +144,21 @@ insert2 (struct PosgresClosure *pg, }; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_bool ("existed", - result[0].existed), + &result[0].existed), GNUNET_PQ_result_spec_uint64 ("known_coin_id", - result[0].known_coin_id), + &result[0].known_coin_id), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - result[0].denom_hash), + &result[0].denom_hash), &is_denom_pub_hash_null), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - result[0].h_age_commitment[0]), + &result[0].h_age_commitment), &is_age_hash_null), GNUNET_PQ_result_spec_bool ("existed2", - result[1].existed), + &result[1].existed), GNUNET_PQ_result_spec_uint64 ("known_coin_id2", - result[1].known_coin_id), + &result[1].known_coin_id), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2", &result[1].denom_hash), @@ -182,57 +178,56 @@ insert2 (struct PosgresClosure *pg, { case GNUNET_DB_STATUS_HARD_ERROR: GNUNET_break (0); - return TALER_EXCHANGEDB_CKS_HARD_FAIL; + return qs; case GNUNET_DB_STATUS_SOFT_ERROR: - return TALER_EXCHANGEDB_CKS_SOFT_FAIL; + return qs; case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: GNUNET_break (0); /* should be impossible */ - return TALER_EXCHANGEDB_CKS_HARD_FAIL; + return GNUNET_DB_STATUS_HARD_ERROR; case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - if (! existed) - return TALER_EXCHANGEDB_CKS_ADDED; break; /* continued below */ } if ( (! is_denom_pub_hash_null) && - (0 != GNUNET_memcmp (&denom_hash[0].hash, - &coin[0].denom_pub_hash.hash)) ) + (0 != GNUNET_memcmp (&result[0].denom_hash, + &coin[0].denom_pub_hash)) ) { GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + result[0].denom_conflict = true; } if ( (! is_age_hash_null) && - (0 != GNUNET_memcmp (h_age_commitment[0], + (0 != GNUNET_memcmp (&result[0].h_age_commitment, &coin[0].h_age_commitment)) ) { - GNUNET_break (GNUNET_is_zero (h_age_commitment[0])); + GNUNET_break (GNUNET_is_zero (&result[0].h_age_commitment)); GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + result[0].age_conflict = true; } if ( (! is_denom_pub_hash_null2) && - (0 != GNUNET_memcmp (&denom_hash[1].hash, - &coin[1].denom_pub_hash.hash)) ) + (0 != GNUNET_memcmp (&result[1].denom_hash, + &coin[1].denom_pub_hash)) ) { GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + result[1].denom_conflict = true; } if ( (! is_age_hash_null) && - (0 != GNUNET_memcmp (h_age_commitment[1], + (0 != GNUNET_memcmp (&result[1].h_age_commitment, &coin[1].h_age_commitment)) ) { - GNUNET_break (GNUNET_is_zero (h_age_commitment[1])); + GNUNET_break (GNUNET_is_zero (&result[1].h_age_commitment)); GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + result[1].age_conflict = true; } - return TALER_EXCHANGEDB_CKS_PRESENT; + return qs; } -static enum TALER_EXCHANGEDB_CoinKnownStatus -insert4 (struct PosgresClosure *pg, - const struct TALER_CoinPublicInfo *coin[4], - const struct TALER_EXCHANGEDB_CoinInfo *result[4]) + +static enum GNUNET_DB_QueryStatus +insert4 (struct PostgresClosure *pg, + const struct TALER_CoinPublicInfo coin[4], + struct TALER_EXCHANGEDB_CoinInfo result[4]) { enum GNUNET_DB_QueryStatus qs; bool is_denom_pub_hash_null = false; @@ -289,52 +284,52 @@ insert4 (struct PosgresClosure *pg, }; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_bool ("existed", - result[0].existed), + &result[0].existed), GNUNET_PQ_result_spec_uint64 ("known_coin_id", - result[0].known_coin_id), + &result[0].known_coin_id), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - result[0].denom_hash), + &result[0].denom_hash), &is_denom_pub_hash_null), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - result[0].h_age_commitment), + &result[0].h_age_commitment), &is_age_hash_null), GNUNET_PQ_result_spec_bool ("existed2", - result[1].existed), + &result[1].existed), GNUNET_PQ_result_spec_uint64 ("known_coin_id2", - result[1].known_coin_id), + &result[1].known_coin_id), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2", - result[1].denom_hash), + &result[1].denom_hash), &is_denom_pub_hash_null2), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2", - result[1].h_age_commitment), + &result[1].h_age_commitment), &is_age_hash_null2), GNUNET_PQ_result_spec_bool ("existed3", - result[2].existed), + &result[2].existed), GNUNET_PQ_result_spec_uint64 ("known_coin_id3", - result[2].known_coin_id), + &result[2].known_coin_id), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash3", - result[2].denom_hash), + &result[2].denom_hash), &is_denom_pub_hash_null3), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash3", - result[2].h_age_commitment), + &result[2].h_age_commitment), &is_age_hash_null3), GNUNET_PQ_result_spec_bool ("existed4", - result[3].existed), + &result[3].existed), GNUNET_PQ_result_spec_uint64 ("known_coin_id4", - result[3].known_coin_id), + &result[3].known_coin_id), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash4", - result[3].denom_hash), + &result[3].denom_hash), &is_denom_pub_hash_null4), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash4", - result[3].h_age_commitment), + &result[3].h_age_commitment), &is_age_hash_null4), GNUNET_PQ_result_spec_end }; @@ -347,113 +342,105 @@ insert4 (struct PosgresClosure *pg, { case GNUNET_DB_STATUS_HARD_ERROR: GNUNET_break (0); - return TALER_EXCHANGEDB_CKS_HARD_FAIL; + return qs; case GNUNET_DB_STATUS_SOFT_ERROR: - return TALER_EXCHANGEDB_CKS_SOFT_FAIL; + return qs; case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: GNUNET_break (0); /* should be impossible */ - return TALER_EXCHANGEDB_CKS_HARD_FAIL; + return GNUNET_DB_STATUS_HARD_ERROR; case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - if (! existed) - return TALER_EXCHANGEDB_CKS_ADDED; break; /* continued below */ } if ( (! is_denom_pub_hash_null) && - (0 != GNUNET_memcmp (result[0].denom_hash.hash, - &coin[0].denom_pub_hash.hash)) ) + (0 != GNUNET_memcmp (&result[0].denom_hash, + &coin[0].denom_pub_hash)) ) { GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + result[0].denom_conflict = true; } if ( (! is_age_hash_null) && - (0 != GNUNET_memcmp (h_age_commitment[0], + (0 != GNUNET_memcmp (&result[0].h_age_commitment, &coin[0].h_age_commitment)) ) { - GNUNET_break (GNUNET_is_zero (h_age_commitment[0])); + GNUNET_break (GNUNET_is_zero (&result[0].h_age_commitment)); GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + result[0].age_conflict = true; } if ( (! is_denom_pub_hash_null2) && - (0 != GNUNET_memcmp (&denom_hash[1].hash, - &coin[1].denom_pub_hash.hash)) ) + (0 != GNUNET_memcmp (&result[1].denom_hash, + &coin[1].denom_pub_hash)) ) { GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + result[1].denom_conflict = true; } if ( (! is_age_hash_null2) && - (0 != GNUNET_memcmp (h_age_commitment[1], + (0 != GNUNET_memcmp (&result[1].h_age_commitment, &coin[1].h_age_commitment)) ) { - GNUNET_break (GNUNET_is_zero (h_age_commitment[1])); + GNUNET_break (GNUNET_is_zero (&result[1].h_age_commitment)); GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + result[1].age_conflict = true; } if ( (! is_denom_pub_hash_null3) && - (0 != GNUNET_memcmp (&denom_hash[2].hash, - &coin[2].denom_pub_hash.hash)) ) + (0 != GNUNET_memcmp (&result[2].denom_hash, + &coin[2].denom_pub_hash)) ) { GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + result[2].denom_conflict = true; } if ( (! is_age_hash_null3) && - (0 != GNUNET_memcmp (h_age_commitment[2], + (0 != GNUNET_memcmp (&result[2].h_age_commitment, &coin[2].h_age_commitment)) ) { - GNUNET_break (GNUNET_is_zero (h_age_commitment[2])); + GNUNET_break (GNUNET_is_zero (&result[2].h_age_commitment)); GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + result[2].age_conflict = true; } if ( (! is_denom_pub_hash_null4) && - (0 != GNUNET_memcmp (&denom_hash[3].hash, - &coin[3].denom_pub_hash.hash)) ) + (0 != GNUNET_memcmp (&result[3].denom_hash, + &coin[3].denom_pub_hash)) ) { GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + result[3].denom_conflict = true; } if ( (! is_age_hash_null4) && - (0 != GNUNET_memcmp (h_age_commitment[3], + (0 != GNUNET_memcmp (&result[3].h_age_commitment, &coin[3].h_age_commitment)) ) { - GNUNET_break (GNUNET_is_zero (h_age_commitment[3])); + GNUNET_break (GNUNET_is_zero (&result[3].h_age_commitment)); GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_AGE_CONFLICT; + result[3].age_conflict = true; } - - return TALER_EXCHANGEDB_CKS_PRESENT; + return qs; } - -enum TALER_EXCHANGEDB_CoinKnownStatus -TEH_PG_batch_ensure_coin_known (void *cls, - const struct - TALER_CoinPublicInfo *coin, - const struct - TALER_EXCHANGEDB_CoinInfo *result, - unsigned int coin_length, - unsigned int batch_size) +enum GNUNET_DB_QueryStatus +TEH_PG_batch_ensure_coin_known ( + void *cls, + const struct TALER_CoinPublicInfo *coin, + struct TALER_EXCHANGEDB_CoinInfo *result, + unsigned int coin_length, + unsigned int batch_size) { struct PostgresClosure *pg = cls; - enum TALER_EXCHANGEDB_CoinKnownStatus qs1; - enum TALER_EXCHANGEDB_CoinKnownStatus qs2; - enum TALER_EXCHANGEDB_CoinKnownStatus qs4; + enum GNUNET_DB_QueryStatus qs = 0; unsigned int i = 0; - while (i < coin_length) + while ( (qs >= 0) && + (i < coin_length) ) { unsigned int bs = GNUNET_MIN (batch_size, coin_length - i); - bs = 1; if (bs >= 4) { - qs4 = insert4 (pg, - &coin[i], - &result[i] - ); + qs = insert4 (pg, + &coin[i], + &result[i]); i += 4; continue; } @@ -461,17 +448,15 @@ TEH_PG_batch_ensure_coin_known (void *cls, { case 3: case 2: - qs2 = insert2 (pg, - &coin[i], - &result[i] - ); + qs = insert2 (pg, + &coin[i], + &result[i]); i += 2; break; case 1: - qs1 = insert1 (pg, - &coin[i], - &result[i] - ); + qs = insert1 (pg, + &coin[i], + &result[i]); i += 1; break; case 0: @@ -479,5 +464,7 @@ TEH_PG_batch_ensure_coin_known (void *cls, break; } } /* end while */ - return TALER_EXCHANGEDB_CKS_PRESENT; + if (qs < 0) + return qs; + return i; } diff --git a/src/exchangedb/pg_batch_ensure_coin_known.h b/src/exchangedb/pg_batch_ensure_coin_known.h index ce2b2f4ce..a80f9d88b 100644 --- a/src/exchangedb/pg_batch_ensure_coin_known.h +++ b/src/exchangedb/pg_batch_ensure_coin_known.h @@ -24,12 +24,14 @@ #include "taler_util.h" #include "taler_json_lib.h" #include "taler_exchangedb_plugin.h" -enum TALER_EXCHANGEDB_CoinKnownStatus -TEH_PG_batch_ensure_coin_known (void *cls, - const struct - TALER_CoinPublicInfo *coin, - const struct - TALER_EXCHANGEDB_CoinInfo *result, - unsigned int coin_length, - unsigned int batch_size); + + +enum GNUNET_DB_QueryStatus +TEH_PG_batch_ensure_coin_known ( + void *cls, + const struct TALER_CoinPublicInfo *coin, + struct TALER_EXCHANGEDB_CoinInfo *result, + unsigned int coin_length, + unsigned int batch_size); + #endif diff --git a/src/exchangedb/pg_begin_revolving_shard.c b/src/exchangedb/pg_begin_revolving_shard.c index 888d7fd20..86cdf80fd 100644 --- a/src/exchangedb/pg_begin_revolving_shard.c +++ b/src/exchangedb/pg_begin_revolving_shard.c @@ -30,11 +30,11 @@ enum GNUNET_DB_QueryStatus TEH_PG_begin_revolving_shard (void *cls, - const char *job_name, - uint32_t shard_size, - uint32_t shard_limit, - uint32_t *start_row, - uint32_t *end_row) + const char *job_name, + uint32_t shard_size, + uint32_t shard_limit, + uint32_t *start_row, + uint32_t *end_row) { struct PostgresClosure *pg = cls; @@ -45,7 +45,7 @@ TEH_PG_begin_revolving_shard (void *cls, { if (GNUNET_OK != TEH_PG_start (pg, - "begin_revolving_shard")) + "begin_revolving_shard")) { GNUNET_break (0); return GNUNET_DB_STATUS_HARD_ERROR; @@ -64,15 +64,15 @@ TEH_PG_begin_revolving_shard (void *cls, &last_end), GNUNET_PQ_result_spec_end }; - /* Used in #postgres_begin_revolving_shard() */ - PREPARE(pg, - "get_last_revolving_shard", - "SELECT" - " end_row" - " FROM revolving_work_shards" - " WHERE job_name=$1" - " ORDER BY end_row DESC" - " LIMIT 1;"); + /* Used in #postgres_begin_revolving_shard() */ + PREPARE (pg, + "get_last_revolving_shard", + "SELECT" + " end_row" + " FROM revolving_work_shards" + " WHERE job_name=$1" + " ORDER BY end_row DESC" + " LIMIT 1;"); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "get_last_revolving_shard", params, @@ -116,7 +116,7 @@ TEH_PG_begin_revolving_shard (void *cls, (unsigned long long) *start_row, (unsigned long long) *end_row); - /* Used in #postgres_claim_revolving_shard() */ + /* Used in #postgres_claim_revolving_shard() */ PREPARE (pg, "create_revolving_shard", "INSERT INTO revolving_work_shards" @@ -164,7 +164,7 @@ TEH_PG_begin_revolving_shard (void *cls, end_row), GNUNET_PQ_result_spec_end }; - /* Used in #postgres_begin_revolving_shard() */ + /* Used in #postgres_begin_revolving_shard() */ PREPARE (pg, "get_open_revolving_shard", "SELECT" @@ -206,7 +206,7 @@ TEH_PG_begin_revolving_shard (void *cls, now = GNUNET_TIME_timestamp_get (); - /* Used in #postgres_begin_revolving_shard() */ + /* Used in #postgres_begin_revolving_shard() */ PREPARE (pg, "reclaim_revolving_shard", "UPDATE revolving_work_shards" diff --git a/src/exchangedb/pg_begin_revolving_shard.h b/src/exchangedb/pg_begin_revolving_shard.h index bdbca4f11..0755f886b 100644 --- a/src/exchangedb/pg_begin_revolving_shard.h +++ b/src/exchangedb/pg_begin_revolving_shard.h @@ -40,9 +40,10 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_begin_revolving_shard (void *cls, - const char *job_name, - uint32_t shard_size, - uint32_t shard_limit, - uint32_t *start_row, + const char *job_name, + uint32_t shard_size, + uint32_t shard_limit, + uint32_t *start_row, uint32_t *end_row); + #endif diff --git a/src/exchangedb/pg_begin_shard.h b/src/exchangedb/pg_begin_shard.h index 39bd834e9..16f19491d 100644 --- a/src/exchangedb/pg_begin_shard.h +++ b/src/exchangedb/pg_begin_shard.h @@ -38,10 +38,10 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_begin_shard (void *cls, - const char *job_name, - struct GNUNET_TIME_Relative delay, - uint64_t shard_size, - uint64_t *start_row, + const char *job_name, + struct GNUNET_TIME_Relative delay, + uint64_t shard_size, + uint64_t *start_row, uint64_t *end_row); #endif diff --git a/src/exchangedb/pg_commit.c b/src/exchangedb/pg_commit.c index f1e61ee34..8c4f87c90 100644 --- a/src/exchangedb/pg_commit.c +++ b/src/exchangedb/pg_commit.c @@ -45,7 +45,7 @@ TEH_PG_commit (void *cls) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Committing transaction `%s'\n", pg->transaction_name); - /* used in #postgres_commit */ + /* used in #postgres_commit */ PREPARE (pg, "do_commit", "COMMIT"); diff --git a/src/exchangedb/pg_complete_shard.h b/src/exchangedb/pg_complete_shard.h index 8693f402e..f06c0483b 100644 --- a/src/exchangedb/pg_complete_shard.h +++ b/src/exchangedb/pg_complete_shard.h @@ -36,7 +36,8 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_complete_shard (void *cls, - const char *job_name, - uint64_t start_row, + const char *job_name, + uint64_t start_row, uint64_t end_row); + #endif diff --git a/src/exchangedb/pg_count_known_coins.c b/src/exchangedb/pg_count_known_coins.c index 28c4612fc..872965ac9 100644 --- a/src/exchangedb/pg_count_known_coins.c +++ b/src/exchangedb/pg_count_known_coins.c @@ -27,8 +27,8 @@ long long TEH_PG_count_known_coins (void *cls, - const struct - TALER_DenominationHashP *denom_pub_hash) + const struct + TALER_DenominationHashP *denom_pub_hash) { struct PostgresClosure *pg = cls; uint64_t count; diff --git a/src/exchangedb/pg_count_known_coins.h b/src/exchangedb/pg_count_known_coins.h index f5dd4f27f..69f07bdf4 100644 --- a/src/exchangedb/pg_count_known_coins.h +++ b/src/exchangedb/pg_count_known_coins.h @@ -33,7 +33,7 @@ */ long long TEH_PG_count_known_coins (void *cls, - const struct + const struct TALER_DenominationHashP *denom_pub_hash); #endif diff --git a/src/exchangedb/pg_create_aggregation_transient.c b/src/exchangedb/pg_create_aggregation_transient.c index 4ced9da04..80fba8bf4 100644 --- a/src/exchangedb/pg_create_aggregation_transient.c +++ b/src/exchangedb/pg_create_aggregation_transient.c @@ -46,18 +46,18 @@ TEH_PG_create_aggregation_transient ( GNUNET_PQ_query_param_auto_from_type (wtid), GNUNET_PQ_query_param_end }; - /* Used in #postgres_create_aggregation_transient() */ + /* Used in #postgres_create_aggregation_transient() */ PREPARE (pg, - "create_aggregation_transient", - "INSERT INTO aggregation_transient" - " (amount_val" - " ,amount_frac" - " ,merchant_pub" - " ,wire_target_h_payto" - " ,legitimization_requirement_serial_id" - " ,exchange_account_section" - " ,wtid_raw)" - " VALUES ($1, $2, $3, $4, $5, $6, $7);"); + "create_aggregation_transient", + "INSERT INTO aggregation_transient" + " (amount_val" + " ,amount_frac" + " ,merchant_pub" + " ,wire_target_h_payto" + " ,legitimization_requirement_serial_id" + " ,exchange_account_section" + " ,wtid_raw)" + " VALUES ($1, $2, $3, $4, $5, $6, $7);"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "create_aggregation_transient", params); diff --git a/src/exchangedb/pg_delete_aggregation_transient.c b/src/exchangedb/pg_delete_aggregation_transient.c index d0622c0f7..63c5c0a23 100644 --- a/src/exchangedb/pg_delete_aggregation_transient.c +++ b/src/exchangedb/pg_delete_aggregation_transient.c @@ -48,5 +48,3 @@ TEH_PG_delete_aggregation_transient ( "delete_aggregation_transient", params); } - - diff --git a/src/exchangedb/pg_delete_shard_locks.c b/src/exchangedb/pg_delete_shard_locks.c index e55cf25ff..dbb0f29ac 100644 --- a/src/exchangedb/pg_delete_shard_locks.c +++ b/src/exchangedb/pg_delete_shard_locks.c @@ -39,4 +39,3 @@ TEH_PG_delete_shard_locks (void *cls) return GNUNET_PQ_exec_statements (pg->conn, es); } - diff --git a/src/exchangedb/pg_do_batch_withdraw.c b/src/exchangedb/pg_do_batch_withdraw.c index 8ef1be268..3dee20d22 100644 --- a/src/exchangedb/pg_do_batch_withdraw.c +++ b/src/exchangedb/pg_do_batch_withdraw.c @@ -60,8 +60,8 @@ TEH_PG_do_batch_withdraw ( pg->legal_reserve_expiration_time)); - /* Used in #postgres_do_batch_withdraw() to - update the reserve balance and check its status */ + /* Used in #postgres_do_batch_withdraw() to + update the reserve balance and check its status */ PREPARE (pg, "call_batch_withdraw", "SELECT " @@ -75,4 +75,3 @@ TEH_PG_do_batch_withdraw ( params, rs); } - diff --git a/src/exchangedb/pg_do_batch_withdraw_insert.c b/src/exchangedb/pg_do_batch_withdraw_insert.c index 8d3aac688..8be18f7cc 100644 --- a/src/exchangedb/pg_do_batch_withdraw_insert.c +++ b/src/exchangedb/pg_do_batch_withdraw_insert.c @@ -59,9 +59,9 @@ TEH_PG_do_batch_withdraw_insert ( nonce_reuse), GNUNET_PQ_result_spec_end }; - /* Used in #postgres_do_batch_withdraw_insert() to store - the signature of a blinded coin with the blinded coin's - details. */ + /* Used in #postgres_do_batch_withdraw_insert() to store + the signature of a blinded coin with the blinded coin's + details. */ PREPARE (pg, "call_batch_withdraw_insert", "SELECT " diff --git a/src/exchangedb/pg_do_deposit.c b/src/exchangedb/pg_do_deposit.c index c8f25e5bc..771c50af3 100644 --- a/src/exchangedb/pg_do_deposit.c +++ b/src/exchangedb/pg_do_deposit.c @@ -69,8 +69,8 @@ TEH_PG_do_deposit ( GNUNET_PQ_result_spec_end }; - /* Used in #postgres_do_deposit() to execute a deposit, - checking the coin's balance in the process as needed. */ + /* Used in #postgres_do_deposit() to execute a deposit, + checking the coin's balance in the process as needed. */ PREPARE (pg, "call_deposit", "SELECT " diff --git a/src/exchangedb/pg_do_melt.c b/src/exchangedb/pg_do_melt.c index 6f81ff38b..40a54d43b 100644 --- a/src/exchangedb/pg_do_melt.c +++ b/src/exchangedb/pg_do_melt.c @@ -63,7 +63,7 @@ TEH_PG_do_melt ( }; enum GNUNET_DB_QueryStatus qs; - /* Used in #postgres_do_melt() to melt a coin. */ + /* Used in #postgres_do_melt() to melt a coin. */ PREPARE (pg, "call_melt", "SELECT " diff --git a/src/exchangedb/pg_do_purse_merge.c b/src/exchangedb/pg_do_purse_merge.c index 518b66bf6..5d11b0565 100644 --- a/src/exchangedb/pg_do_purse_merge.c +++ b/src/exchangedb/pg_do_purse_merge.c @@ -75,7 +75,7 @@ TEH_PG_do_purse_merge ( &h_payto); GNUNET_free (payto_uri); } - /* Used in #postgres_do_purse_merge() */ + /* Used in #postgres_do_purse_merge() */ PREPARE (pg, "call_purse_merge", "SELECT" diff --git a/src/exchangedb/pg_do_recoup.c b/src/exchangedb/pg_do_recoup.c index 00f7bdd8b..1f74104ed 100644 --- a/src/exchangedb/pg_do_recoup.c +++ b/src/exchangedb/pg_do_recoup.c @@ -70,7 +70,6 @@ TEH_PG_do_recoup ( }; - PREPARE (pg, "call_recoup", "SELECT " diff --git a/src/exchangedb/pg_do_recoup_refresh.h b/src/exchangedb/pg_do_recoup_refresh.h index 3ac0f0a07..fbd791d44 100644 --- a/src/exchangedb/pg_do_recoup_refresh.h +++ b/src/exchangedb/pg_do_recoup_refresh.h @@ -53,4 +53,5 @@ TEH_PG_do_recoup_refresh ( struct GNUNET_TIME_Timestamp *recoup_timestamp, bool *recoup_ok, bool *internal_failure); + #endif diff --git a/src/exchangedb/pg_do_refund.c b/src/exchangedb/pg_do_refund.c index 1059f9cbb..0b9665c48 100644 --- a/src/exchangedb/pg_do_refund.c +++ b/src/exchangedb/pg_do_refund.c @@ -72,7 +72,7 @@ TEH_PG_do_refund ( GNUNET_break (0); return GNUNET_DB_STATUS_HARD_ERROR; } - /* Used in #postgres_do_refund() to refund a deposit. */ + /* Used in #postgres_do_refund() to refund a deposit. */ PREPARE (pg, "call_refund", "SELECT " diff --git a/src/exchangedb/pg_do_withdraw.c b/src/exchangedb/pg_do_withdraw.c index 87e4dd1d0..01bbfff5b 100644 --- a/src/exchangedb/pg_do_withdraw.c +++ b/src/exchangedb/pg_do_withdraw.c @@ -82,5 +82,3 @@ TEH_PG_do_withdraw ( params, rs); } - - diff --git a/src/exchangedb/pg_drain_kyc_alert.c b/src/exchangedb/pg_drain_kyc_alert.c index d635d95e9..4388334e9 100644 --- a/src/exchangedb/pg_drain_kyc_alert.c +++ b/src/exchangedb/pg_drain_kyc_alert.c @@ -28,8 +28,8 @@ enum GNUNET_DB_QueryStatus TEH_PG_drain_kyc_alert (void *cls, - uint32_t trigger_type, - struct TALER_PaytoHashP *h_payto) + uint32_t trigger_type, + struct TALER_PaytoHashP *h_payto) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { diff --git a/src/exchangedb/pg_drain_kyc_alert.h b/src/exchangedb/pg_drain_kyc_alert.h index bfaf04892..7425f472d 100644 --- a/src/exchangedb/pg_drain_kyc_alert.h +++ b/src/exchangedb/pg_drain_kyc_alert.h @@ -34,7 +34,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_drain_kyc_alert (void *cls, - uint32_t trigger_type, + uint32_t trigger_type, struct TALER_PaytoHashP *h_payto); #endif diff --git a/src/exchangedb/pg_ensure_coin_known.c b/src/exchangedb/pg_ensure_coin_known.c index 7ad37bf1d..721123fd3 100644 --- a/src/exchangedb/pg_ensure_coin_known.c +++ b/src/exchangedb/pg_ensure_coin_known.c @@ -28,10 +28,10 @@ enum TALER_EXCHANGEDB_CoinKnownStatus TEH_PG_ensure_coin_known (void *cls, - const struct TALER_CoinPublicInfo *coin, - uint64_t *known_coin_id, - struct TALER_DenominationHashP *denom_hash, - struct TALER_AgeCommitmentHash *h_age_commitment) + const struct TALER_CoinPublicInfo *coin, + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_hash, + struct TALER_AgeCommitmentHash *h_age_commitment) { struct PostgresClosure *pg = cls; enum GNUNET_DB_QueryStatus qs; diff --git a/src/exchangedb/pg_ensure_coin_known.h b/src/exchangedb/pg_ensure_coin_known.h index 76581d4b7..68c101735 100644 --- a/src/exchangedb/pg_ensure_coin_known.h +++ b/src/exchangedb/pg_ensure_coin_known.h @@ -37,9 +37,9 @@ */ enum TALER_EXCHANGEDB_CoinKnownStatus TEH_PG_ensure_coin_known (void *cls, - const struct TALER_CoinPublicInfo *coin, - uint64_t *known_coin_id, - struct TALER_DenominationHashP *denom_hash, + const struct TALER_CoinPublicInfo *coin, + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_hash, struct TALER_AgeCommitmentHash *h_age_commitment); #endif diff --git a/src/exchangedb/pg_event_listen.c b/src/exchangedb/pg_event_listen.c index c557ed3c5..6e1d32843 100644 --- a/src/exchangedb/pg_event_listen.c +++ b/src/exchangedb/pg_event_listen.c @@ -38,10 +38,10 @@ */ struct GNUNET_DB_EventHandler * TEH_PG_event_listen (void *cls, - struct GNUNET_TIME_Relative timeout, - const struct GNUNET_DB_EventHeaderP *es, - GNUNET_DB_EventCallback cb, - void *cb_cls) + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_DB_EventHeaderP *es, + GNUNET_DB_EventCallback cb, + void *cb_cls) { struct PostgresClosure *pg = cls; diff --git a/src/exchangedb/pg_event_listen.h b/src/exchangedb/pg_event_listen.h index 1be140776..7e1e83a0e 100644 --- a/src/exchangedb/pg_event_listen.h +++ b/src/exchangedb/pg_event_listen.h @@ -37,9 +37,9 @@ */ struct GNUNET_DB_EventHandler * TEH_PG_event_listen (void *cls, - struct GNUNET_TIME_Relative timeout, - const struct GNUNET_DB_EventHeaderP *es, - GNUNET_DB_EventCallback cb, + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_DB_EventHeaderP *es, + GNUNET_DB_EventCallback cb, void *cb_cls); #endif diff --git a/src/exchangedb/pg_event_listen_cancel.c b/src/exchangedb/pg_event_listen_cancel.c index 5d65827c2..9d776684d 100644 --- a/src/exchangedb/pg_event_listen_cancel.c +++ b/src/exchangedb/pg_event_listen_cancel.c @@ -26,10 +26,9 @@ #include "pg_helper.h" - void TEH_PG_event_listen_cancel (void *cls, - struct GNUNET_DB_EventHandler *eh) + struct GNUNET_DB_EventHandler *eh) { (void) cls; diff --git a/src/exchangedb/pg_event_notify.c b/src/exchangedb/pg_event_notify.c index 577f4acb8..188855775 100644 --- a/src/exchangedb/pg_event_notify.c +++ b/src/exchangedb/pg_event_notify.c @@ -28,9 +28,9 @@ void TEH_PG_event_notify (void *cls, - const struct GNUNET_DB_EventHeaderP *es, - const void *extra, - size_t extra_size) + const struct GNUNET_DB_EventHeaderP *es, + const void *extra, + size_t extra_size) { struct PostgresClosure *pg = cls; diff --git a/src/exchangedb/pg_event_notify.h b/src/exchangedb/pg_event_notify.h index 3b937cbab..85069659b 100644 --- a/src/exchangedb/pg_event_notify.h +++ b/src/exchangedb/pg_event_notify.h @@ -35,8 +35,8 @@ */ void TEH_PG_event_notify (void *cls, - const struct GNUNET_DB_EventHeaderP *es, - const void *extra, + const struct GNUNET_DB_EventHeaderP *es, + const void *extra, size_t extra_size); #endif diff --git a/src/exchangedb/pg_find_aggregation_transient.c b/src/exchangedb/pg_find_aggregation_transient.c index a5f367b5f..ecc6362cf 100644 --- a/src/exchangedb/pg_find_aggregation_transient.c +++ b/src/exchangedb/pg_find_aggregation_transient.c @@ -128,7 +128,7 @@ TEH_PG_find_aggregation_transient ( .pg = pg, .status = GNUNET_OK }; - /* Used in #postgres_find_aggregation_transient() */ + /* Used in #postgres_find_aggregation_transient() */ PREPARE (pg, "find_transient_aggregations", "SELECT" diff --git a/src/exchangedb/pg_gc.h b/src/exchangedb/pg_gc.h index 9e6ffbc3d..803581488 100644 --- a/src/exchangedb/pg_gc.h +++ b/src/exchangedb/pg_gc.h @@ -35,4 +35,5 @@ */ enum GNUNET_GenericReturnValue TEH_PG_gc (void *cls); + #endif diff --git a/src/exchangedb/pg_get_coin_denomination.c b/src/exchangedb/pg_get_coin_denomination.c index e82b86aa9..9f9256f6f 100644 --- a/src/exchangedb/pg_get_coin_denomination.c +++ b/src/exchangedb/pg_get_coin_denomination.c @@ -49,9 +49,9 @@ TEH_PG_get_coin_denomination ( "Getting coin denomination of coin %s\n", TALER_B2S (coin_pub)); - /* Used in #postgres_get_coin_denomination() to fetch - the denomination public key hash for - a coin known to the exchange. */ + /* Used in #postgres_get_coin_denomination() to fetch + the denomination public key hash for + a coin known to the exchange. */ PREPARE (pg, "get_coin_denomination", "SELECT" @@ -67,5 +67,3 @@ TEH_PG_get_coin_denomination ( params, rs); } - - diff --git a/src/exchangedb/pg_get_denomination_revocation.c b/src/exchangedb/pg_get_denomination_revocation.c index 4d29d88c4..5e7a3a322 100644 --- a/src/exchangedb/pg_get_denomination_revocation.c +++ b/src/exchangedb/pg_get_denomination_revocation.c @@ -46,15 +46,15 @@ TEH_PG_get_denomination_revocation ( }; PREPARE (pg, - "denomination_revocation_get", - "SELECT" - " master_sig" - ",denom_revocations_serial_id" - " FROM denomination_revocations" - " WHERE denominations_serial=" - " (SELECT denominations_serial" - " FROM denominations" - " WHERE denom_pub_hash=$1);"); + "denomination_revocation_get", + "SELECT" + " master_sig" + ",denom_revocations_serial_id" + " FROM denomination_revocations" + " WHERE denominations_serial=" + " (SELECT denominations_serial" + " FROM denominations" + " WHERE denom_pub_hash=$1);"); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "denomination_revocation_get", diff --git a/src/exchangedb/pg_get_denomination_revocation.h b/src/exchangedb/pg_get_denomination_revocation.h index d022c822d..5f7f27227 100644 --- a/src/exchangedb/pg_get_denomination_revocation.h +++ b/src/exchangedb/pg_get_denomination_revocation.h @@ -41,4 +41,5 @@ TEH_PG_get_denomination_revocation ( const struct TALER_DenominationHashP *denom_pub_hash, struct TALER_MasterSignatureP *master_sig, uint64_t *rowid); + #endif diff --git a/src/exchangedb/pg_get_extension_manifest.h b/src/exchangedb/pg_get_extension_manifest.h index 3756b7f4c..e8331ad9b 100644 --- a/src/exchangedb/pg_get_extension_manifest.h +++ b/src/exchangedb/pg_get_extension_manifest.h @@ -36,6 +36,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_get_extension_manifest (void *cls, - const char *extension_name, + const char *extension_name, char **manifest); + #endif diff --git a/src/exchangedb/pg_get_global_fee.c b/src/exchangedb/pg_get_global_fee.c index 6f6bbafef..990113fed 100644 --- a/src/exchangedb/pg_get_global_fee.c +++ b/src/exchangedb/pg_get_global_fee.c @@ -28,14 +28,14 @@ enum GNUNET_DB_QueryStatus TEH_PG_get_global_fee (void *cls, - struct GNUNET_TIME_Timestamp date, - struct GNUNET_TIME_Timestamp *start_date, - struct GNUNET_TIME_Timestamp *end_date, - struct TALER_GlobalFeeSet *fees, - struct GNUNET_TIME_Relative *purse_timeout, - struct GNUNET_TIME_Relative *history_expiration, - uint32_t *purse_account_limit, - struct TALER_MasterSignatureP *master_sig) + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative *purse_timeout, + struct GNUNET_TIME_Relative *history_expiration, + uint32_t *purse_account_limit, + struct TALER_MasterSignatureP *master_sig) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -65,25 +65,25 @@ TEH_PG_get_global_fee (void *cls, }; - /* Used in #postgres_get_global_fee() */ - PREPARE(pg, - "get_global_fee", - "SELECT " - " start_date" - ",end_date" - ",history_fee_val" - ",history_fee_frac" - ",account_fee_val" - ",account_fee_frac" - ",purse_fee_val" - ",purse_fee_frac" - ",purse_timeout" - ",history_expiration" - ",purse_account_limit" - ",master_sig" - " FROM global_fee" - " WHERE start_date <= $1" - " AND end_date > $1;"); + /* Used in #postgres_get_global_fee() */ + PREPARE (pg, + "get_global_fee", + "SELECT " + " start_date" + ",end_date" + ",history_fee_val" + ",history_fee_frac" + ",account_fee_val" + ",account_fee_frac" + ",purse_fee_val" + ",purse_fee_frac" + ",purse_timeout" + ",history_expiration" + ",purse_account_limit" + ",master_sig" + " FROM global_fee" + " WHERE start_date <= $1" + " AND end_date > $1;"); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "get_global_fee", params, diff --git a/src/exchangedb/pg_get_global_fee.h b/src/exchangedb/pg_get_global_fee.h index 0887d54d2..1e7c9e94b 100644 --- a/src/exchangedb/pg_get_global_fee.h +++ b/src/exchangedb/pg_get_global_fee.h @@ -40,13 +40,13 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_get_global_fee (void *cls, - struct GNUNET_TIME_Timestamp date, - struct GNUNET_TIME_Timestamp *start_date, - struct GNUNET_TIME_Timestamp *end_date, - struct TALER_GlobalFeeSet *fees, - struct GNUNET_TIME_Relative *purse_timeout, - struct GNUNET_TIME_Relative *history_expiration, - uint32_t *purse_account_limit, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative *purse_timeout, + struct GNUNET_TIME_Relative *history_expiration, + uint32_t *purse_account_limit, struct TALER_MasterSignatureP *master_sig); #endif diff --git a/src/exchangedb/pg_get_global_fees.c b/src/exchangedb/pg_get_global_fees.c index 0e1736bd4..e01eb2dab 100644 --- a/src/exchangedb/pg_get_global_fees.c +++ b/src/exchangedb/pg_get_global_fees.c @@ -121,11 +121,10 @@ global_fees_cb (void *cls, } - enum GNUNET_DB_QueryStatus TEH_PG_get_global_fees (void *cls, - TALER_EXCHANGEDB_GlobalFeeCallback cb, - void *cb_cls) + TALER_EXCHANGEDB_GlobalFeeCallback cb, + void *cb_cls) { struct PostgresClosure *pg = cls; struct GNUNET_TIME_Timestamp date @@ -144,7 +143,7 @@ TEH_PG_get_global_fees (void *cls, .status = GNUNET_OK }; - /* Used in #postgres_get_global_fees() */ + /* Used in #postgres_get_global_fees() */ PREPARE (pg, "get_global_fees", "SELECT " @@ -169,7 +168,3 @@ TEH_PG_get_global_fees (void *cls, &global_fees_cb, &gctx); } - - - - diff --git a/src/exchangedb/pg_get_global_fees.h b/src/exchangedb/pg_get_global_fees.h index c8f6f02c2..80c9b812f 100644 --- a/src/exchangedb/pg_get_global_fees.h +++ b/src/exchangedb/pg_get_global_fees.h @@ -35,6 +35,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_get_global_fees (void *cls, - TALER_EXCHANGEDB_GlobalFeeCallback cb, + TALER_EXCHANGEDB_GlobalFeeCallback cb, void *cb_cls); + #endif diff --git a/src/exchangedb/pg_get_known_coin.c b/src/exchangedb/pg_get_known_coin.c index fe5c683bc..bab48c119 100644 --- a/src/exchangedb/pg_get_known_coin.c +++ b/src/exchangedb/pg_get_known_coin.c @@ -27,8 +27,8 @@ enum GNUNET_DB_QueryStatus TEH_PG_get_known_coin (void *cls, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_CoinPublicInfo *coin_info) + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_CoinPublicInfo *coin_info) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -51,9 +51,9 @@ TEH_PG_get_known_coin (void *cls, "Getting known coin data for coin %s\n", TALER_B2S (coin_pub)); coin_info->coin_pub = *coin_pub; - /* Used in #postgres_get_known_coin() to fetch - the denomination public key and signature for - a coin known to the exchange. */ + /* Used in #postgres_get_known_coin() to fetch + the denomination public key and signature for + a coin known to the exchange. */ PREPARE (pg, "get_known_coin", "SELECT" diff --git a/src/exchangedb/pg_get_known_coin.h b/src/exchangedb/pg_get_known_coin.h index d7f55b33c..c34bd2a97 100644 --- a/src/exchangedb/pg_get_known_coin.h +++ b/src/exchangedb/pg_get_known_coin.h @@ -34,7 +34,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_get_known_coin (void *cls, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendPublicKeyP *coin_pub, struct TALER_CoinPublicInfo *coin_info); #endif diff --git a/src/exchangedb/pg_get_melt.c b/src/exchangedb/pg_get_melt.c index f239c605b..8e5685ec3 100644 --- a/src/exchangedb/pg_get_melt.c +++ b/src/exchangedb/pg_get_melt.c @@ -28,9 +28,9 @@ enum GNUNET_DB_QueryStatus TEH_PG_get_melt (void *cls, - const struct TALER_RefreshCommitmentP *rc, - struct TALER_EXCHANGEDB_Melt *melt, - uint64_t *melt_serial_id) + const struct TALER_RefreshCommitmentP *rc, + struct TALER_EXCHANGEDB_Melt *melt, + uint64_t *melt_serial_id) { struct PostgresClosure *pg = cls; bool h_age_commitment_is_null; @@ -66,8 +66,8 @@ TEH_PG_get_melt (void *cls, 0, sizeof (melt->session.coin.denom_sig)); - /* Used in #postgres_get_melt() to fetch - high-level information about a melt operation */ + /* Used in #postgres_get_melt() to fetch + high-level information about a melt operation */ PREPARE (pg, "get_melt", /* "SELECT" diff --git a/src/exchangedb/pg_get_melt.h b/src/exchangedb/pg_get_melt.h index 73d757a05..269960bad 100644 --- a/src/exchangedb/pg_get_melt.h +++ b/src/exchangedb/pg_get_melt.h @@ -37,8 +37,8 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_get_melt (void *cls, - const struct TALER_RefreshCommitmentP *rc, - struct TALER_EXCHANGEDB_Melt *melt, + const struct TALER_RefreshCommitmentP *rc, + struct TALER_EXCHANGEDB_Melt *melt, uint64_t *melt_serial_id); #endif diff --git a/src/exchangedb/pg_get_old_coin_by_h_blind.c b/src/exchangedb/pg_get_old_coin_by_h_blind.c index 385c3f1d1..dcce7b32f 100644 --- a/src/exchangedb/pg_get_old_coin_by_h_blind.c +++ b/src/exchangedb/pg_get_old_coin_by_h_blind.c @@ -26,7 +26,6 @@ #include "pg_helper.h" - enum GNUNET_DB_QueryStatus TEH_PG_get_old_coin_by_h_blind ( void *cls, @@ -47,7 +46,7 @@ TEH_PG_get_old_coin_by_h_blind ( GNUNET_PQ_result_spec_end }; - /* Used in #postgres_get_old_coin_by_h_blind() */ + /* Used in #postgres_get_old_coin_by_h_blind() */ PREPARE (pg, "old_coin_by_h_blind", "SELECT" diff --git a/src/exchangedb/pg_get_old_coin_by_h_blind.h b/src/exchangedb/pg_get_old_coin_by_h_blind.h index 1404990d9..93ed541b6 100644 --- a/src/exchangedb/pg_get_old_coin_by_h_blind.h +++ b/src/exchangedb/pg_get_old_coin_by_h_blind.h @@ -41,4 +41,5 @@ TEH_PG_get_old_coin_by_h_blind ( const struct TALER_BlindedCoinHashP *h_blind_ev, struct TALER_CoinSpendPublicKeyP *old_coin_pub, uint64_t *rrc_serial); + #endif diff --git a/src/exchangedb/pg_get_policy_details.c b/src/exchangedb/pg_get_policy_details.c index fafdca53c..6e1b5c5dc 100644 --- a/src/exchangedb/pg_get_policy_details.c +++ b/src/exchangedb/pg_get_policy_details.c @@ -57,7 +57,6 @@ TEH_PG_get_policy_details ( }; - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "get_policy_details", params, diff --git a/src/exchangedb/pg_get_purse_deposit.c b/src/exchangedb/pg_get_purse_deposit.c index 539bd5ece..8a135818d 100644 --- a/src/exchangedb/pg_get_purse_deposit.c +++ b/src/exchangedb/pg_get_purse_deposit.c @@ -61,7 +61,7 @@ TEH_PG_get_purse_deposit ( *partner_url = NULL; - /* Used in #postgres_get_purse_deposit */ + /* Used in #postgres_get_purse_deposit */ PREPARE (pg, "select_purse_deposit_by_coin_pub", "SELECT " diff --git a/src/exchangedb/pg_get_purse_request.c b/src/exchangedb/pg_get_purse_request.c index ba8182857..c5f5aac76 100644 --- a/src/exchangedb/pg_get_purse_request.c +++ b/src/exchangedb/pg_get_purse_request.c @@ -59,7 +59,7 @@ TEH_PG_get_purse_request ( purse_sig), GNUNET_PQ_result_spec_end }; - + PREPARE (pg, "get_purse_request", "SELECT " @@ -80,4 +80,3 @@ TEH_PG_get_purse_request ( params, rs); } - diff --git a/src/exchangedb/pg_get_ready_deposit.h b/src/exchangedb/pg_get_ready_deposit.h index 19b6dafe4..b1dd7a968 100644 --- a/src/exchangedb/pg_get_ready_deposit.h +++ b/src/exchangedb/pg_get_ready_deposit.h @@ -38,9 +38,9 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_get_ready_deposit (void *cls, - uint64_t start_shard_row, - uint64_t end_shard_row, - struct TALER_MerchantPublicKeyP *merchant_pub, + uint64_t start_shard_row, + uint64_t end_shard_row, + struct TALER_MerchantPublicKeyP *merchant_pub, char **payto_uri); #endif diff --git a/src/exchangedb/pg_get_refresh_reveal.c b/src/exchangedb/pg_get_refresh_reveal.c index e2db082b7..07d632248 100644 --- a/src/exchangedb/pg_get_refresh_reveal.c +++ b/src/exchangedb/pg_get_refresh_reveal.c @@ -133,14 +133,11 @@ add_revealed_coins (void *cls, } - - - enum GNUNET_DB_QueryStatus TEH_PG_get_refresh_reveal (void *cls, - const struct TALER_RefreshCommitmentP *rc, - TALER_EXCHANGEDB_RefreshCallback cb, - void *cb_cls) + const struct TALER_RefreshCommitmentP *rc, + TALER_EXCHANGEDB_RefreshCallback cb, + void *cb_cls) { struct PostgresClosure *pg = cls; struct GetRevealContext grctx; @@ -154,8 +151,8 @@ TEH_PG_get_refresh_reveal (void *cls, 0, sizeof (grctx)); - /* Obtain information about the coins created in a refresh - operation, used in #postgres_get_refresh_reveal() */ + /* Obtain information about the coins created in a refresh + operation, used in #postgres_get_refresh_reveal() */ PREPARE (pg, "get_refresh_revealed_coins", "SELECT " diff --git a/src/exchangedb/pg_get_refresh_reveal.h b/src/exchangedb/pg_get_refresh_reveal.h index 0fcea26cd..15b57b343 100644 --- a/src/exchangedb/pg_get_refresh_reveal.h +++ b/src/exchangedb/pg_get_refresh_reveal.h @@ -37,8 +37,8 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_get_refresh_reveal (void *cls, - const struct TALER_RefreshCommitmentP *rc, - TALER_EXCHANGEDB_RefreshCallback cb, + const struct TALER_RefreshCommitmentP *rc, + TALER_EXCHANGEDB_RefreshCallback cb, void *cb_cls); #endif diff --git a/src/exchangedb/pg_get_reserve_balance.c b/src/exchangedb/pg_get_reserve_balance.c index e08261fc0..7d5eb58f8 100644 --- a/src/exchangedb/pg_get_reserve_balance.c +++ b/src/exchangedb/pg_get_reserve_balance.c @@ -27,8 +27,8 @@ enum GNUNET_DB_QueryStatus TEH_PG_get_reserve_balance (void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct TALER_Amount *balance) + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_Amount *balance) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { diff --git a/src/exchangedb/pg_get_reserve_balance.h b/src/exchangedb/pg_get_reserve_balance.h index fd15f0d80..6dc88d906 100644 --- a/src/exchangedb/pg_get_reserve_balance.h +++ b/src/exchangedb/pg_get_reserve_balance.h @@ -34,7 +34,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_get_reserve_balance (void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, struct TALER_Amount *balance); #endif diff --git a/src/exchangedb/pg_get_reserve_by_h_blind.c b/src/exchangedb/pg_get_reserve_by_h_blind.c index 2105b4766..f87fe6cd4 100644 --- a/src/exchangedb/pg_get_reserve_by_h_blind.c +++ b/src/exchangedb/pg_get_reserve_by_h_blind.c @@ -45,7 +45,7 @@ TEH_PG_get_reserve_by_h_blind ( reserve_out_serial_id), GNUNET_PQ_result_spec_end }; - /* Used in #postgres_get_reserve_by_h_blind() */ + /* Used in #postgres_get_reserve_by_h_blind() */ PREPARE (pg, "reserve_by_h_blind", "SELECT" diff --git a/src/exchangedb/pg_get_wire_accounts.c b/src/exchangedb/pg_get_wire_accounts.c index 6986eaef2..43590acf8 100644 --- a/src/exchangedb/pg_get_wire_accounts.c +++ b/src/exchangedb/pg_get_wire_accounts.c @@ -92,12 +92,10 @@ get_wire_accounts_cb (void *cls, } - - enum GNUNET_DB_QueryStatus TEH_PG_get_wire_accounts (void *cls, - TALER_EXCHANGEDB_WireAccountCallback cb, - void *cb_cls) + TALER_EXCHANGEDB_WireAccountCallback cb, + void *cb_cls) { struct PostgresClosure *pg = cls; struct GetWireAccountsContext ctx = { @@ -111,12 +109,12 @@ TEH_PG_get_wire_accounts (void *cls, enum GNUNET_DB_QueryStatus qs; PREPARE (pg, - "get_wire_accounts", - "SELECT" - " payto_uri" - ",master_sig" - " FROM wire_accounts" - " WHERE is_active"); + "get_wire_accounts", + "SELECT" + " payto_uri" + ",master_sig" + " FROM wire_accounts" + " WHERE is_active"); qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, "get_wire_accounts", params, diff --git a/src/exchangedb/pg_get_wire_accounts.h b/src/exchangedb/pg_get_wire_accounts.h index 4ddda0ed3..f4dc97ce0 100644 --- a/src/exchangedb/pg_get_wire_accounts.h +++ b/src/exchangedb/pg_get_wire_accounts.h @@ -36,7 +36,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_get_wire_accounts (void *cls, - TALER_EXCHANGEDB_WireAccountCallback cb, + TALER_EXCHANGEDB_WireAccountCallback cb, void *cb_cls); #endif diff --git a/src/exchangedb/pg_get_wire_fee.c b/src/exchangedb/pg_get_wire_fee.c index 4b4324766..4aab68b85 100644 --- a/src/exchangedb/pg_get_wire_fee.c +++ b/src/exchangedb/pg_get_wire_fee.c @@ -27,12 +27,12 @@ enum GNUNET_DB_QueryStatus TEH_PG_get_wire_fee (void *cls, - const char *type, - struct GNUNET_TIME_Timestamp date, - struct GNUNET_TIME_Timestamp *start_date, - struct GNUNET_TIME_Timestamp *end_date, - struct TALER_WireFeeSet *fees, - struct TALER_MasterSignatureP *master_sig) + const char *type, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_WireFeeSet *fees, + struct TALER_MasterSignatureP *master_sig) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -55,22 +55,21 @@ TEH_PG_get_wire_fee (void *cls, }; - - /* Used in #postgres_get_wire_fee() */ - PREPARE(pg, - "get_wire_fee", - "SELECT " - " start_date" - ",end_date" - ",wire_fee_val" - ",wire_fee_frac" - ",closing_fee_val" - ",closing_fee_frac" - ",master_sig" - " FROM wire_fee" - " WHERE wire_method=$1" - " AND start_date <= $2" - " AND end_date > $2;"); + /* Used in #postgres_get_wire_fee() */ + PREPARE (pg, + "get_wire_fee", + "SELECT " + " start_date" + ",end_date" + ",wire_fee_val" + ",wire_fee_frac" + ",closing_fee_val" + ",closing_fee_frac" + ",master_sig" + " FROM wire_fee" + " WHERE wire_method=$1" + " AND start_date <= $2" + " AND end_date > $2;"); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "get_wire_fee", params, diff --git a/src/exchangedb/pg_get_wire_fee.h b/src/exchangedb/pg_get_wire_fee.h index 92107fe30..409a5c48b 100644 --- a/src/exchangedb/pg_get_wire_fee.h +++ b/src/exchangedb/pg_get_wire_fee.h @@ -39,11 +39,11 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_get_wire_fee (void *cls, - const char *type, - struct GNUNET_TIME_Timestamp date, - struct GNUNET_TIME_Timestamp *start_date, - struct GNUNET_TIME_Timestamp *end_date, - struct TALER_WireFeeSet *fees, + const char *type, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_WireFeeSet *fees, struct TALER_MasterSignatureP *master_sig); #endif diff --git a/src/exchangedb/pg_get_wire_fees.c b/src/exchangedb/pg_get_wire_fees.c index a83db151d..e34d44a9a 100644 --- a/src/exchangedb/pg_get_wire_fees.c +++ b/src/exchangedb/pg_get_wire_fees.c @@ -109,9 +109,9 @@ get_wire_fees_cb (void *cls, enum GNUNET_DB_QueryStatus TEH_PG_get_wire_fees (void *cls, - const char *wire_method, - TALER_EXCHANGEDB_WireFeeCallback cb, - void *cb_cls) + const char *wire_method, + TALER_EXCHANGEDB_WireFeeCallback cb, + void *cb_cls) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { diff --git a/src/exchangedb/pg_get_wire_fees.h b/src/exchangedb/pg_get_wire_fees.h index 83bacd674..798a514db 100644 --- a/src/exchangedb/pg_get_wire_fees.h +++ b/src/exchangedb/pg_get_wire_fees.h @@ -37,8 +37,8 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_get_wire_fees (void *cls, - const char *wire_method, - TALER_EXCHANGEDB_WireFeeCallback cb, + const char *wire_method, + TALER_EXCHANGEDB_WireFeeCallback cb, void *cb_cls); #endif diff --git a/src/exchangedb/pg_get_withdraw_info.c b/src/exchangedb/pg_get_withdraw_info.c index ef3936269..d6a180b00 100644 --- a/src/exchangedb/pg_get_withdraw_info.c +++ b/src/exchangedb/pg_get_withdraw_info.c @@ -55,10 +55,10 @@ TEH_PG_get_withdraw_info ( GNUNET_PQ_result_spec_end }; - /* Used in #postgres_get_withdraw_info() to - locate the response for a /reserve/withdraw request - using the hash of the blinded message. Used to - make sure /reserve/withdraw requests are idempotent. */ + /* Used in #postgres_get_withdraw_info() to + locate the response for a /reserve/withdraw request + using the hash of the blinded message. Used to + make sure /reserve/withdraw requests are idempotent. */ PREPARE (pg, "get_withdraw_info", "SELECT" diff --git a/src/exchangedb/pg_have_deposit2.c b/src/exchangedb/pg_have_deposit2.c index 1616858c5..92c300605 100644 --- a/src/exchangedb/pg_have_deposit2.c +++ b/src/exchangedb/pg_have_deposit2.c @@ -71,29 +71,29 @@ TEH_PG_have_deposit2 ( "Getting deposits for coin %s\n", TALER_B2S (coin_pub)); - /* Fetch an existing deposit request, used to ensure idempotency - during /deposit processing. Used in #postgres_have_deposit(). */ + /* Fetch an existing deposit request, used to ensure idempotency + during /deposit processing. Used in #postgres_have_deposit(). */ PREPARE (pg, - "get_deposit", - "SELECT" - " dep.amount_with_fee_val" - ",dep.amount_with_fee_frac" - ",denominations.fee_deposit_val" - ",denominations.fee_deposit_frac" - ",dep.wallet_timestamp" - ",dep.exchange_timestamp" - ",dep.refund_deadline" - ",dep.wire_deadline" - ",dep.h_contract_terms" - ",dep.wire_salt" - ",wt.payto_uri AS receiver_wire_account" - " FROM deposits dep" - " JOIN known_coins kc ON (kc.coin_pub = dep.coin_pub)" - " JOIN denominations USING (denominations_serial)" - " JOIN wire_targets wt USING (wire_target_h_payto)" - " WHERE dep.coin_pub=$1" - " AND dep.merchant_pub=$3" - " AND dep.h_contract_terms=$2;"); + "get_deposit", + "SELECT" + " dep.amount_with_fee_val" + ",dep.amount_with_fee_frac" + ",denominations.fee_deposit_val" + ",denominations.fee_deposit_frac" + ",dep.wallet_timestamp" + ",dep.exchange_timestamp" + ",dep.refund_deadline" + ",dep.wire_deadline" + ",dep.h_contract_terms" + ",dep.wire_salt" + ",wt.payto_uri AS receiver_wire_account" + " FROM deposits dep" + " JOIN known_coins kc ON (kc.coin_pub = dep.coin_pub)" + " JOIN denominations USING (denominations_serial)" + " JOIN wire_targets wt USING (wire_target_h_payto)" + " WHERE dep.coin_pub=$1" + " AND dep.merchant_pub=$3" + " AND dep.h_contract_terms=$2;"); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "get_deposit", diff --git a/src/exchangedb/pg_insert_aggregation_tracking.c b/src/exchangedb/pg_insert_aggregation_tracking.c index 01c5928ba..fe61b841d 100644 --- a/src/exchangedb/pg_insert_aggregation_tracking.c +++ b/src/exchangedb/pg_insert_aggregation_tracking.c @@ -51,4 +51,3 @@ TEH_PG_insert_aggregation_tracking ( "insert_aggregation_tracking", params); } - diff --git a/src/exchangedb/pg_insert_aggregation_tracking.h b/src/exchangedb/pg_insert_aggregation_tracking.h index 4f0ac1aae..e67c0e8e7 100644 --- a/src/exchangedb/pg_insert_aggregation_tracking.h +++ b/src/exchangedb/pg_insert_aggregation_tracking.h @@ -40,4 +40,3 @@ TEH_PG_insert_aggregation_tracking ( unsigned long long deposit_serial_id); #endif - diff --git a/src/exchangedb/pg_insert_auditor.c b/src/exchangedb/pg_insert_auditor.c index 757dfa625..2f1de7ba7 100644 --- a/src/exchangedb/pg_insert_auditor.c +++ b/src/exchangedb/pg_insert_auditor.c @@ -27,10 +27,10 @@ enum GNUNET_DB_QueryStatus TEH_PG_insert_auditor (void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const char *auditor_url, - const char *auditor_name, - struct GNUNET_TIME_Timestamp start_date) + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp start_date) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -41,7 +41,7 @@ TEH_PG_insert_auditor (void *cls, GNUNET_PQ_query_param_end }; - /* used in #postgres_insert_auditor() */ + /* used in #postgres_insert_auditor() */ PREPARE (pg, "insert_auditor", "INSERT INTO auditors " diff --git a/src/exchangedb/pg_insert_auditor.h b/src/exchangedb/pg_insert_auditor.h index 7523282e4..8de388f23 100644 --- a/src/exchangedb/pg_insert_auditor.h +++ b/src/exchangedb/pg_insert_auditor.h @@ -38,8 +38,8 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_insert_auditor (void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const char *auditor_url, - const char *auditor_name, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name, struct GNUNET_TIME_Timestamp start_date); #endif diff --git a/src/exchangedb/pg_insert_contract.c b/src/exchangedb/pg_insert_contract.c index d3e6c23be..0274f8d93 100644 --- a/src/exchangedb/pg_insert_contract.c +++ b/src/exchangedb/pg_insert_contract.c @@ -45,20 +45,20 @@ TEH_PG_insert_contract ( }; *in_conflict = false; - /* Used in #postgres_insert_contract() */ + /* Used in #postgres_insert_contract() */ PREPARE (pg, - "insert_contract", - "INSERT INTO contracts" - " (purse_pub" - " ,pub_ckey" - " ,e_contract" - " ,contract_sig" - " ,purse_expiration" - " ) SELECT " - " $1, $2, $3, $4, purse_expiration" - " FROM purse_requests" - " WHERE purse_pub=$1" - " ON CONFLICT DO NOTHING;"); + "insert_contract", + "INSERT INTO contracts" + " (purse_pub" + " ,pub_ckey" + " ,e_contract" + " ,contract_sig" + " ,purse_expiration" + " ) SELECT " + " $1, $2, $3, $4, purse_expiration" + " FROM purse_requests" + " WHERE purse_pub=$1" + " ON CONFLICT DO NOTHING;"); qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, "insert_contract", params); @@ -68,8 +68,8 @@ TEH_PG_insert_contract ( struct TALER_EncryptedContract econtract2; qs = TEH_PG_select_contract_by_purse (pg, - purse_pub, - &econtract2); + purse_pub, + &econtract2); if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { GNUNET_break (0); diff --git a/src/exchangedb/pg_insert_denomination_revocation.c b/src/exchangedb/pg_insert_denomination_revocation.c index 061d7adc0..49445f262 100644 --- a/src/exchangedb/pg_insert_denomination_revocation.c +++ b/src/exchangedb/pg_insert_denomination_revocation.c @@ -39,7 +39,7 @@ TEH_PG_insert_denomination_revocation ( GNUNET_PQ_query_param_end }; - /* Used in #postgres_insert_denomination_revocation() */ + /* Used in #postgres_insert_denomination_revocation() */ PREPARE (pg, "denomination_revocation_insert", "INSERT INTO denomination_revocations " diff --git a/src/exchangedb/pg_insert_deposit.h b/src/exchangedb/pg_insert_deposit.h index 15de39eff..82cbcd542 100644 --- a/src/exchangedb/pg_insert_deposit.h +++ b/src/exchangedb/pg_insert_deposit.h @@ -34,7 +34,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_insert_deposit (void *cls, - struct GNUNET_TIME_Timestamp exchange_timestamp, + struct GNUNET_TIME_Timestamp exchange_timestamp, const struct TALER_EXCHANGEDB_Deposit *deposit); #endif diff --git a/src/exchangedb/pg_insert_drain_profit.c b/src/exchangedb/pg_insert_drain_profit.c index 19340eafb..34ab0332c 100644 --- a/src/exchangedb/pg_insert_drain_profit.c +++ b/src/exchangedb/pg_insert_drain_profit.c @@ -45,7 +45,7 @@ TEH_PG_insert_drain_profit ( GNUNET_PQ_query_param_auto_from_type (master_sig), GNUNET_PQ_query_param_end }; - /* Used in #postgres_insert_drain_profit() */ + /* Used in #postgres_insert_drain_profit() */ PREPARE (pg, "drain_profit_insert", "INSERT INTO profit_drains " diff --git a/src/exchangedb/pg_insert_global_fee.c b/src/exchangedb/pg_insert_global_fee.c index c08fc23bb..1c34016a7 100644 --- a/src/exchangedb/pg_insert_global_fee.c +++ b/src/exchangedb/pg_insert_global_fee.c @@ -28,13 +28,13 @@ enum GNUNET_DB_QueryStatus TEH_PG_insert_global_fee (void *cls, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - const struct TALER_GlobalFeeSet *fees, - struct GNUNET_TIME_Relative purse_timeout, - struct GNUNET_TIME_Relative history_expiration, - uint32_t purse_account_limit, - const struct TALER_MasterSignatureP *master_sig) + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + const struct TALER_MasterSignatureP *master_sig) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -59,14 +59,14 @@ TEH_PG_insert_global_fee (void *cls, uint32_t pal; qs = TEH_PG_get_global_fee (pg, - start_date, - &sd, - &ed, - &wx, - &pt, - &he, - &pal, - &sig); + start_date, + &sd, + &ed, + &wx, + &pt, + &he, + &pal, + &sig); if (qs < 0) return qs; if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) @@ -113,7 +113,7 @@ TEH_PG_insert_global_fee (void *cls, return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; } - /* Used in #postgres_insert_global_fee */ + /* Used in #postgres_insert_global_fee */ PREPARE (pg, "insert_global_fee", "INSERT INTO global_fee " diff --git a/src/exchangedb/pg_insert_global_fee.h b/src/exchangedb/pg_insert_global_fee.h index 9780d5322..411345dc4 100644 --- a/src/exchangedb/pg_insert_global_fee.h +++ b/src/exchangedb/pg_insert_global_fee.h @@ -40,11 +40,11 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_insert_global_fee (void *cls, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - const struct TALER_GlobalFeeSet *fees, - struct GNUNET_TIME_Relative purse_timeout, - struct GNUNET_TIME_Relative history_expiration, - uint32_t purse_account_limit, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, const struct TALER_MasterSignatureP *master_sig); #endif diff --git a/src/exchangedb/pg_insert_history_request.c b/src/exchangedb/pg_insert_history_request.c index 00270b1a1..ab3f39133 100644 --- a/src/exchangedb/pg_insert_history_request.c +++ b/src/exchangedb/pg_insert_history_request.c @@ -51,7 +51,7 @@ TEH_PG_insert_history_request ( idempotent), GNUNET_PQ_result_spec_end }; - /* Used in #postgres_insert_history_request() */ + /* Used in #postgres_insert_history_request() */ PREPARE (pg, "call_history_request", "SELECT" diff --git a/src/exchangedb/pg_insert_kyc_requirement_for_account.c b/src/exchangedb/pg_insert_kyc_requirement_for_account.c index be5cbac87..2552aae40 100644 --- a/src/exchangedb/pg_insert_kyc_requirement_for_account.c +++ b/src/exchangedb/pg_insert_kyc_requirement_for_account.c @@ -43,7 +43,7 @@ TEH_PG_insert_kyc_requirement_for_account ( requirement_row), GNUNET_PQ_result_spec_end }; - /* Used in #postgres_insert_kyc_requirement_for_account() */ + /* Used in #postgres_insert_kyc_requirement_for_account() */ PREPARE (pg, "insert_legitimization_requirement", "INSERT INTO legitimization_requirements" diff --git a/src/exchangedb/pg_insert_kyc_requirement_for_account.h b/src/exchangedb/pg_insert_kyc_requirement_for_account.h index 5f9bf6a48..c2f03b02a 100644 --- a/src/exchangedb/pg_insert_kyc_requirement_for_account.h +++ b/src/exchangedb/pg_insert_kyc_requirement_for_account.h @@ -41,4 +41,5 @@ TEH_PG_insert_kyc_requirement_for_account ( const char *provider_section, const struct TALER_PaytoHashP *h_payto, uint64_t *requirement_row); + #endif diff --git a/src/exchangedb/pg_insert_kyc_requirement_process.c b/src/exchangedb/pg_insert_kyc_requirement_process.c index d520ac59c..f1ea5b490 100644 --- a/src/exchangedb/pg_insert_kyc_requirement_process.c +++ b/src/exchangedb/pg_insert_kyc_requirement_process.c @@ -52,7 +52,7 @@ TEH_PG_insert_kyc_requirement_process ( GNUNET_PQ_result_spec_end }; - /* Used in #postgres_insert_kyc_requirement_process() */ + /* Used in #postgres_insert_kyc_requirement_process() */ PREPARE (pg, "insert_legitimization_process", "INSERT INTO legitimization_processes" diff --git a/src/exchangedb/pg_insert_kyc_requirement_process.h b/src/exchangedb/pg_insert_kyc_requirement_process.h index 3f354472e..df21db8cd 100644 --- a/src/exchangedb/pg_insert_kyc_requirement_process.h +++ b/src/exchangedb/pg_insert_kyc_requirement_process.h @@ -45,4 +45,5 @@ TEH_PG_insert_kyc_requirement_process ( const char *provider_account_id, const char *provider_legitimization_id, uint64_t *process_row); + #endif diff --git a/src/exchangedb/pg_insert_partner.h b/src/exchangedb/pg_insert_partner.h index eed40a80e..3ebae786c 100644 --- a/src/exchangedb/pg_insert_partner.h +++ b/src/exchangedb/pg_insert_partner.h @@ -40,12 +40,12 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_insert_partner (void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - struct GNUNET_TIME_Relative wad_frequency, - const struct TALER_Amount *wad_fee, - const char *partner_base_url, + const struct TALER_MasterPublicKeyP *master_pub, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + struct GNUNET_TIME_Relative wad_frequency, + const struct TALER_Amount *wad_fee, + const char *partner_base_url, const struct TALER_MasterSignatureP *master_sig); #endif diff --git a/src/exchangedb/pg_insert_refund.c b/src/exchangedb/pg_insert_refund.c index 047df0334..8f9466575 100644 --- a/src/exchangedb/pg_insert_refund.c +++ b/src/exchangedb/pg_insert_refund.c @@ -28,7 +28,7 @@ enum GNUNET_DB_QueryStatus TEH_PG_insert_refund (void *cls, - const struct TALER_EXCHANGEDB_Refund *refund) + const struct TALER_EXCHANGEDB_Refund *refund) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -45,7 +45,7 @@ TEH_PG_insert_refund (void *cls, TALER_amount_cmp_currency (&refund->details.refund_amount, &refund->details.refund_fee)); - /* Used in #postgres_insert_refund() to store refund information */ + /* Used in #postgres_insert_refund() to store refund information */ PREPARE (pg, "insert_refund", "INSERT INTO refunds " diff --git a/src/exchangedb/pg_insert_reserve_closed.c b/src/exchangedb/pg_insert_reserve_closed.c index d17c37edc..963a38226 100644 --- a/src/exchangedb/pg_insert_reserve_closed.c +++ b/src/exchangedb/pg_insert_reserve_closed.c @@ -57,20 +57,20 @@ TEH_PG_insert_reserve_closed ( GNUNET_PQ_query_param_end }; - /* Used in #postgres_insert_reserve_closed() */ + /* Used in #postgres_insert_reserve_closed() */ PREPARE (pg, - "reserves_close_insert", - "INSERT INTO reserves_close " - "(reserve_pub" - ",execution_date" - ",wtid" - ",wire_target_h_payto" - ",amount_val" - ",amount_frac" - ",closing_fee_val" - ",closing_fee_frac" - ",close_request_row" - ") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9);"); + "reserves_close_insert", + "INSERT INTO reserves_close " + "(reserve_pub" + ",execution_date" + ",wtid" + ",wire_target_h_payto" + ",amount_val" + ",amount_frac" + ",closing_fee_val" + ",closing_fee_frac" + ",close_request_row" + ") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9);"); qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, "reserves_close_insert", @@ -83,7 +83,7 @@ TEH_PG_insert_reserve_closed ( reserve.pub = *reserve_pub; if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != (qs = TEH_PG_reserves_get (cls, - &reserve))) + &reserve))) { /* Existence should have been checked before we got here... */ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -110,5 +110,5 @@ TEH_PG_insert_reserve_closed ( GNUNET_break (TALER_AAR_RESULT_ZERO == ret); } return TEH_PG_reserves_update (cls, - &reserve); + &reserve); } diff --git a/src/exchangedb/pg_insert_wire.h b/src/exchangedb/pg_insert_wire.h index 15ce08674..670928d7c 100644 --- a/src/exchangedb/pg_insert_wire.h +++ b/src/exchangedb/pg_insert_wire.h @@ -37,8 +37,8 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_insert_wire (void *cls, - const char *payto_uri, - struct GNUNET_TIME_Timestamp start_date, + const char *payto_uri, + struct GNUNET_TIME_Timestamp start_date, const struct TALER_MasterSignatureP *master_sig); #endif diff --git a/src/exchangedb/pg_insert_wire_fee.c b/src/exchangedb/pg_insert_wire_fee.c index 278ec2bcb..ac14a8cbb 100644 --- a/src/exchangedb/pg_insert_wire_fee.c +++ b/src/exchangedb/pg_insert_wire_fee.c @@ -28,11 +28,11 @@ enum GNUNET_DB_QueryStatus TEH_PG_insert_wire_fee (void *cls, - const char *type, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - const struct TALER_WireFeeSet *fees, - const struct TALER_MasterSignatureP *master_sig) + const char *type, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_WireFeeSet *fees, + const struct TALER_MasterSignatureP *master_sig) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -51,12 +51,12 @@ TEH_PG_insert_wire_fee (void *cls, enum GNUNET_DB_QueryStatus qs; qs = TEH_PG_get_wire_fee (pg, - type, - start_date, - &sd, - &ed, - &wx, - &sig); + type, + start_date, + &sd, + &ed, + &wx, + &sig); if (qs < 0) return qs; if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) @@ -88,7 +88,7 @@ TEH_PG_insert_wire_fee (void *cls, return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; } - /* Used in #postgres_insert_wire_fee */ + /* Used in #postgres_insert_wire_fee */ PREPARE (pg, "insert_wire_fee", "INSERT INTO wire_fee " diff --git a/src/exchangedb/pg_insert_wire_fee.h b/src/exchangedb/pg_insert_wire_fee.h index e53faf5a5..15c1a39f8 100644 --- a/src/exchangedb/pg_insert_wire_fee.h +++ b/src/exchangedb/pg_insert_wire_fee.h @@ -38,9 +38,9 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_insert_wire_fee (void *cls, - const char *type, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - const struct TALER_WireFeeSet *fees, + const char *type, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_WireFeeSet *fees, const struct TALER_MasterSignatureP *master_sig); #endif diff --git a/src/exchangedb/pg_iterate_active_auditors.h b/src/exchangedb/pg_iterate_active_auditors.h index 1247d2d3d..f0e2808e9 100644 --- a/src/exchangedb/pg_iterate_active_auditors.h +++ b/src/exchangedb/pg_iterate_active_auditors.h @@ -36,6 +36,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_iterate_active_auditors (void *cls, - TALER_EXCHANGEDB_AuditorsCallback cb, + TALER_EXCHANGEDB_AuditorsCallback cb, void *cb_cls); + #endif diff --git a/src/exchangedb/pg_iterate_active_signkeys.h b/src/exchangedb/pg_iterate_active_signkeys.h index b99dfa8df..5ebba9f5a 100644 --- a/src/exchangedb/pg_iterate_active_signkeys.h +++ b/src/exchangedb/pg_iterate_active_signkeys.h @@ -37,7 +37,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_iterate_active_signkeys (void *cls, - TALER_EXCHANGEDB_ActiveSignkeysCallback cb, + TALER_EXCHANGEDB_ActiveSignkeysCallback cb, void *cb_cls); #endif diff --git a/src/exchangedb/pg_iterate_auditor_denominations.h b/src/exchangedb/pg_iterate_auditor_denominations.h index da1f36701..1278e8a9f 100644 --- a/src/exchangedb/pg_iterate_auditor_denominations.h +++ b/src/exchangedb/pg_iterate_auditor_denominations.h @@ -41,4 +41,5 @@ TEH_PG_iterate_auditor_denominations ( void *cls, TALER_EXCHANGEDB_AuditorDenominationsCallback cb, void *cb_cls); + #endif diff --git a/src/exchangedb/pg_iterate_denomination_info.h b/src/exchangedb/pg_iterate_denomination_info.h index 57847a515..27c08d0a9 100644 --- a/src/exchangedb/pg_iterate_denomination_info.h +++ b/src/exchangedb/pg_iterate_denomination_info.h @@ -35,7 +35,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_iterate_denomination_info (void *cls, - TALER_EXCHANGEDB_DenominationCallback cb, + TALER_EXCHANGEDB_DenominationCallback cb, void *cb_cls); #endif diff --git a/src/exchangedb/pg_iterate_denominations.h b/src/exchangedb/pg_iterate_denominations.h index a205fc6ba..9f59fc803 100644 --- a/src/exchangedb/pg_iterate_denominations.h +++ b/src/exchangedb/pg_iterate_denominations.h @@ -38,7 +38,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_iterate_denominations (void *cls, - TALER_EXCHANGEDB_DenominationsCallback cb, + TALER_EXCHANGEDB_DenominationsCallback cb, void *cb_cls); #endif diff --git a/src/exchangedb/pg_kyc_provider_account_lookup.c b/src/exchangedb/pg_kyc_provider_account_lookup.c index 32cd65f7d..f3bd84c1a 100644 --- a/src/exchangedb/pg_kyc_provider_account_lookup.c +++ b/src/exchangedb/pg_kyc_provider_account_lookup.c @@ -26,7 +26,6 @@ #include "pg_helper.h" - enum GNUNET_DB_QueryStatus TEH_PG_kyc_provider_account_lookup ( void *cls, @@ -48,7 +47,7 @@ TEH_PG_kyc_provider_account_lookup ( process_row), GNUNET_PQ_result_spec_end }; - /* Used in #postgres_kyc_provider_account_lookup() */ + /* Used in #postgres_kyc_provider_account_lookup() */ PREPARE (pg, "get_wire_target_by_legitimization_id", "SELECT " diff --git a/src/exchangedb/pg_kyc_provider_account_lookup.h b/src/exchangedb/pg_kyc_provider_account_lookup.h index 41bcb86ae..74f90d88d 100644 --- a/src/exchangedb/pg_kyc_provider_account_lookup.h +++ b/src/exchangedb/pg_kyc_provider_account_lookup.h @@ -44,4 +44,5 @@ TEH_PG_kyc_provider_account_lookup ( const char *provider_legitimization_id, struct TALER_PaytoHashP *h_payto, uint64_t *process_row); + #endif diff --git a/src/exchangedb/pg_lookup_auditor_status.c b/src/exchangedb/pg_lookup_auditor_status.c index 5e62bfa9e..91afe6eaa 100644 --- a/src/exchangedb/pg_lookup_auditor_status.c +++ b/src/exchangedb/pg_lookup_auditor_status.c @@ -46,7 +46,7 @@ TEH_PG_lookup_auditor_status ( GNUNET_PQ_result_spec_end }; - /* Used in #postgres_lookup_auditor_status() */ + /* Used in #postgres_lookup_auditor_status() */ PREPARE (pg, "lookup_auditor_status", "SELECT" diff --git a/src/exchangedb/pg_lookup_denomination_key.c b/src/exchangedb/pg_lookup_denomination_key.c index 36ada96e4..759af1b5c 100644 --- a/src/exchangedb/pg_lookup_denomination_key.c +++ b/src/exchangedb/pg_lookup_denomination_key.c @@ -60,7 +60,7 @@ TEH_PG_lookup_denomination_key ( GNUNET_PQ_result_spec_end }; - /* used in #postgres_lookup_denomination_key() */ + /* used in #postgres_lookup_denomination_key() */ PREPARE (pg, "lookup_denomination_key", "SELECT" diff --git a/src/exchangedb/pg_lookup_global_fee_by_time.h b/src/exchangedb/pg_lookup_global_fee_by_time.h index 9ac7d7dcd..c5ff95fc6 100644 --- a/src/exchangedb/pg_lookup_global_fee_by_time.h +++ b/src/exchangedb/pg_lookup_global_fee_by_time.h @@ -48,4 +48,5 @@ TEH_PG_lookup_global_fee_by_time ( struct GNUNET_TIME_Relative *purse_timeout, struct GNUNET_TIME_Relative *history_expiration, uint32_t *purse_account_limit); + #endif diff --git a/src/exchangedb/pg_lookup_kyc_process_by_account.h b/src/exchangedb/pg_lookup_kyc_process_by_account.h index 40af6a7f6..0300b498c 100644 --- a/src/exchangedb/pg_lookup_kyc_process_by_account.h +++ b/src/exchangedb/pg_lookup_kyc_process_by_account.h @@ -47,4 +47,5 @@ TEH_PG_lookup_kyc_process_by_account ( struct GNUNET_TIME_Absolute *expiration, char **provider_account_id, char **provider_legitimization_id); + #endif diff --git a/src/exchangedb/pg_lookup_signing_key.c b/src/exchangedb/pg_lookup_signing_key.c index 3f31a6f49..3803d114f 100644 --- a/src/exchangedb/pg_lookup_signing_key.c +++ b/src/exchangedb/pg_lookup_signing_key.c @@ -62,4 +62,3 @@ TEH_PG_lookup_signing_key ( params, rs); } - diff --git a/src/exchangedb/pg_lookup_wire_timestamp.c b/src/exchangedb/pg_lookup_wire_timestamp.c index 19e915d48..17dffc706 100644 --- a/src/exchangedb/pg_lookup_wire_timestamp.c +++ b/src/exchangedb/pg_lookup_wire_timestamp.c @@ -28,8 +28,8 @@ enum GNUNET_DB_QueryStatus TEH_PG_lookup_wire_timestamp (void *cls, - const char *payto_uri, - struct GNUNET_TIME_Timestamp *last_date) + const char *payto_uri, + struct GNUNET_TIME_Timestamp *last_date) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { diff --git a/src/exchangedb/pg_lookup_wire_timestamp.h b/src/exchangedb/pg_lookup_wire_timestamp.h index 069dd940c..f2ee117de 100644 --- a/src/exchangedb/pg_lookup_wire_timestamp.h +++ b/src/exchangedb/pg_lookup_wire_timestamp.h @@ -34,7 +34,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_lookup_wire_timestamp (void *cls, - const char *payto_uri, + const char *payto_uri, struct GNUNET_TIME_Timestamp *last_date); #endif diff --git a/src/exchangedb/pg_profit_drains_get_pending.c b/src/exchangedb/pg_profit_drains_get_pending.c index a7044ebb8..f4a5d4517 100644 --- a/src/exchangedb/pg_profit_drains_get_pending.c +++ b/src/exchangedb/pg_profit_drains_get_pending.c @@ -57,7 +57,7 @@ TEH_PG_profit_drains_get_pending ( master_sig), GNUNET_PQ_result_spec_end }; - /* Used in #postgres_profit_drains_get_pending() */ + /* Used in #postgres_profit_drains_get_pending() */ PREPARE (pg, "get_ready_profit_drain", "SELECT" diff --git a/src/exchangedb/pg_profit_drains_set_finished.c b/src/exchangedb/pg_profit_drains_set_finished.c index b70af31fe..f0de27945 100644 --- a/src/exchangedb/pg_profit_drains_set_finished.c +++ b/src/exchangedb/pg_profit_drains_set_finished.c @@ -38,18 +38,12 @@ TEH_PG_profit_drains_set_finished ( }; PREPARE (pg, - "drain_profit_set_finished", - "UPDATE profit_drains" - " SET" - " executed=TRUE" - " WHERE profit_drain_serial_id=$1;"); + "drain_profit_set_finished", + "UPDATE profit_drains" + " SET" + " executed=TRUE" + " WHERE profit_drain_serial_id=$1;"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "drain_profit_set_finished", params); } - - - - - - diff --git a/src/exchangedb/pg_release_revolving_shard.c b/src/exchangedb/pg_release_revolving_shard.c index f176972b6..43e45c4bc 100644 --- a/src/exchangedb/pg_release_revolving_shard.c +++ b/src/exchangedb/pg_release_revolving_shard.c @@ -27,9 +27,9 @@ enum GNUNET_DB_QueryStatus TEH_PG_release_revolving_shard (void *cls, - const char *job_name, - uint32_t start_row, - uint32_t end_row) + const char *job_name, + uint32_t start_row, + uint32_t end_row) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { diff --git a/src/exchangedb/pg_release_revolving_shard.h b/src/exchangedb/pg_release_revolving_shard.h index f1712f538..ea65ab605 100644 --- a/src/exchangedb/pg_release_revolving_shard.h +++ b/src/exchangedb/pg_release_revolving_shard.h @@ -37,8 +37,8 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_release_revolving_shard (void *cls, - const char *job_name, - uint32_t start_row, + const char *job_name, + uint32_t start_row, uint32_t end_row); #endif diff --git a/src/exchangedb/pg_reserves_get.c b/src/exchangedb/pg_reserves_get.c index bea0022dd..d081ca00f 100644 --- a/src/exchangedb/pg_reserves_get.c +++ b/src/exchangedb/pg_reserves_get.c @@ -27,7 +27,7 @@ enum GNUNET_DB_QueryStatus TEH_PG_reserves_get (void *cls, - struct TALER_EXCHANGEDB_Reserve *reserve) + struct TALER_EXCHANGEDB_Reserve *reserve) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -43,7 +43,7 @@ TEH_PG_reserves_get (void *cls, &reserve->gc), GNUNET_PQ_result_spec_end }; - /* Used in #postgres_reserves_get() */ + /* Used in #postgres_reserves_get() */ PREPARE (pg, "reserves_get", "SELECT" diff --git a/src/exchangedb/pg_reserves_get_origin.c b/src/exchangedb/pg_reserves_get_origin.c index fd6c56586..55d3179d1 100644 --- a/src/exchangedb/pg_reserves_get_origin.c +++ b/src/exchangedb/pg_reserves_get_origin.c @@ -50,7 +50,7 @@ TEH_PG_reserves_get_origin ( " wire_source_h_payto" " FROM reserves_in" " WHERE reserve_pub=$1"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "get_h_wire_source_of_reserve", params, rs); diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c index 16d30d41c..e4d1b6e77 100644 --- a/src/exchangedb/pg_reserves_in_insert.c +++ b/src/exchangedb/pg_reserves_in_insert.c @@ -779,7 +779,8 @@ TEH_PG_reserves_in_insert (void *cls, &conflicts[i], &reserve_uuid[i], &results[i]); - fprintf(stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], conflicts[i], transaction_duplicate[i]); + fprintf (stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], + conflicts[i], transaction_duplicate[i]); if (qs2<0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, diff --git a/src/exchangedb/pg_reserves_update.c b/src/exchangedb/pg_reserves_update.c index 4a8861020..a76c37c27 100644 --- a/src/exchangedb/pg_reserves_update.c +++ b/src/exchangedb/pg_reserves_update.c @@ -27,7 +27,7 @@ enum GNUNET_DB_QueryStatus TEH_PG_reserves_update (void *cls, - const struct TALER_EXCHANGEDB_Reserve *reserve) + const struct TALER_EXCHANGEDB_Reserve *reserve) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { diff --git a/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.c b/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.c index abddab52f..d24c6245b 100644 --- a/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.c +++ b/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.c @@ -26,8 +26,6 @@ #include "pg_helper.h" - - /** * Closure for #get_kyc_amounts_cb(). */ @@ -112,7 +110,6 @@ get_kyc_amounts_cb (void *cls, } - enum GNUNET_DB_QueryStatus TEH_PG_select_aggregation_amounts_for_kyc_check ( void *cls, diff --git a/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.h b/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.h index 87fc8677a..b91740581 100644 --- a/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.h +++ b/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.h @@ -44,4 +44,5 @@ TEH_PG_select_aggregation_amounts_for_kyc_check ( struct GNUNET_TIME_Absolute time_limit, TALER_EXCHANGEDB_KycAmountCallback kac, void *kac_cls); + #endif diff --git a/src/exchangedb/pg_select_aggregation_transient.c b/src/exchangedb/pg_select_aggregation_transient.c index f3e39c532..d8d7ae701 100644 --- a/src/exchangedb/pg_select_aggregation_transient.c +++ b/src/exchangedb/pg_select_aggregation_transient.c @@ -49,7 +49,7 @@ TEH_PG_select_aggregation_transient ( wtid), GNUNET_PQ_result_spec_end }; - /* Used in #postgres_select_aggregation_transient() */ + /* Used in #postgres_select_aggregation_transient() */ PREPARE (pg, "select_aggregation_transient", "SELECT" diff --git a/src/exchangedb/pg_select_auditor_denom_sig.c b/src/exchangedb/pg_select_auditor_denom_sig.c index 90e0c5096..1dd6bd3d1 100644 --- a/src/exchangedb/pg_select_auditor_denom_sig.c +++ b/src/exchangedb/pg_select_auditor_denom_sig.c @@ -64,4 +64,3 @@ TEH_PG_select_auditor_denom_sig ( params, rs); } - diff --git a/src/exchangedb/pg_select_contract.c b/src/exchangedb/pg_select_contract.c index 4f4a525bd..3e6bf22bc 100644 --- a/src/exchangedb/pg_select_contract.c +++ b/src/exchangedb/pg_select_contract.c @@ -27,11 +27,11 @@ enum GNUNET_DB_QueryStatus TEH_PG_select_contract (void *cls, - const struct TALER_ContractDiffiePublicP *pub_ckey, - struct TALER_PurseContractPublicKeyP *purse_pub, - struct TALER_PurseContractSignatureP *econtract_sig, - size_t *econtract_size, - void **econtract) + const struct TALER_ContractDiffiePublicP *pub_ckey, + struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_PurseContractSignatureP *econtract_sig, + size_t *econtract_size, + void **econtract) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -49,15 +49,15 @@ TEH_PG_select_contract (void *cls, GNUNET_PQ_result_spec_end }; - /* Used in #postgres_select_contract */ + /* Used in #postgres_select_contract */ PREPARE (pg, - "select_contract", - "SELECT " - " purse_pub" - ",e_contract" - ",contract_sig" - " FROM contracts" - " WHERE pub_ckey=$1;"); + "select_contract", + "SELECT " + " purse_pub" + ",e_contract" + ",contract_sig" + " FROM contracts" + " WHERE pub_ckey=$1;"); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "select_contract", params, diff --git a/src/exchangedb/pg_select_contract.h b/src/exchangedb/pg_select_contract.h index a503c8da9..747a82753 100644 --- a/src/exchangedb/pg_select_contract.h +++ b/src/exchangedb/pg_select_contract.h @@ -38,10 +38,10 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_select_contract (void *cls, - const struct TALER_ContractDiffiePublicP *pub_ckey, - struct TALER_PurseContractPublicKeyP *purse_pub, - struct TALER_PurseContractSignatureP *econtract_sig, - size_t *econtract_size, + const struct TALER_ContractDiffiePublicP *pub_ckey, + struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_PurseContractSignatureP *econtract_sig, + size_t *econtract_size, void **econtract); #endif diff --git a/src/exchangedb/pg_select_contract_by_purse.c b/src/exchangedb/pg_select_contract_by_purse.c index aeeb56d48..8d29b3954 100644 --- a/src/exchangedb/pg_select_contract_by_purse.c +++ b/src/exchangedb/pg_select_contract_by_purse.c @@ -46,7 +46,7 @@ TEH_PG_select_contract_by_purse ( &econtract->econtract_size), GNUNET_PQ_result_spec_end }; - /* Used in #postgres_select_contract_by_purse */ + /* Used in #postgres_select_contract_by_purse */ PREPARE (pg, "select_contract_by_purse", "SELECT " diff --git a/src/exchangedb/pg_select_deposits_missing_wire.c b/src/exchangedb/pg_select_deposits_missing_wire.c index 2a260a369..e638c88e9 100644 --- a/src/exchangedb/pg_select_deposits_missing_wire.c +++ b/src/exchangedb/pg_select_deposits_missing_wire.c @@ -114,10 +114,10 @@ missing_wire_cb (void *cls, enum GNUNET_DB_QueryStatus TEH_PG_select_deposits_missing_wire (void *cls, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - TALER_EXCHANGEDB_WireMissingCallback cb, - void *cb_cls) + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + TALER_EXCHANGEDB_WireMissingCallback cb, + void *cb_cls) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -133,11 +133,11 @@ TEH_PG_select_deposits_missing_wire (void *cls, }; enum GNUNET_DB_QueryStatus qs; - /* Used in #postgres_select_deposits_missing_wire */ - // FIXME: used by the auditor; can probably be done - // smarter by checking if 'done' or 'blocked' - // are set correctly when going over deposits, instead - // of JOINing with refunds. + /* Used in #postgres_select_deposits_missing_wire */ + // FIXME: used by the auditor; can probably be done + // smarter by checking if 'done' or 'blocked' + // are set correctly when going over deposits, instead + // of JOINing with refunds. PREPARE (pg, "deposits_get_overdue", "SELECT" @@ -164,7 +164,6 @@ TEH_PG_select_deposits_missing_wire (void *cls, " ORDER BY wire_deadline ASC"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, "deposits_get_overdue", params, diff --git a/src/exchangedb/pg_select_deposits_missing_wire.h b/src/exchangedb/pg_select_deposits_missing_wire.h index f702c2417..40c592cee 100644 --- a/src/exchangedb/pg_select_deposits_missing_wire.h +++ b/src/exchangedb/pg_select_deposits_missing_wire.h @@ -38,9 +38,9 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_select_deposits_missing_wire (void *cls, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - TALER_EXCHANGEDB_WireMissingCallback cb, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + TALER_EXCHANGEDB_WireMissingCallback cb, void *cb_cls); #endif diff --git a/src/exchangedb/pg_select_history_requests_above_serial_id.c b/src/exchangedb/pg_select_history_requests_above_serial_id.c index 81e038114..36902e0ab 100644 --- a/src/exchangedb/pg_select_history_requests_above_serial_id.c +++ b/src/exchangedb/pg_select_history_requests_above_serial_id.c @@ -113,8 +113,6 @@ history_request_serial_helper_cb (void *cls, } - - enum GNUNET_DB_QueryStatus TEH_PG_select_history_requests_above_serial_id ( void *cls, diff --git a/src/exchangedb/pg_select_merge_amounts_for_kyc_check.c b/src/exchangedb/pg_select_merge_amounts_for_kyc_check.c index 5cb665fa8..b1bdd1450 100644 --- a/src/exchangedb/pg_select_merge_amounts_for_kyc_check.c +++ b/src/exchangedb/pg_select_merge_amounts_for_kyc_check.c @@ -26,7 +26,6 @@ #include "pg_helper.h" - /** * Closure for #get_kyc_amounts_cb(). */ @@ -132,7 +131,7 @@ TEH_PG_select_merge_amounts_for_kyc_check ( }; enum GNUNET_DB_QueryStatus qs; - + PREPARE (pg, "select_kyc_relevant_merge_events", "SELECT" @@ -157,4 +156,3 @@ TEH_PG_select_merge_amounts_for_kyc_check ( return GNUNET_DB_STATUS_HARD_ERROR; return qs; } - diff --git a/src/exchangedb/pg_select_purse_decisions_above_serial_id.c b/src/exchangedb/pg_select_purse_decisions_above_serial_id.c index 2368f2d3e..02e67197b 100644 --- a/src/exchangedb/pg_select_purse_decisions_above_serial_id.c +++ b/src/exchangedb/pg_select_purse_decisions_above_serial_id.c @@ -112,7 +112,6 @@ purse_decision_serial_helper_cb (void *cls, } - enum GNUNET_DB_QueryStatus TEH_PG_select_purse_decisions_above_serial_id ( void *cls, diff --git a/src/exchangedb/pg_select_purse_decisions_above_serial_id.h b/src/exchangedb/pg_select_purse_decisions_above_serial_id.h index 53ab31c80..83168d546 100644 --- a/src/exchangedb/pg_select_purse_decisions_above_serial_id.h +++ b/src/exchangedb/pg_select_purse_decisions_above_serial_id.h @@ -43,4 +43,5 @@ TEH_PG_select_purse_decisions_above_serial_id ( bool refunded, TALER_EXCHANGEDB_PurseDecisionCallback cb, void *cb_cls); + #endif diff --git a/src/exchangedb/pg_select_purse_merge.c b/src/exchangedb/pg_select_purse_merge.c index d1f6a5396..ce9f03618 100644 --- a/src/exchangedb/pg_select_purse_merge.c +++ b/src/exchangedb/pg_select_purse_merge.c @@ -56,7 +56,7 @@ TEH_PG_select_purse_merge ( }; *partner_url = NULL; - /* Used in #postgres_select_purse_merge */ + /* Used in #postgres_select_purse_merge */ PREPARE (pg, "select_purse_merge", "SELECT " diff --git a/src/exchangedb/pg_select_recoup_above_serial_id.c b/src/exchangedb/pg_select_recoup_above_serial_id.c index 9047a86f8..b2933fae3 100644 --- a/src/exchangedb/pg_select_recoup_above_serial_id.c +++ b/src/exchangedb/pg_select_recoup_above_serial_id.c @@ -26,7 +26,6 @@ #include "pg_helper.h" - /** * Closure for #recoup_serial_helper_cb(). */ @@ -137,6 +136,7 @@ recoup_serial_helper_cb (void *cls, } } + enum GNUNET_DB_QueryStatus TEH_PG_select_recoup_above_serial_id ( void *cls, @@ -157,7 +157,7 @@ TEH_PG_select_recoup_above_serial_id ( }; enum GNUNET_DB_QueryStatus qs; - /* Used in #postgres_select_recoup_above_serial_id() to obtain recoup transactions */ + /* Used in #postgres_select_recoup_above_serial_id() to obtain recoup transactions */ PREPARE (pg, "recoup_get_incr", "SELECT" diff --git a/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c index a3f6bc93d..c6fb62cc7 100644 --- a/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c +++ b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c @@ -141,7 +141,6 @@ recoup_refresh_serial_helper_cb (void *cls, } - enum GNUNET_DB_QueryStatus TEH_PG_select_recoup_refresh_above_serial_id ( void *cls, @@ -162,8 +161,8 @@ TEH_PG_select_recoup_refresh_above_serial_id ( }; enum GNUNET_DB_QueryStatus qs; - /* Used in #postgres_select_recoup_refresh_above_serial_id() to obtain - recoup-refresh transactions */ + /* Used in #postgres_select_recoup_refresh_above_serial_id() to obtain + recoup-refresh transactions */ PREPARE (pg, "recoup_refresh_get_incr", "SELECT" diff --git a/src/exchangedb/pg_select_refreshes_above_serial_id.c b/src/exchangedb/pg_select_refreshes_above_serial_id.c index d2b4a7fa6..401e6dcef 100644 --- a/src/exchangedb/pg_select_refreshes_above_serial_id.c +++ b/src/exchangedb/pg_select_refreshes_above_serial_id.c @@ -130,10 +130,6 @@ refreshs_serial_helper_cb (void *cls, } - - - - enum GNUNET_DB_QueryStatus TEH_PG_select_refreshes_above_serial_id ( void *cls, @@ -153,8 +149,8 @@ TEH_PG_select_refreshes_above_serial_id ( .status = GNUNET_OK }; enum GNUNET_DB_QueryStatus qs; - /* Used in #postgres_select_refreshes_above_serial_id() to fetch - refresh session with id '\geq' the given parameter */ + /* Used in #postgres_select_refreshes_above_serial_id() to fetch + refresh session with id '\geq' the given parameter */ PREPARE (pg, "audit_get_refresh_commitments_incr", "SELECT" diff --git a/src/exchangedb/pg_select_refunds_by_coin.h b/src/exchangedb/pg_select_refunds_by_coin.h index e1838b235..72df13fda 100644 --- a/src/exchangedb/pg_select_refunds_by_coin.h +++ b/src/exchangedb/pg_select_refunds_by_coin.h @@ -44,4 +44,5 @@ TEH_PG_select_refunds_by_coin ( const struct TALER_PrivateContractHashP *h_contract, TALER_EXCHANGEDB_RefundCoinCallback cb, void *cb_cls); + #endif diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id.c b/src/exchangedb/pg_select_reserves_in_above_serial_id.c index 1a6efc66b..8dd4a9aba 100644 --- a/src/exchangedb/pg_select_reserves_in_above_serial_id.c +++ b/src/exchangedb/pg_select_reserves_in_above_serial_id.c @@ -137,8 +137,8 @@ TEH_PG_select_reserves_in_above_serial_id ( }; enum GNUNET_DB_QueryStatus qs; - /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound - transactions for reserves with serial id '\geq' the given parameter */ + /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound + transactions for reserves with serial id '\geq' the given parameter */ PREPARE (pg, "audit_reserves_in_get_transactions_incr", "SELECT" 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 index ba73994f0..809df191b 100644 --- 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 @@ -138,8 +138,8 @@ TEH_PG_select_reserves_in_above_serial_id_by_account ( }; enum GNUNET_DB_QueryStatus qs; - /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound - transactions for reserves with serial id '\geq' the given parameter */ + /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound + transactions for reserves with serial id '\geq' the given parameter */ PREPARE (pg, "audit_reserves_in_get_transactions_incr_by_account", "SELECT" diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id.c b/src/exchangedb/pg_select_wire_out_above_serial_id.c index e219f5d4b..a9615ac8e 100644 --- a/src/exchangedb/pg_select_wire_out_above_serial_id.c +++ b/src/exchangedb/pg_select_wire_out_above_serial_id.c @@ -113,7 +113,6 @@ wire_out_serial_helper_cb (void *cls, } - enum GNUNET_DB_QueryStatus TEH_PG_select_wire_out_above_serial_id ( void *cls, @@ -133,7 +132,7 @@ TEH_PG_select_wire_out_above_serial_id ( .status = GNUNET_OK }; enum GNUNET_DB_QueryStatus qs; - /* Used in #postgres_select_wire_out_above_serial_id() */ + /* Used in #postgres_select_wire_out_above_serial_id() */ PREPARE (pg, "audit_get_wire_incr", "SELECT" 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 index 08883c9a4..a6c3f0730 100644 --- 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 @@ -112,6 +112,7 @@ wire_out_serial_helper_cb (void *cls, } } + enum GNUNET_DB_QueryStatus TEH_PG_select_wire_out_above_serial_id_by_account ( void *cls, @@ -134,7 +135,7 @@ TEH_PG_select_wire_out_above_serial_id_by_account ( }; enum GNUNET_DB_QueryStatus qs; - /* Used in #postgres_select_wire_out_above_serial_id_by_account() */ + /* Used in #postgres_select_wire_out_above_serial_id_by_account() */ PREPARE (pg, "audit_get_wire_incr_by_account", "SELECT" diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.h b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.h index 98315cace..04c6a62b2 100644 --- a/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.h +++ b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.h @@ -43,4 +43,5 @@ TEH_PG_select_wire_out_above_serial_id_by_account ( uint64_t serial_id, TALER_EXCHANGEDB_WireTransferOutCallback cb, void *cb_cls); + #endif diff --git a/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.c b/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.c index e200da8de..339fa3e23 100644 --- a/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.c +++ b/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.c @@ -131,21 +131,21 @@ TEH_PG_select_withdraw_amounts_for_kyc_check ( .status = GNUNET_OK }; enum GNUNET_DB_QueryStatus qs; - /* Used in #postgres_select_withdraw_amounts_for_kyc_check ( -() */ + /* Used in #postgres_select_withdraw_amounts_for_kyc_check ( + () */ PREPARE (pg, - "select_kyc_relevant_withdraw_events", - "SELECT" - " ro.amount_with_fee_val AS amount_val" - ",ro.amount_with_fee_frac AS amount_frac" - ",ro.execution_date AS date" - " FROM reserves_out ro" - " JOIN reserves_out_by_reserve USING (h_blind_ev)" - " JOIN reserves res ON (ro.reserve_uuid = res.reserve_uuid)" - " JOIN reserves_in ri ON (res.reserve_pub = ri.reserve_pub)" - " WHERE wire_source_h_payto=$1" - " AND ro.execution_date >= $2" - " ORDER BY ro.execution_date DESC"); + "select_kyc_relevant_withdraw_events", + "SELECT" + " ro.amount_with_fee_val AS amount_val" + ",ro.amount_with_fee_frac AS amount_frac" + ",ro.execution_date AS date" + " FROM reserves_out ro" + " JOIN reserves_out_by_reserve USING (h_blind_ev)" + " JOIN reserves res ON (ro.reserve_uuid = res.reserve_uuid)" + " JOIN reserves_in ri ON (res.reserve_pub = ri.reserve_pub)" + " WHERE wire_source_h_payto=$1" + " AND ro.execution_date >= $2" + " ORDER BY ro.execution_date DESC"); qs = GNUNET_PQ_eval_prepared_multi_select ( pg->conn, "select_kyc_relevant_withdraw_events", diff --git a/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.h b/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.h index 4c1283744..9a780adbe 100644 --- a/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.h +++ b/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.h @@ -44,4 +44,5 @@ TEH_PG_select_withdraw_amounts_for_kyc_check ( struct GNUNET_TIME_Absolute time_limit, TALER_EXCHANGEDB_KycAmountCallback kac, void *kac_cls); + #endif diff --git a/src/exchangedb/pg_select_withdrawals_above_serial_id.c b/src/exchangedb/pg_select_withdrawals_above_serial_id.c index 4718a62ae..b842b11aa 100644 --- a/src/exchangedb/pg_select_withdrawals_above_serial_id.c +++ b/src/exchangedb/pg_select_withdrawals_above_serial_id.c @@ -121,7 +121,6 @@ reserves_out_serial_helper_cb (void *cls, } - enum GNUNET_DB_QueryStatus TEH_PG_select_withdrawals_above_serial_id ( void *cls, @@ -142,7 +141,7 @@ TEH_PG_select_withdrawals_above_serial_id ( }; enum GNUNET_DB_QueryStatus qs; - /* Fetch deposits with rowid '\geq' the given parameter */ + /* Fetch deposits with rowid '\geq' the given parameter */ PREPARE (pg, "audit_get_reserves_out_incr", diff --git a/src/exchangedb/pg_select_withdrawals_above_serial_id.h b/src/exchangedb/pg_select_withdrawals_above_serial_id.h index adc23fb30..2b741a3b4 100644 --- a/src/exchangedb/pg_select_withdrawals_above_serial_id.h +++ b/src/exchangedb/pg_select_withdrawals_above_serial_id.h @@ -41,4 +41,5 @@ TEH_PG_select_withdrawals_above_serial_id ( uint64_t serial_id, TALER_EXCHANGEDB_WithdrawCallback cb, void *cb_cls); + #endif diff --git a/src/exchangedb/pg_set_extension_manifest.c b/src/exchangedb/pg_set_extension_manifest.c index 86e9d3f08..c7db04312 100644 --- a/src/exchangedb/pg_set_extension_manifest.c +++ b/src/exchangedb/pg_set_extension_manifest.c @@ -28,8 +28,8 @@ enum GNUNET_DB_QueryStatus TEH_PG_set_extension_manifest (void *cls, - const char *extension_name, - const char *manifest) + const char *extension_name, + const char *manifest) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam pcfg = diff --git a/src/exchangedb/pg_set_extension_manifest.h b/src/exchangedb/pg_set_extension_manifest.h index ead3abd28..0befeedd8 100644 --- a/src/exchangedb/pg_set_extension_manifest.h +++ b/src/exchangedb/pg_set_extension_manifest.h @@ -37,7 +37,7 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_set_extension_manifest (void *cls, - const char *extension_name, + const char *extension_name, const char *manifest); #endif diff --git a/src/exchangedb/pg_set_purse_balance.c b/src/exchangedb/pg_set_purse_balance.c index a996104bc..e955cb1cb 100644 --- a/src/exchangedb/pg_set_purse_balance.c +++ b/src/exchangedb/pg_set_purse_balance.c @@ -50,6 +50,3 @@ TEH_PG_set_purse_balance ( "set_purse_balance", params); } - - - diff --git a/src/exchangedb/pg_setup_wire_target.c b/src/exchangedb/pg_setup_wire_target.c index a2d890c50..ed6fbe338 100644 --- a/src/exchangedb/pg_setup_wire_target.c +++ b/src/exchangedb/pg_setup_wire_target.c @@ -26,7 +26,7 @@ enum GNUNET_DB_QueryStatus -TEH_PG_setup_wire_target( +TEH_PG_setup_wire_target ( struct PostgresClosure *pg, const char *payto_uri, struct TALER_PaytoHashP *h_payto) diff --git a/src/exchangedb/pg_setup_wire_target.h b/src/exchangedb/pg_setup_wire_target.h index 12c0e59b0..77512a600 100644 --- a/src/exchangedb/pg_setup_wire_target.h +++ b/src/exchangedb/pg_setup_wire_target.h @@ -35,7 +35,7 @@ * @return transaction status */ enum GNUNET_DB_QueryStatus -TEH_PG_setup_wire_target( +TEH_PG_setup_wire_target ( struct PostgresClosure *pg, const char *payto_uri, struct TALER_PaytoHashP *h_payto); diff --git a/src/exchangedb/pg_store_wire_transfer_out.c b/src/exchangedb/pg_store_wire_transfer_out.c index 8bc0147dd..b8b0bb692 100644 --- a/src/exchangedb/pg_store_wire_transfer_out.c +++ b/src/exchangedb/pg_store_wire_transfer_out.c @@ -44,7 +44,7 @@ TEH_PG_store_wire_transfer_out ( GNUNET_PQ_query_param_end }; - /* Used in #postgres_store_wire_transfer_out */ + /* Used in #postgres_store_wire_transfer_out */ PREPARE (pg, "insert_wire_out", "INSERT INTO wire_out " diff --git a/src/exchangedb/pg_update_aggregation_transient.c b/src/exchangedb/pg_update_aggregation_transient.c index 1d91301c3..c44cd67ec 100644 --- a/src/exchangedb/pg_update_aggregation_transient.c +++ b/src/exchangedb/pg_update_aggregation_transient.c @@ -26,7 +26,6 @@ #include "pg_helper.h" - enum GNUNET_DB_QueryStatus TEH_PG_update_aggregation_transient ( void *cls, @@ -45,7 +44,7 @@ TEH_PG_update_aggregation_transient ( }; - /* Used in #postgres_update_aggregation_transient() */ + /* Used in #postgres_update_aggregation_transient() */ PREPARE (pg, "update_aggregation_transient", "UPDATE aggregation_transient" diff --git a/src/exchangedb/pg_update_auditor.c b/src/exchangedb/pg_update_auditor.c index 9d82f25db..167a270b9 100644 --- a/src/exchangedb/pg_update_auditor.c +++ b/src/exchangedb/pg_update_auditor.c @@ -28,11 +28,11 @@ enum GNUNET_DB_QueryStatus TEH_PG_update_auditor (void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const char *auditor_url, - const char *auditor_name, - struct GNUNET_TIME_Timestamp change_date, - bool enabled) + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp change_date, + bool enabled) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -43,16 +43,16 @@ TEH_PG_update_auditor (void *cls, GNUNET_PQ_query_param_timestamp (&change_date), GNUNET_PQ_query_param_end }; - /* used in #postgres_update_auditor() */ - PREPARE(pg, - "update_auditor", - "UPDATE auditors" - " SET" - " auditor_url=$2" - " ,auditor_name=$3" - " ,is_active=$4" - " ,last_change=$5" - " WHERE auditor_pub=$1"); + /* used in #postgres_update_auditor() */ + PREPARE (pg, + "update_auditor", + "UPDATE auditors" + " SET" + " auditor_url=$2" + " ,auditor_name=$3" + " ,is_active=$4" + " ,last_change=$5" + " WHERE auditor_pub=$1"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "update_auditor", params); diff --git a/src/exchangedb/pg_update_auditor.h b/src/exchangedb/pg_update_auditor.h index af8d06062..ee869f8b7 100644 --- a/src/exchangedb/pg_update_auditor.h +++ b/src/exchangedb/pg_update_auditor.h @@ -38,10 +38,10 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_update_auditor (void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const char *auditor_url, - const char *auditor_name, - struct GNUNET_TIME_Timestamp change_date, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp change_date, bool enabled); #endif diff --git a/src/exchangedb/pg_update_wire.c b/src/exchangedb/pg_update_wire.c index f5f5672cb..4059348c9 100644 --- a/src/exchangedb/pg_update_wire.c +++ b/src/exchangedb/pg_update_wire.c @@ -28,9 +28,9 @@ enum GNUNET_DB_QueryStatus TEH_PG_update_wire (void *cls, - const char *payto_uri, - struct GNUNET_TIME_Timestamp change_date, - bool enabled) + const char *payto_uri, + struct GNUNET_TIME_Timestamp change_date, + bool enabled) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -40,7 +40,7 @@ TEH_PG_update_wire (void *cls, GNUNET_PQ_query_param_end }; - /* used in #postgres_update_wire() */ + /* used in #postgres_update_wire() */ PREPARE (pg, "update_wire", "UPDATE wire_accounts" diff --git a/src/exchangedb/pg_update_wire.h b/src/exchangedb/pg_update_wire.h index c01d68a46..67038b580 100644 --- a/src/exchangedb/pg_update_wire.h +++ b/src/exchangedb/pg_update_wire.h @@ -36,8 +36,8 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_update_wire (void *cls, - const char *payto_uri, - struct GNUNET_TIME_Timestamp change_date, + const char *payto_uri, + struct GNUNET_TIME_Timestamp change_date, bool enabled); #endif diff --git a/src/exchangedb/pg_wire_prepare_data_get.c b/src/exchangedb/pg_wire_prepare_data_get.c index d45413010..21d1b947a 100644 --- a/src/exchangedb/pg_wire_prepare_data_get.c +++ b/src/exchangedb/pg_wire_prepare_data_get.c @@ -99,10 +99,10 @@ prewire_cb (void *cls, enum GNUNET_DB_QueryStatus TEH_PG_wire_prepare_data_get (void *cls, - uint64_t start_row, - uint64_t limit, - TALER_EXCHANGEDB_WirePreparationIterator cb, - void *cb_cls) + uint64_t start_row, + uint64_t limit, + TALER_EXCHANGEDB_WirePreparationIterator cb, + void *cb_cls) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -118,7 +118,7 @@ TEH_PG_wire_prepare_data_get (void *cls, enum GNUNET_DB_QueryStatus qs; - /* Used in #postgres_wire_prepare_data_get() */ + /* Used in #postgres_wire_prepare_data_get() */ PREPARE (pg, "wire_prepare_data_get", "SELECT" diff --git a/src/exchangedb/pg_wire_prepare_data_get.h b/src/exchangedb/pg_wire_prepare_data_get.h index 91e21d27e..815c14bdf 100644 --- a/src/exchangedb/pg_wire_prepare_data_get.h +++ b/src/exchangedb/pg_wire_prepare_data_get.h @@ -38,8 +38,9 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_wire_prepare_data_get (void *cls, - uint64_t start_row, - uint64_t limit, - TALER_EXCHANGEDB_WirePreparationIterator cb, + uint64_t start_row, + uint64_t limit, + TALER_EXCHANGEDB_WirePreparationIterator cb, void *cb_cls); + #endif diff --git a/src/exchangedb/pg_wire_prepare_data_insert.c b/src/exchangedb/pg_wire_prepare_data_insert.c index 903f22a5b..919fccdaf 100644 --- a/src/exchangedb/pg_wire_prepare_data_insert.c +++ b/src/exchangedb/pg_wire_prepare_data_insert.c @@ -27,9 +27,9 @@ enum GNUNET_DB_QueryStatus TEH_PG_wire_prepare_data_insert (void *cls, - const char *type, - const char *buf, - size_t buf_size) + const char *type, + const char *buf, + size_t buf_size) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -39,15 +39,15 @@ TEH_PG_wire_prepare_data_insert (void *cls, }; - /* Used in #postgres_wire_prepare_data_insert() to store - wire transfer information before actually committing it with the bank */ + /* Used in #postgres_wire_prepare_data_insert() to store + wire transfer information before actually committing it with the bank */ PREPARE (pg, - "wire_prepare_data_insert", - "INSERT INTO prewire " - "(wire_method" - ",buf" - ") VALUES " - "($1, $2);"); + "wire_prepare_data_insert", + "INSERT INTO prewire " + "(wire_method" + ",buf" + ") VALUES " + "($1, $2);"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "wire_prepare_data_insert", params); diff --git a/src/exchangedb/pg_wire_prepare_data_insert.h b/src/exchangedb/pg_wire_prepare_data_insert.h index 2b6050d05..e73ee152d 100644 --- a/src/exchangedb/pg_wire_prepare_data_insert.h +++ b/src/exchangedb/pg_wire_prepare_data_insert.h @@ -36,7 +36,8 @@ */ enum GNUNET_DB_QueryStatus TEH_PG_wire_prepare_data_insert (void *cls, - const char *type, - const char *buf, + const char *type, + const char *buf, size_t buf_size); + #endif diff --git a/src/exchangedb/pg_wire_prepare_data_mark_failed.c b/src/exchangedb/pg_wire_prepare_data_mark_failed.c index fe2236b82..4e4d729a3 100644 --- a/src/exchangedb/pg_wire_prepare_data_mark_failed.c +++ b/src/exchangedb/pg_wire_prepare_data_mark_failed.c @@ -37,7 +37,7 @@ TEH_PG_wire_prepare_data_mark_failed ( GNUNET_PQ_query_param_end }; - /* Used in #postgres_wire_prepare_data_mark_failed() */ + /* Used in #postgres_wire_prepare_data_mark_failed() */ PREPARE (pg, "wire_prepare_data_mark_failed", diff --git a/src/exchangedb/pg_wire_prepare_data_mark_failed.h b/src/exchangedb/pg_wire_prepare_data_mark_failed.h index cae1523d1..98846b284 100644 --- a/src/exchangedb/pg_wire_prepare_data_mark_failed.h +++ b/src/exchangedb/pg_wire_prepare_data_mark_failed.h @@ -36,4 +36,5 @@ enum GNUNET_DB_QueryStatus TEH_PG_wire_prepare_data_mark_failed ( void *cls, uint64_t rowid); + #endif diff --git a/src/exchangedb/pg_wire_prepare_data_mark_finished.c b/src/exchangedb/pg_wire_prepare_data_mark_finished.c index de8738e40..af4a0fbbb 100644 --- a/src/exchangedb/pg_wire_prepare_data_mark_finished.c +++ b/src/exchangedb/pg_wire_prepare_data_mark_finished.c @@ -36,12 +36,12 @@ TEH_PG_wire_prepare_data_mark_finished ( GNUNET_PQ_query_param_end }; - /* Used in #postgres_wire_prepare_data_mark_finished() */ + /* Used in #postgres_wire_prepare_data_mark_finished() */ PREPARE (pg, - "wire_prepare_data_mark_done", - "UPDATE prewire" - " SET finished=TRUE" - " WHERE prewire_uuid=$1;"); + "wire_prepare_data_mark_done", + "UPDATE prewire" + " SET finished=TRUE" + " WHERE prewire_uuid=$1;"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "wire_prepare_data_mark_done", diff --git a/src/exchangedb/pg_wire_prepare_data_mark_finished.h b/src/exchangedb/pg_wire_prepare_data_mark_finished.h index 19db2ca99..ba2e384cd 100644 --- a/src/exchangedb/pg_wire_prepare_data_mark_finished.h +++ b/src/exchangedb/pg_wire_prepare_data_mark_finished.h @@ -36,4 +36,5 @@ enum GNUNET_DB_QueryStatus TEH_PG_wire_prepare_data_mark_finished ( void *cls, uint64_t rowid); + #endif diff --git a/src/exchangedb/test_exchangedb_by_j.c b/src/exchangedb/test_exchangedb_by_j.c index 9769d964b..24b24d5b0 100644 --- a/src/exchangedb/test_exchangedb_by_j.c +++ b/src/exchangedb/test_exchangedb_by_j.c @@ -74,8 +74,8 @@ static void run (void *cls) { static const unsigned int batches[] = {1, 2, 3, 4, 8, 16 }; - struct GNUNET_TIME_Relative times[sizeof (batches)/sizeof(*batches)]; - unsigned long long sqrs[sizeof (batches)/sizeof(*batches)]; + struct GNUNET_TIME_Relative times[sizeof (batches) / sizeof(*batches)]; + unsigned long long sqrs[sizeof (batches) / sizeof(*batches)]; struct GNUNET_CONFIGURATION_Handle *cfg = cls; const uint32_t num_partitions = 10; @@ -101,74 +101,75 @@ run (void *cls) memset (times, 0, sizeof (times)); memset (sqrs, 0, sizeof (sqrs)); for (unsigned int r = 0; r < ROUNDS; r++) - { + { for (unsigned int i = 0; i< 6; i++) + { + const char *sndr = "payto://x-taler-bank/localhost:8080/1"; + struct TALER_Amount value; + unsigned int batch_size = batches[i]; + unsigned int iterations = 16; // 1024*10; + struct TALER_ReservePublicKeyP reserve_pubs[iterations]; + struct GNUNET_TIME_Absolute now; + struct GNUNET_TIME_Timestamp ts; + struct GNUNET_TIME_Relative duration; + struct TALER_EXCHANGEDB_ReserveInInfo reserves[iterations]; + enum GNUNET_DB_QueryStatus results[iterations]; + unsigned long long duration_sq; + + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (CURRENCY ":1.000010", + &value)); + now = GNUNET_TIME_absolute_get (); + ts = GNUNET_TIME_timestamp_get (); + for (unsigned int r = 0; rbatch2_reserves_in_insert (plugin->cls, - reserves, - iterations, - batch_size, - results)); - duration = GNUNET_TIME_absolute_get_duration (now); - times[i] = GNUNET_TIME_relative_add (times[i], - duration); - duration_sq = duration.rel_value_us * duration.rel_value_us; - GNUNET_assert (duration_sq / duration.rel_value_us == duration.rel_value_us); - GNUNET_assert (sqrs[i] + duration_sq >= sqrs[i]); - sqrs[i] += duration_sq; - fprintf (stdout, - "for a batchsize equal to %d it took %s\n", - batch_size, - GNUNET_STRINGS_relative_time_to_string (duration, - GNUNET_NO) ); - - system ("./test.sh"); //DELETE AFTER TIMER + RND_BLK (&reserve_pubs[r]); + reserves[r].reserve_pub = &reserve_pubs[r]; + reserves[r].balance = &value; + reserves[r].execution_time = ts; + reserves[r].sender_account_details = sndr; + reserves[r].exchange_account_name = "name"; + reserves[r].wire_reference = r; } - } - for (unsigned int i = 0; i< 6; i++) - { - struct GNUNET_TIME_Relative avg; - double avg_dbl; - double variance; + FAILIF (iterations != + plugin->batch2_reserves_in_insert (plugin->cls, + reserves, + iterations, + batch_size, + results)); + duration = GNUNET_TIME_absolute_get_duration (now); + times[i] = GNUNET_TIME_relative_add (times[i], + duration); + duration_sq = duration.rel_value_us * duration.rel_value_us; + GNUNET_assert (duration_sq / duration.rel_value_us == + duration.rel_value_us); + GNUNET_assert (sqrs[i] + duration_sq >= sqrs[i]); + sqrs[i] += duration_sq; + fprintf (stdout, + "for a batchsize equal to %d it took %s\n", + batch_size, + GNUNET_STRINGS_relative_time_to_string (duration, + GNUNET_NO) ); - avg = GNUNET_TIME_relative_divide (times[i], - ROUNDS); - avg_dbl = avg.rel_value_us; - variance = sqrs[i] - (avg_dbl * avg_dbl * ROUNDS); - fprintf(stdout, - "Batch[%2u]: %8llu ± %6.0f\n", - batches[i], - (unsigned long long) avg.rel_value_us, - sqrt (variance / (ROUNDS-1))); + system ("./test.sh"); // DELETE AFTER TIMER } + } + for (unsigned int i = 0; i< 6; i++) + { + struct GNUNET_TIME_Relative avg; + double avg_dbl; + double variance; + + avg = GNUNET_TIME_relative_divide (times[i], + ROUNDS); + avg_dbl = avg.rel_value_us; + variance = sqrs[i] - (avg_dbl * avg_dbl * ROUNDS); + fprintf (stdout, + "Batch[%2u]: %8llu ± %6.0f\n", + batches[i], + (unsigned long long) avg.rel_value_us, + sqrt (variance / (ROUNDS - 1))); + } result = 0; drop: diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index cee8fb883..30d48833c 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -29,19 +29,17 @@ #include "taler_extensions_policy.h" - - struct TALER_EXCHANGEDB_CoinInfo { - uint64_t *known_coin_id; - struct TALER_DenominationHashP *denom_hash; - struct TALER_AgeCommitmentHash *h_age_commitment; - bool *existed; + uint64_t known_coin_id; + struct TALER_DenominationHashP denom_hash; + struct TALER_AgeCommitmentHash h_age_commitment; + bool existed; + bool denom_conflict; + bool age_conflict; }; - - /** * Information about a denomination key. */ @@ -900,21 +898,6 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData }; - - - - - - - - - - - - - - - /** * Signature of a function called with information about the exchange's * denomination keys. @@ -4055,10 +4038,10 @@ struct TALER_EXCHANGEDB_Plugin struct TALER_DenominationHashP *denom_pub_hash, struct TALER_AgeCommitmentHash *age_hash); - enum TALER_EXCHANGEDB_CoinKnownStatus + enum GNUNET_DB_QueryStatus (*batch_ensure_coin_known)(void *cls, const struct TALER_CoinPublicInfo *coin, - const struct + struct TALER_EXCHANGEDB_CoinInfo *result, unsigned int coin_length, unsigned int batch_size); From a30827fcef87af1c5a9707f31c58b7b69f7b9ae8 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 31 Mar 2023 14:03:12 +0200 Subject: [PATCH 11/50] -fix missing comments --- src/include/taler_exchangedb_plugin.h | 55 ++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 30d48833c..a0caf4f85 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -29,13 +29,43 @@ #include "taler_extensions_policy.h" +/** + * Per-coin information returned when doing a batch insert. + */ struct TALER_EXCHANGEDB_CoinInfo { + /** + * Row of the coin in the known_coins table. + */ uint64_t known_coin_id; + + /** + * Hash of the denomination, relevant on @e denom_conflict. + */ struct TALER_DenominationHashP denom_hash; + + /** + * Hash of the age commitment, relevant on @e age_conflict. + */ struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * True if the coin was known previously. + */ bool existed; + + /** + * True if the known coin has a different denomination; + * application will find denomination of the already + * known coin in @e denom_hash. + */ bool denom_conflict; + + /** + * True if the known coin has a different age restriction; + * application will find age commitment of the already + * known coin in @e h_age_commitment. + */ bool age_conflict; }; @@ -4038,13 +4068,26 @@ struct TALER_EXCHANGEDB_Plugin struct TALER_DenominationHashP *denom_pub_hash, struct TALER_AgeCommitmentHash *age_hash); + + /** + * Make sure the array of given @a coin is known to the database. + * + * @param cls database connection plugin state + * @param coin array of coins that must be made known + * @param[out] result array where to store information about each coin + * @param coin_length length of the @a coin and @a result arraysf + * @param batch_size desired (maximum) batch size + * @return database transaction status, non-negative on success + */ enum GNUNET_DB_QueryStatus - (*batch_ensure_coin_known)(void *cls, - const struct TALER_CoinPublicInfo *coin, - struct - TALER_EXCHANGEDB_CoinInfo *result, - unsigned int coin_length, - unsigned int batch_size); + (*batch_ensure_coin_known)( + void *cls, + const struct TALER_CoinPublicInfo *coin, + struct TALER_EXCHANGEDB_CoinInfo *result, + unsigned int coin_length, + unsigned int batch_size); + + /** * Retrieve information about the given @a coin from the database. * From e99450e2e2c28e6ae8c68b40e3f99d4a1ff3e63e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 31 Mar 2023 14:04:04 +0200 Subject: [PATCH 12/50] -fix missing comments --- src/exchangedb/pg_batch_ensure_coin_known.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/exchangedb/pg_batch_ensure_coin_known.h b/src/exchangedb/pg_batch_ensure_coin_known.h index a80f9d88b..2c53676d9 100644 --- a/src/exchangedb/pg_batch_ensure_coin_known.h +++ b/src/exchangedb/pg_batch_ensure_coin_known.h @@ -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 @@ -26,6 +26,16 @@ #include "taler_exchangedb_plugin.h" +/** + * Make sure the array of given @a coin is known to the database. + * + * @param cls database connection plugin state + * @param coin array of coins that must be made known + * @param[out] result array where to store information about each coin + * @param coin_length length of the @a coin and @a result arraysf + * @param batch_size desired (maximum) batch size + * @return database transaction status, non-negative on success + */ enum GNUNET_DB_QueryStatus TEH_PG_batch_ensure_coin_known ( void *cls, From 979ec38ec44bf223c6578bffd5201d2de18a89c7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 2 Apr 2023 14:12:13 +0200 Subject: [PATCH 13/50] left-pad TOTP code with 0s --- src/util/crypto_confirmation.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/crypto_confirmation.c b/src/util/crypto_confirmation.c index c5a674501..e52562e3e 100644 --- a/src/util/crypto_confirmation.c +++ b/src/util/crypto_confirmation.c @@ -189,7 +189,7 @@ executive_totp (void *h_key, if (NULL == ret) { GNUNET_asprintf (&ret, - "%llu", + "%08llu", (unsigned long long) code); } else @@ -197,7 +197,7 @@ executive_totp (void *h_key, char *tmp; GNUNET_asprintf (&tmp, - "%s\n%llu", + "%s\n%08llu", ret, (unsigned long long) code); GNUNET_free (ret); From d4f9417d8c5c4f533e1206554520d7a519ecd4d9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 4 Apr 2023 17:26:51 +0200 Subject: [PATCH 14/50] -spelling, typos, indentation --- src/exchangedb/spi/own_test.c | 493 ++++++++++++++++-------------- src/exchangedb/spi/pg_aggregate.c | 278 +++++++++-------- 2 files changed, 420 insertions(+), 351 deletions(-) diff --git a/src/exchangedb/spi/own_test.c b/src/exchangedb/spi/own_test.c index 10af02e31..7da89cbd2 100644 --- a/src/exchangedb/spi/own_test.c +++ b/src/exchangedb/spi/own_test.c @@ -19,145 +19,154 @@ PG_MODULE_MAGIC; #endif -typedef struct { +typedef struct +{ Datum col1; Datum col2; } valuest; -void _PG_init(void); -void _PG_fini(void); +void _PG_init (void); -void _PG_init(void) +void _PG_fini (void); + +void +_PG_init (void) { } -PG_FUNCTION_INFO_V1(pg_spi_insert_int); -PG_FUNCTION_INFO_V1(pg_spi_select_from_x); -PG_FUNCTION_INFO_V1(pg_spi_select_pair_from_y); -//PG_FUNCTION_INFO_V1(pg_spi_select_with_cond); -PG_FUNCTION_INFO_V1(pg_spi_update_y); -PG_FUNCTION_INFO_V1(pg_spi_prepare_example); -PG_FUNCTION_INFO_V1(pg_spi_prepare_example_without_saveplan); -PG_FUNCTION_INFO_V1(pg_spi_prepare_insert); -PG_FUNCTION_INFO_V1(pg_spi_prepare_insert_without_saveplan); -//PG_FUNCTION_INFO_V1(pg_spi_prepare_select_with_cond); -PG_FUNCTION_INFO_V1(pg_spi_prepare_select_with_cond_without_saveplan); -PG_FUNCTION_INFO_V1(pg_spi_prepare_update); -PG_FUNCTION_INFO_V1(pg_spi_get_dep_ref_fees); + +PG_FUNCTION_INFO_V1 (pg_spi_insert_int); +PG_FUNCTION_INFO_V1 (pg_spi_select_from_x); +PG_FUNCTION_INFO_V1 (pg_spi_select_pair_from_y); +// PG_FUNCTION_INFO_V1(pg_spi_select_with_cond); +PG_FUNCTION_INFO_V1 (pg_spi_update_y); +PG_FUNCTION_INFO_V1 (pg_spi_prepare_example); +PG_FUNCTION_INFO_V1 (pg_spi_prepare_example_without_saveplan); +PG_FUNCTION_INFO_V1 (pg_spi_prepare_insert); +PG_FUNCTION_INFO_V1 (pg_spi_prepare_insert_without_saveplan); +// PG_FUNCTION_INFO_V1(pg_spi_prepare_select_with_cond); +PG_FUNCTION_INFO_V1 (pg_spi_prepare_select_with_cond_without_saveplan); +PG_FUNCTION_INFO_V1 (pg_spi_prepare_update); +PG_FUNCTION_INFO_V1 (pg_spi_get_dep_ref_fees); // SIMPLE SELECT Datum -pg_spi_prepare_example(PG_FUNCTION_ARGS) +pg_spi_prepare_example (PG_FUNCTION_ARGS) { static SPIPlanPtr prepared_plan; int ret; int64 result; - char * value; + char *value; SPIPlanPtr new_plan; - ret=SPI_connect(); - if (ret != SPI_OK_CONNECT) { - elog(ERROR, "DB connexion failed ! \n"); + ret = SPI_connect (); + if (ret != SPI_OK_CONNECT) + { + elog (ERROR, "DB connection failed ! \n"); } { if (prepared_plan == NULL) { - new_plan = SPI_prepare("SELECT 1 FROM joseph_test.X", 0, NULL); - prepared_plan = SPI_saveplan(new_plan); + new_plan = SPI_prepare ("SELECT 1 FROM joseph_test.X", 0, NULL); + prepared_plan = SPI_saveplan (new_plan); if (prepared_plan == NULL) { - elog(ERROR, "FAIL TO SAVE !\n"); + elog (ERROR, "FAIL TO SAVE !\n"); } } - ret = SPI_execute_plan(prepared_plan, NULL, 0,false, 0); - if (ret != SPI_OK_SELECT) { - elog(ERROR, "SELECT FAILED %d !\n", ret); + ret = SPI_execute_plan (prepared_plan, NULL, 0,false, 0); + if (ret != SPI_OK_SELECT) + { + elog (ERROR, "SELECT FAILED %d !\n", ret); } - if (SPI_tuptable != NULL && SPI_tuptable->vals != NULL && SPI_tuptable->tupdesc != NULL) + if (SPI_tuptable != NULL && SPI_tuptable->vals != NULL && + SPI_tuptable->tupdesc != NULL) { - value = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1); - result = atoi(value); + value = SPI_getvalue (SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1); + result = atoi (value); } else { - elog(ERROR, "EMPTY TABLE !\n"); + elog (ERROR, "EMPTY TABLE !\n"); } } - SPI_finish(); - PG_RETURN_INT64(result); + SPI_finish (); + PG_RETURN_INT64 (result); } - Datum -pg_spi_prepare_example_without_saveplan(PG_FUNCTION_ARGS) +pg_spi_prepare_example_without_saveplan (PG_FUNCTION_ARGS) { int ret; int64 result; - char * value; + char *value; SPIPlanPtr new_plan; - ret=SPI_connect(); - if (ret != SPI_OK_CONNECT) { - elog(ERROR, "DB connexion failed ! \n"); + ret = SPI_connect (); + if (ret != SPI_OK_CONNECT) + { + elog (ERROR, "DB connection failed ! \n"); } { - new_plan = SPI_prepare("SELECT 1 FROM joseph_test.X", 0, NULL); - ret = SPI_execute_plan(new_plan, NULL, 0,false, 0); - if (ret != SPI_OK_SELECT) { - elog(ERROR, "SELECT FAILED %d !\n", ret); + new_plan = SPI_prepare ("SELECT 1 FROM joseph_test.X", 0, NULL); + ret = SPI_execute_plan (new_plan, NULL, 0,false, 0); + if (ret != SPI_OK_SELECT) + { + elog (ERROR, "SELECT FAILED %d !\n", ret); } if (SPI_tuptable != NULL && SPI_tuptable->vals != NULL && SPI_tuptable->tupdesc != NULL) { - value = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1); - result = atoi(value); + value = SPI_getvalue (SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1); + result = atoi (value); } else { - elog(ERROR, "EMPTY TABLE !\n"); + elog (ERROR, "EMPTY TABLE !\n"); } } - SPI_finish(); - PG_RETURN_INT64(result);// PG_RETURN_INT64(result); + SPI_finish (); + PG_RETURN_INT64 (result);// PG_RETURN_INT64(result); } -//SELECT 1 FROM X -//V1 +// SELECT 1 FROM X +// V1 Datum -pg_spi_select_from_x(PG_FUNCTION_ARGS) +pg_spi_select_from_x (PG_FUNCTION_ARGS) { int ret; char *query = "SELECT 1 FROM joseph_test.X"; uint64 proc; - ret = SPI_connect(); + ret = SPI_connect (); if (ret != SPI_OK_CONNECT) { - elog(ERROR, "SPI_connect failed"); + elog (ERROR, "SPI_connect failed"); } - ret = SPI_exec(query, 10); + ret = SPI_exec (query, 10); proc = SPI_processed; if (ret != SPI_OK_SELECT) { - elog(ERROR, "SPI_exec failed"); + elog (ERROR, "SPI_exec failed"); } - SPI_finish(); + SPI_finish (); - PG_RETURN_INT64(proc); + PG_RETURN_INT64 (proc); } -//INSERT INTO X VALUES (1) + +// INSERT INTO X VALUES (1) Datum -pg_spi_insert_int(PG_FUNCTION_ARGS) +pg_spi_insert_int (PG_FUNCTION_ARGS) { int ret; int nargs; @@ -165,30 +174,30 @@ pg_spi_insert_int(PG_FUNCTION_ARGS) Datum values[1]; char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; - ret = SPI_connect(); + ret = SPI_connect (); if (ret != SPI_OK_CONNECT) { - elog(ERROR, "SPI_connect failed"); + elog (ERROR, "SPI_connect failed"); } nargs = 1; argtypes[0] = INT4OID; - values[0] = Int32GetDatum(3); + values[0] = Int32GetDatum (3); - ret = SPI_execute_with_args(query, nargs, argtypes, values, NULL, false, 0); + ret = SPI_execute_with_args (query, nargs, argtypes, values, NULL, false, 0); if (ret != SPI_OK_INSERT) { - elog(ERROR, "SPI_execute_with_args failed"); + elog (ERROR, "SPI_execute_with_args failed"); } - SPI_finish(); + SPI_finish (); - PG_RETURN_VOID(); + PG_RETURN_VOID (); } Datum -pg_spi_prepare_insert(PG_FUNCTION_ARGS) +pg_spi_prepare_insert (PG_FUNCTION_ARGS) { static SPIPlanPtr prepared_plan = NULL; int ret; @@ -197,38 +206,41 @@ pg_spi_prepare_insert(PG_FUNCTION_ARGS) Datum values[1]; char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; SPIPlanPtr new_plan; - ret = SPI_connect(); + ret = SPI_connect (); if (ret != SPI_OK_CONNECT) { - elog(ERROR, "SPI_connect failed ! \n"); + elog (ERROR, "SPI_connect failed ! \n"); } - if (prepared_plan == NULL) { + if (prepared_plan == NULL) + { argtypes[0] = INT4OID; nargs = 1; - values[0] = Int32GetDatum(3); - new_plan = SPI_prepare(query, nargs, argtypes); + values[0] = Int32GetDatum (3); + new_plan = SPI_prepare (query, nargs, argtypes); if (new_plan== NULL) { - elog(ERROR, "SPI_prepare failed ! \n"); + elog (ERROR, "SPI_prepare failed ! \n"); } - prepared_plan = SPI_saveplan(new_plan); + prepared_plan = SPI_saveplan (new_plan); if (prepared_plan == NULL) { - elog(ERROR, "SPI_saveplan failed ! \n"); + elog (ERROR, "SPI_saveplan failed ! \n"); } } - ret = SPI_execute_plan(prepared_plan, values, NULL, false, 0); + ret = SPI_execute_plan (prepared_plan, values, NULL, false, 0); if (ret != SPI_OK_INSERT) { - elog(ERROR, "SPI_execute_plan failed ! \n"); + elog (ERROR, "SPI_execute_plan failed ! \n"); } - SPI_finish(); + SPI_finish (); - PG_RETURN_VOID(); + PG_RETURN_VOID (); } + + /* Datum pg_spi_prepare_insert_bytea(PG_FUNCTION_ARGS) @@ -278,7 +290,7 @@ pg_spi_prepare_insert_bytea(PG_FUNCTION_ARGS) */ Datum -pg_spi_prepare_insert_without_saveplan(PG_FUNCTION_ARGS) +pg_spi_prepare_insert_without_saveplan (PG_FUNCTION_ARGS) { int ret; int nargs; @@ -286,38 +298,34 @@ pg_spi_prepare_insert_without_saveplan(PG_FUNCTION_ARGS) Datum values[1]; char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; SPIPlanPtr new_plan; - ret = SPI_connect(); + ret = SPI_connect (); if (ret != SPI_OK_CONNECT) { - elog(ERROR, "SPI_connect failed"); + elog (ERROR, "SPI_connect failed"); } { argtypes[0] = INT4OID; nargs = 1; - values[0] = Int32GetDatum(3); - new_plan = SPI_prepare(query, nargs, argtypes); + values[0] = Int32GetDatum (3); + new_plan = SPI_prepare (query, nargs, argtypes); if (new_plan== NULL) { - elog(ERROR, "SPI_prepare failed"); + elog (ERROR, "SPI_prepare failed"); } } - ret = SPI_execute_plan(new_plan, values, NULL, false, 0); + ret = SPI_execute_plan (new_plan, values, NULL, false, 0); if (ret != SPI_OK_INSERT) { - elog(ERROR, "SPI_execute_plan failed"); + elog (ERROR, "SPI_execute_plan failed"); } - SPI_finish(); + SPI_finish (); - PG_RETURN_VOID(); + PG_RETURN_VOID (); } - - - - /* Datum pg_spi_select_pair_from_y(PG_FUNCTION_ARGS) @@ -349,7 +357,7 @@ pg_spi_select_pair_from_y(PG_FUNCTION_ARGS) } */ -//SELECT X FROM Y WHERE Z=$1 +// SELECT X FROM Y WHERE Z=$1 /* Datum pg_spi_select_with_cond(PG_FUNCTION_ARGS) @@ -443,7 +451,9 @@ Datum pg_spi_prepare_select_with_cond(PG_FUNCTION_ARGS) { } */ -Datum pg_spi_prepare_select_with_cond_without_saveplan(PG_FUNCTION_ARGS) { +Datum +pg_spi_prepare_select_with_cond_without_saveplan (PG_FUNCTION_ARGS) +{ SPIPlanPtr new_plan; int ret; @@ -454,54 +464,56 @@ Datum pg_spi_prepare_select_with_cond_without_saveplan(PG_FUNCTION_ARGS) { char *query = "SELECT col1 FROM joseph_test.Y WHERE col2 = $1"; int result = 0; - ret = SPI_connect(); + ret = SPI_connect (); if (ret != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed ! \n"); + elog (ERROR, "SPI_connect failed ! \n"); { argtypes[0] = INT4OID; nargs = 1; - values[0] = Int32GetDatum(2); //Value col2 + values[0] = Int32GetDatum (2); // Value col2 - new_plan = SPI_prepare(query, nargs, argtypes); + new_plan = SPI_prepare (query, nargs, argtypes); if (new_plan == NULL) - elog(ERROR, "SPI_prepare failed ! \n"); + elog (ERROR, "SPI_prepare failed ! \n"); } - ret = SPI_execute_plan(new_plan, values, NULL, false, 0); + ret = SPI_execute_plan (new_plan, values, NULL, false, 0); - if (ret != SPI_OK_SELECT) { - elog(ERROR, "SPI_execute_plan failed: %d \n", ret); - } + if (ret != SPI_OK_SELECT) + { + elog (ERROR, "SPI_execute_plan failed: %d \n", ret); + } proc = SPI_processed; - if (proc > 0) { + if (proc > 0) + { SPITupleTable *tuptable = SPI_tuptable; TupleDesc tupdesc = tuptable->tupdesc; HeapTuple tuple; int i; - for (i = 0; i < proc; i++) { + for (i = 0; i < proc; i++) + { tuple = tuptable->vals[i]; - for (int j = 1; j <= tupdesc->natts; j++) { - char * value = SPI_getvalue(tuple, tupdesc, j); - result += atoi(value); + for (int j = 1; j <= tupdesc->natts; j++) + { + char *value = SPI_getvalue (tuple, tupdesc, j); + result += atoi (value); } } } - SPI_finish(); - PG_RETURN_INT64(result); + SPI_finish (); + PG_RETURN_INT64 (result); } - - Datum -pg_spi_update_y(PG_FUNCTION_ARGS) +pg_spi_update_y (PG_FUNCTION_ARGS) { int ret; int nargs; @@ -509,34 +521,30 @@ pg_spi_update_y(PG_FUNCTION_ARGS) Datum values[1]; char *query = "UPDATE joseph_test.Y SET col1 = 4 WHERE (col2 = $1)"; - ret = SPI_connect(); + ret = SPI_connect (); if (ret != SPI_OK_CONNECT) { - elog(ERROR, "SPI_connect failed ! \n"); + elog (ERROR, "SPI_connect failed ! \n"); } nargs = 1; argtypes[0] = INT4OID; - values[0] = Int32GetDatum(0); + values[0] = Int32GetDatum (0); - ret = SPI_execute_with_args(query, nargs, argtypes, values, NULL, false, 0); + ret = SPI_execute_with_args (query, nargs, argtypes, values, NULL, false, 0); if (ret != SPI_OK_UPDATE) { - elog(ERROR, "SPI_execute_with_args failed ! \n"); + elog (ERROR, "SPI_execute_with_args failed ! \n"); } - SPI_finish(); + SPI_finish (); - PG_RETURN_VOID(); + PG_RETURN_VOID (); } - - - - Datum -pg_spi_prepare_update(PG_FUNCTION_ARGS) +pg_spi_prepare_update (PG_FUNCTION_ARGS) { static SPIPlanPtr prepared_plan = NULL; SPIPlanPtr new_plan; @@ -546,60 +554,63 @@ pg_spi_prepare_update(PG_FUNCTION_ARGS) Datum values[1]; char *query = "UPDATE joseph_test.Y SET col1 = 4 WHERE (col2 = $1)"; - ret = SPI_connect(); + ret = SPI_connect (); if (ret != SPI_OK_CONNECT) { - elog(ERROR, "SPI_connect failed ! \n"); + elog (ERROR, "SPI_connect failed ! \n"); } - if ( prepared_plan == NULL) + if (prepared_plan == NULL) { argtypes[0] = INT4OID; nargs = 1; - values[0] = Int32GetDatum(3); - //PREPARE - new_plan = SPI_prepare(query, nargs, argtypes); + values[0] = Int32GetDatum (3); + // PREPARE + new_plan = SPI_prepare (query, nargs, argtypes); if (new_plan == NULL) - elog(ERROR, "SPI_prepare failed ! \n"); - //SAVEPLAN - prepared_plan = SPI_saveplan(new_plan); - if(prepared_plan == NULL) - elog(ERROR, "SPI_saveplan failed ! \n"); + elog (ERROR, "SPI_prepare failed ! \n"); + // SAVEPLAN + prepared_plan = SPI_saveplan (new_plan); + if (prepared_plan == NULL) + elog (ERROR, "SPI_saveplan failed ! \n"); } - ret = SPI_execute_plan(prepared_plan, values, NULL, false, 0); + ret = SPI_execute_plan (prepared_plan, values, NULL, false, 0); if (ret != SPI_OK_UPDATE) - elog(ERROR, "SPI_execute_plan failed ! \n"); + elog (ERROR, "SPI_execute_plan failed ! \n"); - SPI_finish(); - PG_RETURN_VOID(); + SPI_finish (); + PG_RETURN_VOID (); } + + /* Datum pg_spi_prepare_update_without_saveplan(PG_FUNCTION_ARGS) {}*/ -void _PG_fini(void) +void +_PG_fini (void) { } + /* */ - - Datum -pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) { +pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) +{ /* Define plan to save */ static SPIPlanPtr deposit_plan; static SPIPlanPtr ref_plan; static SPIPlanPtr fees_plan; static SPIPlanPtr dummy_plan; /* Define variables to update */ - Timestamp refund_deadline = PG_GETARG_TIMESTAMP(0); - bytea *merchant_pub = PG_GETARG_BYTEA_P(1); - bytea *wire_target_h_payto = PG_GETARG_BYTEA_P(2); - bytea *wtid_raw = PG_GETARG_BYTEA_P(3); + Timestamp refund_deadline = PG_GETARG_TIMESTAMP (0); + bytea *merchant_pub = PG_GETARG_BYTEA_P (1); + bytea *wire_target_h_payto = PG_GETARG_BYTEA_P (2); + bytea *wtid_raw = PG_GETARG_BYTEA_P (3); bool is_null; /* Define variables to store the results of each SPI query */ uint64_t sum_deposit_val = 0; @@ -632,11 +643,12 @@ pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) { bytea *norm_ref_by_coin_coin_pub; int64_t norm_ref_by_coin_deposit_serial_id = 0; bytea *new_dep_coin_pub = NULL; - int res = SPI_connect(); + int res = SPI_connect (); /* Connect to SPI */ - if (res < 0) { - elog(ERROR, "Could not connect to SPI manager"); + if (res < 0) + { + elog (ERROR, "Could not connect to SPI manager"); } if (deposit_plan == NULL) { @@ -655,74 +667,98 @@ pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) { "coin_pub," "amount_with_fee_val," "amount_with_fee_frac;"; - fprintf(stderr, "dep sql %d\n", 1); + fprintf (stderr, "dep sql %d\n", 1); new_plan = - SPI_prepare(dep_sql, 4,(Oid[]){INT8OID, BYTEAOID, BYTEAOID}); - fprintf(stderr, "dep sql %d\n", 2); + SPI_prepare (dep_sql, 4,(Oid[]){INT8OID, BYTEAOID, BYTEAOID}); + fprintf (stderr, "dep sql %d\n", 2); if (new_plan == NULL) - elog(ERROR, "SPI_prepare failed for dep \n"); - deposit_plan = SPI_saveplan(new_plan); + elog (ERROR, "SPI_prepare failed for dep \n"); + deposit_plan = SPI_saveplan (new_plan); if (deposit_plan == NULL) - elog(ERROR, "SPI_saveplan failed for dep \n"); + elog (ERROR, "SPI_saveplan failed for dep \n"); } - fprintf(stdout, "dep sql %d\n", 3); + fprintf (stdout, "dep sql %d\n", 3); - values_deposit[0] = Int64GetDatum(refund_deadline); - values_deposit[1] = PointerGetDatum(merchant_pub); - values_deposit[2] = PointerGetDatum(wire_target_h_payto); + values_deposit[0] = Int64GetDatum (refund_deadline); + values_deposit[1] = PointerGetDatum (merchant_pub); + values_deposit[2] = PointerGetDatum (wire_target_h_payto); res = SPI_execute_plan (deposit_plan, values_deposit, NULL, true, 0); - fprintf(stdout, "dep sql %d\n", 4); + fprintf (stdout, "dep sql %d\n", 4); if (res != SPI_OK_UPDATE) { - elog(ERROR, "Failed to execute subquery 1 \n"); + elog (ERROR, "Failed to execute subquery 1 \n"); } // STORE TUPTABLE deposit dep_res = SPI_tuptable; - for (unsigned int i = 0; i < SPI_processed; i++) { - int64 dep_deposit_serial_ids = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &is_null)); - bytea *dep_coin_pub = DatumGetByteaP(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &is_null)); - int64 dep_amount_val = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 3, &is_null)); - int32 dep_amount_frac = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 4, &is_null)); + for (unsigned int i = 0; i < SPI_processed; i++) + { + int64 dep_deposit_serial_ids = DatumGetInt64 (SPI_getbinval ( + SPI_tuptable->vals[i], + SPI_tuptable->tupdesc, 1, + &is_null)); + bytea *dep_coin_pub = DatumGetByteaP (SPI_getbinval (SPI_tuptable->vals[i], + SPI_tuptable->tupdesc, + 2, &is_null)); + int64 dep_amount_val = DatumGetInt64 (SPI_getbinval (SPI_tuptable->vals[i], + SPI_tuptable->tupdesc, + 3, &is_null)); + int32 dep_amount_frac = DatumGetInt32 (SPI_getbinval (SPI_tuptable->vals[i], + SPI_tuptable->tupdesc, + 4, &is_null)); if (is_null) - elog(ERROR, "Failed to retrive data from deposit \n"); + elog (ERROR, "Failed to retrieve data from deposit \n"); if (ref_plan == NULL) { // Execute second query with parameters from first query and store results in variables - const char * ref_sql = + const char *ref_sql = "SELECT amount_with_fee_val, amount_with_fee_frac, coin_pub, deposit_serial_id " "FROM refunds " "WHERE coin_pub=$1 " "AND deposit_serial_id=$2;"; - SPIPlanPtr new_plan = SPI_prepare(ref_sql, 3, (Oid[]){BYTEAOID, INT8OID}); + SPIPlanPtr new_plan = SPI_prepare (ref_sql, 3, (Oid[]){BYTEAOID, + INT8OID}); if (new_plan == NULL) - elog(ERROR, "SPI_prepare failed for refund\n"); - ref_plan = SPI_saveplan(new_plan); + elog (ERROR, "SPI_prepare failed for refund\n"); + ref_plan = SPI_saveplan (new_plan); if (ref_plan == NULL) - elog(ERROR, "SPI_saveplan failed for refund\n"); + elog (ERROR, "SPI_saveplan failed for refund\n"); } - values_refund[0] = PointerGetDatum(dep_coin_pub); - values_refund[1] = Int64GetDatum(dep_deposit_serial_ids); - res = SPI_execute_plan(ref_plan, - values_refund, - NULL, - false, - 0); + values_refund[0] = PointerGetDatum (dep_coin_pub); + values_refund[1] = Int64GetDatum (dep_deposit_serial_ids); + res = SPI_execute_plan (ref_plan, + values_refund, + NULL, + false, + 0); if (res != SPI_OK_SELECT) - elog(ERROR, "Failed to execute subquery 2\n"); + elog (ERROR, "Failed to execute subquery 2\n"); // STORE TUPTABLE refund ref_res = SPI_tuptable; - for (unsigned int j = 0; j < SPI_processed; j++) { - int64 ref_refund_val = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 1, &is_null)); - int32 ref_refund_frac = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 2, &is_null)); - bytea *ref_coin_pub = DatumGetByteaP(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 3, &is_null)); - int64 ref_deposit_serial_id = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 4, &is_null)); + for (unsigned int j = 0; j < SPI_processed; j++) + { + int64 ref_refund_val = DatumGetInt64 (SPI_getbinval ( + SPI_tuptable->vals[j], + SPI_tuptable->tupdesc, 1, + &is_null)); + int32 ref_refund_frac = DatumGetInt32 (SPI_getbinval ( + SPI_tuptable->vals[j], + SPI_tuptable->tupdesc, 2, + &is_null)); + bytea *ref_coin_pub = DatumGetByteaP (SPI_getbinval ( + SPI_tuptable->vals[j], + SPI_tuptable->tupdesc, 3, + &is_null)); + int64 ref_deposit_serial_id = DatumGetInt64 (SPI_getbinval ( + SPI_tuptable->vals[j], + SPI_tuptable->tupdesc, 4, + &is_null)); // Execute third query with parameters from second query and store results in variables ref_by_coin_coin_pub = ref_coin_pub; ref_by_coin_deposit_serial_id = ref_deposit_serial_id; @@ -730,10 +766,14 @@ pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) { for (unsigned int i = 0; ivals[i], SPI_tuptable->tupdesc, 1, &is_null))) + DatumGetByteaP (SPI_getbinval (SPI_tuptable->vals[i], + SPI_tuptable->tupdesc, 1, + &is_null))) && (ref_by_coin_deposit_serial_id == - DatumGetUInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &is_null))) + DatumGetUInt64 (SPI_getbinval (SPI_tuptable->vals[i], + SPI_tuptable->tupdesc, 2, + &is_null))) ) { sum_refund_val += ref_refund_val; @@ -742,15 +782,15 @@ pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) { norm_ref_by_coin_deposit_serial_id = ref_by_coin_deposit_serial_id; } }// END SUM CALCULATION - //NORMALIZE REFUND VAL FRAC + // NORMALIZE REFUND VAL FRAC norm_refund_val = - (sum_refund_val + sum_refund_frac ) / 100000000; + (sum_refund_val + sum_refund_frac) / 100000000; norm_refund_frac = sum_refund_frac % 100000000; // Get refund values s_refund_val += sum_refund_val; s_refund_frac = sum_refund_frac; - }//END REFUND + }// END REFUND if (norm_ref_by_coin_coin_pub == dep_coin_pub && ref_by_coin_deposit_serial_id == dep_deposit_serial_ids && norm_refund_val == dep_amount_val @@ -759,40 +799,46 @@ pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) { new_dep_coin_pub = dep_coin_pub; } // Ensure we get the fee for each coin and not only once per denomination - if (fees_plan == NULL ) + if (fees_plan == NULL) { - const char * fees_sql = + const char *fees_sql = "SELECT " " denom.fee_deposit_val AS fee_val, " " denom.fee_deposit_frac AS fee_frac, " "FROM known_coins kc" "JOIN denominations denom USING (denominations_serial) " "WHERE kc.coin_pub = $1 AND kc.coin_pub != $2;"; - SPIPlanPtr new_plan = SPI_prepare(fees_sql, 3, (Oid[]){BYTEAOID, BYTEAOID}); + SPIPlanPtr new_plan = SPI_prepare (fees_sql, 3, (Oid[]){BYTEAOID, + BYTEAOID}); if (new_plan == NULL) - { - elog(ERROR, "SPI_prepare for fees failed ! \n"); - } - fees_plan = SPI_saveplan(new_plan); + { + elog (ERROR, "SPI_prepare for fees failed ! \n"); + } + fees_plan = SPI_saveplan (new_plan); if (fees_plan == NULL) - { - elog(ERROR, "SPI_saveplan for fees failed ! \n"); - } + { + elog (ERROR, "SPI_saveplan for fees failed ! \n"); + } } - values_fees[0] = PointerGetDatum(dep_coin_pub); - values_fees[1] = PointerGetDatum(new_dep_coin_pub); - res = SPI_execute_plan(fees_plan, values_fees, NULL, false, 0); + values_fees[0] = PointerGetDatum (dep_coin_pub); + values_fees[1] = PointerGetDatum (new_dep_coin_pub); + res = SPI_execute_plan (fees_plan, values_fees, NULL, false, 0); if (res != SPI_OK_SELECT) - elog(ERROR, "SPI_execute_plan failed for fees \n"); + elog (ERROR, "SPI_execute_plan failed for fees \n"); fees_res = SPI_tuptable; tupdesc = fees_res->tupdesc; for (unsigned int i = 0; ivals[i]; bool is_null; - uint64_t fee_val = DatumGetUInt64(SPI_getbinval(tuple, tupdesc, 1, &is_null)); - uint32_t fee_frac = DatumGetUInt32(SPI_getbinval(tuple, tupdesc, 2, &is_null)); - uint64_t fees_deposit_serial_id = DatumGetUInt64(SPI_getbinval(tuple, tupdesc, 3, &is_null)); + uint64_t fee_val = DatumGetUInt64 (SPI_getbinval (tuple, tupdesc, 1, + &is_null)); + uint32_t fee_frac = DatumGetUInt32 (SPI_getbinval (tuple, tupdesc, 2, + &is_null)); + uint64_t fees_deposit_serial_id = DatumGetUInt64 (SPI_getbinval (tuple, + tupdesc, + 3, + &is_null)); if (dummy_plan == NULL) { const char *insert_dummy_sql = @@ -800,18 +846,19 @@ pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) { "aggregation_tracking(deposit_serial_id, wtid_raw)" " VALUES ($1, $2)"; - SPIPlanPtr new_plan = SPI_prepare(insert_dummy_sql, 2, (Oid[]){INT8OID, BYTEAOID}); + SPIPlanPtr new_plan = SPI_prepare (insert_dummy_sql, 2, (Oid[]){INT8OID, + BYTEAOID}); if (new_plan == NULL) - elog(ERROR, "FAILED to prepare aggregation tracking \n"); - dummy_plan = SPI_saveplan(new_plan); - if ( dummy_plan == NULL ) - elog(ERROR, "FAILED to saveplan aggregation tracking\n"); + elog (ERROR, "FAILED to prepare aggregation tracking \n"); + dummy_plan = SPI_saveplan (new_plan); + if (dummy_plan == NULL) + elog (ERROR, "FAILED to saveplan aggregation tracking\n"); } - values_dummys[0] = Int64GetDatum(dep_deposit_serial_ids); - values_dummys[1] = PointerGetDatum(wtid_raw); - res = SPI_execute_plan(dummy_plan, values_dummys, NULL, false, 0); + values_dummys[0] = Int64GetDatum (dep_deposit_serial_ids); + values_dummys[1] = PointerGetDatum (wtid_raw); + res = SPI_execute_plan (dummy_plan, values_dummys, NULL, false, 0); if (res != SPI_OK_INSERT) - elog(ERROR, "Failed to insert dummy\n"); + elog (ERROR, "Failed to insert dummy\n"); dummys_res = SPI_tuptable; // Calculation of deposit fees for not fully refunded deposits sum_dep_fee_val += fee_val; @@ -820,7 +867,7 @@ pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) { // Get deposit values sum_deposit_val += dep_amount_val; sum_deposit_frac += dep_amount_frac; - }//END DEPOSIT - SPI_finish(); - PG_RETURN_VOID(); + }// END DEPOSIT + SPI_finish (); + PG_RETURN_VOID (); } diff --git a/src/exchangedb/spi/pg_aggregate.c b/src/exchangedb/spi/pg_aggregate.c index 262100ce8..721f247c7 100644 --- a/src/exchangedb/spi/pg_aggregate.c +++ b/src/exchangedb/spi/pg_aggregate.c @@ -6,9 +6,10 @@ PG_MODULE_MAGIC; -PG_FUNCTION_INFO_V1(get_deposit_summary); +PG_FUNCTION_INFO_V1 (get_deposit_summary); -Datum get_deposit_summary(PG_FUNCTION_ARGS) +Datum +get_deposit_summary (PG_FUNCTION_ARGS) { static SPIPlanPtr deposit_plan; @@ -18,24 +19,25 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) static SPIPlanPtr fully_refunded_by_coins_plan; static SPIPlanPtr fees_plan; - int shard = PG_GETARG_INT32(0); - char * sql; - char *merchant_pub = text_to_cstring(PG_GETARG_TEXT_P(1)); - char *wire_target_h_payto = text_to_cstring(PG_GETARG_TEXT_P(2)); - char *wtid_raw = text_to_cstring(PG_GETARG_TEXT_P(3)); - int refund_deadline = PG_GETARG_INT32(4); - int conn = SPI_connect(); + int shard = PG_GETARG_INT32 (0); + char *sql; + char *merchant_pub = text_to_cstring (PG_GETARG_TEXT_P (1)); + char *wire_target_h_payto = text_to_cstring (PG_GETARG_TEXT_P (2)); + char *wtid_raw = text_to_cstring (PG_GETARG_TEXT_P (3)); + int refund_deadline = PG_GETARG_INT32 (4); + int conn = SPI_connect (); if (conn != SPI_OK_CONNECT) { - elog(ERROR, "DB connexion failed ! \n"); + elog (ERROR, "DB connection failed ! \n"); } - if ( deposit_plan == NULL - || refund_plan == NULL - || refund_by_coin_plan == NULL - || norm_refund_by_coin_plan = NULL - || fully_refunded_coins_plan = NULL - || fees_plan == NULL ) + if (deposit_plan == NULL + || refund_plan == NULL + || refund_by_coin_plan == NULL + || norm_refund_by_coin_plan = NULL + || fully_refunded_coins_plan = NULL + || fees_plan + == NULL) { if (deposit_plan == NULL) { @@ -57,22 +59,22 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) " ,amount_with_fee_val AS amount_val" " ,amount_with_fee_frac AS amount_frac"; SPIPlanPtr new_plan = - SPI_prepare(dep_sql, 4, argtypes}); + SPI_prepare (dep_sql, 4, argtypes); if (new_plan == NULL) { - elog(ERROR, "SPI_prepare for deposit failed ! \n"); + elog (ERROR, "SPI_prepare for deposit failed ! \n"); } - deposit_plan = SPI_saveplan(new_plan); + deposit_plan = SPI_saveplan (new_plan); if (deposit_plan == NULL) { - elog(ERROR, "SPI_saveplan for deposit failed ! \n"); + elog (ERROR, "SPI_saveplan for deposit failed ! \n"); } } Datum values[4]; - values[0] = Int64GetDatum(refund_deadline); - values[1] = CStringGetDatum(merchant_pub); - values[2] = CStringGetDatum(wire_target_h_payto); + values[0] = Int64GetDatum (refund_deadline); + values[1] = CStringGetDatum (merchant_pub); + values[2] = CStringGetDatum (wire_target_h_payto); int ret = SPI_execute_plan (deposit_plan, values, NULL, @@ -80,22 +82,24 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) 0); if (ret != SPI_OK_UPDATE) { - elog(ERROR, "Failed to execute subquery 1\n"); + elog (ERROR, "Failed to execute subquery 1\n"); } - uint64_t *dep_deposit_serial_ids = palloc(sizeof(uint64_t) * SPI_processed); - BYTEA **dep_coin_pubs = palloc(sizeof(BYTEA *) * SPI_processed); - uint64_t *dep_amount_vals = palloc(sizeof(uint64_t) * SPI_processed); - uint32_t *dep_amount_fracs = palloc(sizeof(uint32_t) * SPI_processed); - for (unsigned int i = 0; i < SPI_processed; i++) { + uint64_t *dep_deposit_serial_ids = palloc (sizeof(uint64_t) + * SPI_processed); + BYTEA **dep_coin_pubs = palloc (sizeof(BYTEA *) * SPI_processed); + uint64_t *dep_amount_vals = palloc (sizeof(uint64_t) * SPI_processed); + uint32_t *dep_amount_fracs = palloc (sizeof(uint32_t) * SPI_processed); + for (unsigned int i = 0; i < SPI_processed; i++) + { HeapTuple tuple = SPI_tuptable->vals[i]; dep_deposit_serial_ids[i] = - DatumGetInt64(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 1, &ret)); + DatumGetInt64 (SPI_getbinval (tuple, SPI_tuptable->tupdesc, 1, &ret)); dep_coin_pubs[i] = - DatumGetByteaP(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 2, &ret)); + DatumGetByteaP (SPI_getbinval (tuple, SPI_tuptable->tupdesc, 2, &ret)); dep_amount_vals[i] = - DatumGetInt64(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 3, &ret)); + DatumGetInt64 (SPI_getbinval (tuple, SPI_tuptable->tupdesc, 3, &ret)); dep_amount_fracs[i] = - DatumGetInt32(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 4, &ret)); + DatumGetInt32 (SPI_getbinval (tuple, SPI_tuptable->tupdesc, 4, &ret)); } @@ -111,45 +115,47 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) " FROM refunds" " WHERE coin_pub IN (SELECT coin_pub FROM dep)" " AND deposit_serial_id IN (SELECT deposit_serial_id FROM dep)) "; - SPIPlanPtr new_plan = SPI_prepare(ref_sql, 0, NULL); + SPIPlanPtr new_plan = SPI_prepare (ref_sql, 0, NULL); if (new_plan == NULL) elog (ERROR, "SPI_prepare for refund failed ! \n"); - refund_plan = SPI_saveplan(new_plan); + refund_plan = SPI_saveplan (new_plan); if (refund_plan == NULL) { - elog(ERROR, "SPI_saveplan for refund failed ! \n"); + elog (ERROR, "SPI_saveplan for refund failed ! \n"); } } - int64t_t *ref_deposit_serial_ids = palloc(sizeof(int64_t) * SPI_processed); + int64t_t *ref_deposit_serial_ids = palloc (sizeof(int64_t) * SPI_processed); int res = SPI_execute_plan (refund_plan, NULL, NULL, false, 0); if (res != SPI_OK_SELECT) { - elog(ERROR, "Failed to execute subquery 2\n"); + elog (ERROR, "Failed to execute subquery 2\n"); } SPITupleTable *tuptable = SPI_tuptable; TupleDesc tupdesc = tuptable->tupdesc; for (unsigned int i = 0; i < SPI_processed; i++) { HeapTuple tuple = tuptable->vals[i]; - Datum refund_val = SPI_getbinval(tuple, tupdesc, 1, &refund_val_isnull); - Datum refund_frac = SPI_getbinval(tuple, tupdesc, 2, &refund_frac_isnull); - Datum coin_pub = SPI_getbinval(tuple, tupdesc, 3, &coin_pub_isnull); - Datum deposit_serial_id = SPI_getbinval(tuple, tupdesc, 4, &deposit_serial_id_isnull); + Datum refund_val = SPI_getbinval (tuple, tupdesc, 1, &refund_val_isnull); + Datum refund_frac = SPI_getbinval (tuple, tupdesc, 2, + &refund_frac_isnull); + Datum coin_pub = SPI_getbinval (tuple, tupdesc, 3, &coin_pub_isnull); + Datum deposit_serial_id = SPI_getbinval (tuple, tupdesc, 4, + &deposit_serial_id_isnull); if (refund_val_isnull || refund_frac_isnull || coin_pub_isnull - || deposit_serial_id_isnull ) + || deposit_serial_id_isnull) { - elog(ERROR, "Failed to retrieve data from subquery 2"); + elog (ERROR, "Failed to retrieve data from subquery 2"); } - uint64_t refund_val_int = DatumGetUInt64(refund_val); - uint32_t refund_frac_int = DatumGetUInt32(refund_frac); - BYTEA coin_pub = DatumGetByteaP(coin_pub); - ref_deposit_serial_ids = DatumGetInt64(deposit_serial_id); + uint64_t refund_val_int = DatumGetUInt64 (refund_val); + uint32_t refund_frac_int = DatumGetUInt32 (refund_frac); + BYTEA coin_pub = DatumGetByteaP (coin_pub); + ref_deposit_serial_ids = DatumGetInt64 (deposit_serial_id); - refund *new_refund = (refund*) palloc(sizeof(refund)); + refund *new_refund = (refund*) palloc (sizeof(refund)); new_refund->coin_pub = coin_pub_str; new_refund->deposit_serial_id = deposit_serial_id_int; new_refund->amount_with_fee_val = refund_val_int; @@ -170,17 +176,17 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) " GROUP BY coin_pub, deposit_serial_id) "; SPIPlanPtr new_plan = SPI_prepare (ref_by_coin_sql, 0, NULL); if (new_plan == NULL) - elog(ERROR, "SPI_prepare for refund by coin failed ! \n"); + elog (ERROR, "SPI_prepare for refund by coin failed ! \n"); refund_by_coin_plan = SPI_saveplan (new_plan); if (refund_by_coin_plan == NULL) - elog(ERROR, "SPI_saveplan for refund failed"); + elog (ERROR, "SPI_saveplan for refund failed"); } int res = SPI_execute_plan (refund_by_coin_plan, NULL, NULL, false, 0); if (res != SPI_OK_SELECT) { - elog(ERROR, "Failed to execute subquery 2\n"); + elog (ERROR, "Failed to execute subquery 2\n"); } SPITupleTable *tuptable = SPI_tuptable; @@ -188,22 +194,25 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) for (unsigned int i = 0; i < SPI_processed; i++) { HeapTuple tuple = tuptable->vals[i]; - Datum sum_refund_val = SPI_getbinval(tuple, tupdesc, 1, &refund_val_isnull); - Datum sum_refund_frac = SPI_getbinval(tuple, tupdesc, 2, &refund_frac_isnull); - Datum coin_pub = SPI_getbinval(tuple, tupdesc, 3, &coin_pub_isnull); - Datum deposit_serial_id_int = SPI_getbinval(tuple, tupdesc, 4, &deposit_serial_id_isnull); + Datum sum_refund_val = SPI_getbinval (tuple, tupdesc, 1, + &refund_val_isnull); + Datum sum_refund_frac = SPI_getbinval (tuple, tupdesc, 2, + &refund_frac_isnull); + Datum coin_pub = SPI_getbinval (tuple, tupdesc, 3, &coin_pub_isnull); + Datum deposit_serial_id_int = SPI_getbinval (tuple, tupdesc, 4, + &deposit_serial_id_isnull); if (refund_val_isnull || refund_frac_isnull || coin_pub_isnull - || deposit_serial_id_isnull ) + || deposit_serial_id_isnull) { - elog(ERROR, "Failed to retrieve data from subquery 2"); + elog (ERROR, "Failed to retrieve data from subquery 2"); } - uint64_t s_refund_val_int = DatumGetUInt64(sum_refund_val); - uint32_t s_refund_frac_int = DatumGetUInt32(sum_refund_frac); - BYTEA coin_pub = DatumGetByteaP(coin_pub); - uint64_t deposit_serial_id_int = DatumGetInt64(deposit_serial_id_int); - refund *new_refund_by_coin = (refund*) palloc(sizeof(refund)); + uint64_t s_refund_val_int = DatumGetUInt64 (sum_refund_val); + uint32_t s_refund_frac_int = DatumGetUInt32 (sum_refund_frac); + BYTEA coin_pub = DatumGetByteaP (coin_pub); + uint64_t deposit_serial_id_int = DatumGetInt64 (deposit_serial_id_int); + refund *new_refund_by_coin = (refund*) palloc (sizeof(refund)); new_refund_by_coin->coin_pub = coin_pub; new_refund_by_coin->deposit_serial_id = deposit_serial_id_int; new_refund_by_coin->refund_amount_with_fee_val = s_refund_val_int; @@ -221,17 +230,17 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) " FROM ref_by_coin) "; SPIPlanPtr new_plan = SPI_prepare (norm_ref_by_coin_sql, 0, NULL); if (new_plan == NULL) - elog(ERROR, "SPI_prepare for norm refund by coin failed ! \n"); - norm_refund_by_coin_plan = SPI_saveplan(new_plan); + elog (ERROR, "SPI_prepare for norm refund by coin failed ! \n"); + norm_refund_by_coin_plan = SPI_saveplan (new_plan); if (norm_refund_by_coin_plan == NULL) - elog(ERROR, "SPI_saveplan for norm refund by coin failed ! \n"); + elog (ERROR, "SPI_saveplan for norm refund by coin failed ! \n"); } double norm_refund_val = - ((double)new_refund_by_coin->refund_amount_with_fee_val - + (double)new_refund_by_coin->refund_amount_with_fee_frac) / 100000000; + ((double) new_refund_by_coin->refund_amount_with_fee_val + + (double) new_refund_by_coin->refund_amount_with_fee_frac) / 100000000; double norm_refund_frac = - (double)new_refund_by_coin->refund_amount_with_fee_frac % 100000000; + (double) new_refund_by_coin->refund_amount_with_fee_frac % 100000000; if (fully_refunded_coins_plan == NULL) { @@ -246,21 +255,21 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) " AND norm.norm_refund_val = dep.amount_val" " AND norm.norm_refund_frac = dep.amount_frac)) "; SPIPlanPtr new_plan = - SPI_prepare(fully_refunded_coins_sql, 0, NULL); + SPI_prepare (fully_refunded_coins_sql, 0, NULL); if (new_plan == NULL) elog (ERROR, "SPI_prepare for fully refunded coins failed ! \n"); - fully_refunded_coins_plan = SPI_saveplan(new_plan); + fully_refunded_coins_plan = SPI_saveplan (new_plan); if (fully_refunded_coins_plan == NULL) elog (ERROR, "SPI_saveplan for fully refunded coins failed ! \n"); } - int res = SPI_execute_plan(fully_refunded_coins_sql); - if ( res != SPI_OK_SELECT) - elog(ERROR, "Failed to execute subquery 4\n"); - SPITupleTable * tuptable = SPI_tuptable; + int res = SPI_execute_plan (fully_refunded_coins_sql); + if (res != SPI_OK_SELECT) + elog (ERROR, "Failed to execute subquery 4\n"); + SPITupleTable *tuptable = SPI_tuptable; TupleDesc tupdesc = tuptable->tupdesc; - BYTEA coin_pub = SPI_getbinval(tuple, tupdesc, 1, &coin_pub_isnull); + BYTEA coin_pub = SPI_getbinval (tuple, tupdesc, 1, &coin_pub_isnull); if (fees_plan == NULL) { const char *fees_sql = @@ -273,26 +282,27 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) "JOIN denominations denom USING (denominations_serial) " "WHERE coin_pub NOT IN (SELECT coin_pub FROM fully_refunded_coins)"; SPIPlanPtr new_plan = - SPI_prepare(fees_sql, 0, NULL); + SPI_prepare (fees_sql, 0, NULL); if (new_plan == NULL) { - elog(ERROR, "SPI_prepare for fees failed ! \n"); + elog (ERROR, "SPI_prepare for fees failed ! \n"); } - fees_plan = SPI_saveplan(new_plan); + fees_plan = SPI_saveplan (new_plan); if (fees_plan == NULL) { - elog(ERROR, "SPI_saveplan for fees failed ! \n"); + elog (ERROR, "SPI_saveplan for fees failed ! \n"); } } } int fees_ntuples; - SPI_execute(fees_sql, true, 0); - if (SPI_result_code() != SPI_OK_SELECT) + SPI_execute (fees_sql, true, 0); + if (SPI_result_code () != SPI_OK_SELECT) { - ereport( - ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("deposit fee query failed: error code %d \n", SPI_result_code()))); + ereport ( + ERROR, + (errcode (ERRCODE_INTERNAL_ERROR), + errmsg ("deposit fee query failed: error code %d \n", + SPI_result_code ()))); } fees_ntuples = SPI_processed; @@ -301,25 +311,28 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) for (i = 0; i < fees_ntuples; i++) { Datum fee_val_datum = - SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &fee_null); + SPI_getbinval (SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, + &fee_null); Datum fee_frac_datum = - SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &fee_null); + SPI_getbinval (SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, + &fee_null); Datum deposit_id_datum = - SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 3, &deposit_null); - if (!fee_null && !deposit_null) + SPI_getbinval (SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 3, + &deposit_null); + if (! fee_null && ! deposit_null) { - int64 fee_val = DatumGetInt64(fee_val_datum); - int32 fee_frac = DatumGetInt32(fee_frac_datum); - int64 deposit_id = DatumGetInt64(deposit_id_datum); + int64 fee_val = DatumGetInt64 (fee_val_datum); + int32 fee_frac = DatumGetInt32 (fee_frac_datum); + int64 deposit_id = DatumGetInt64 (deposit_id_datum); sum_fee_value += fee_val; sum_fee_fraction += fee_frac; char *insert_agg_sql = - psprintf( - "INSERT INTO " - "aggregation_tracking(deposit_serial_id, wtid_raw)" - " VALUES (%lld, '%s')", - deposit_id, wtid_raw); - SPI_execute(insert_agg_sql, false, 0); + psprintf ( + "INSERT INTO " + "aggregation_tracking(deposit_serial_id, wtid_raw)" + " VALUES (%lld, '%s')", + deposit_id, wtid_raw); + SPI_execute (insert_agg_sql, false, 0); } } } @@ -331,33 +344,39 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) if (tuptable == NULL || SPI_processed != 1) { - ereport( - ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("Unexpected result \n"))); + ereport ( + ERROR, + (errcode (ERRCODE_INTERNAL_ERROR), + errmsg ("Unexpected result \n"))); } tupdesc = SPI_tuptable->tupdesc; tuple = SPI_tuptable->vals[0]; - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetDatum (tuple); - TupleDesc result_desc = CreateTemplateTupleDesc(6, false); - TupleDescInitEntry(result_desc, (AttrNumber) 1, "sum_deposit_value", INT8OID, -1, 0); - TupleDescInitEntry(result_desc, (AttrNumber) 2, "sum_deposit_fraction", INT4OID, -1, 0); - TupleDescInitEntry(result_desc, (AttrNumber) 3, "sum_refund_value", INT8OID, -1, 0); - TupleDescInitEntry(result_desc, (AttrNumber) 4, "sum_refund_fraction", INT4OID, -1, 0); - TupleDescInitEntry(result_desc, (AttrNumber) 5, "sum_fee_value", INT8OID, -1, 0); - TupleDescInitEntry(result_desc, (AttrNumber) 6, "sum_fee_fraction", INT4OID, -1, 0); + TupleDesc result_desc = CreateTemplateTupleDesc (6, false); + TupleDescInitEntry (result_desc, (AttrNumber) 1, "sum_deposit_value", INT8OID, + -1, 0); + TupleDescInitEntry (result_desc, (AttrNumber) 2, "sum_deposit_fraction", + INT4OID, -1, 0); + TupleDescInitEntry (result_desc, (AttrNumber) 3, "sum_refund_value", INT8OID, + -1, 0); + TupleDescInitEntry (result_desc, (AttrNumber) 4, "sum_refund_fraction", + INT4OID, -1, 0); + TupleDescInitEntry (result_desc, (AttrNumber) 5, "sum_fee_value", INT8OID, -1, + 0); + TupleDescInitEntry (result_desc, (AttrNumber) 6, "sum_fee_fraction", INT4OID, + -1, 0); - int ret = SPI_prepare(sql, 4, argtypes); + int ret = SPI_prepare (sql, 4, argtypes); if (ret != SPI_OK_PREPARE) { - elog(ERROR, "Failed to prepare statement: %s \n", sql); + elog (ERROR, "Failed to prepare statement: %s \n", sql); } - ret = SPI_execute_plan(plan, args, nulls, true, 0); + ret = SPI_execute_plan (plan, args, nulls, true, 0); if (ret != SPI_OK_SELECT) { - elog(ERROR, "Failed to execute statement: %s \n", sql); + elog (ERROR, "Failed to execute statement: %s \n", sql); } if (SPI_processed > 0) @@ -366,24 +385,27 @@ Datum get_deposit_summary(PG_FUNCTION_ARGS) Datum values[6]; bool nulls[6] = {false}; values[0] = - SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &nulls[0]); + SPI_getbinval (SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, + &nulls[0]); values[1] = - SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 2, &nulls[1]); + SPI_getbinval (SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 2, + &nulls[1]); values[2] = - SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 3, &nulls[2]); + SPI_getbinval (SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 3, + &nulls[2]); values[3] = - SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 4, &nulls[3]); + SPI_getbinval (SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 4, + &nulls[3]); values[4] = - SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 5, &nulls[4]); + SPI_getbinval (SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 5, + &nulls[4]); values[5] = - SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 6, &nulls[5]); - tuple = heap_form_tuple(result_desc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); + SPI_getbinval (SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 6, + &nulls[5]); + tuple = heap_form_tuple (result_desc, values, nulls); + PG_RETURN_DATUM (HeapTupleGetDatum (tuple)); } - SPI_finish(); + SPI_finish (); - PG_RETURN_NULL(); + PG_RETURN_NULL (); } - - - From 36b2cbb47e6cbb9b658abea34ea6cc37d90a1336 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 6 Apr 2023 23:46:39 +0200 Subject: [PATCH 15/50] modify logic to match https://datatracker.ietf.org/doc/draft-nottingham-http-availability-hints/ --- src/mhd/mhd_legal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mhd/mhd_legal.c b/src/mhd/mhd_legal.c index 25435210e..37042a563 100644 --- a/src/mhd/mhd_legal.c +++ b/src/mhd/mhd_legal.c @@ -257,7 +257,7 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn, char *tmp = langs; GNUNET_asprintf (&langs, - "%s %s", + "%s,%s", tmp, p->language); GNUNET_free (tmp); @@ -327,7 +327,7 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn, { GNUNET_break (MHD_YES == MHD_add_response_header (resp, - "Acceptable-Languages", + "Avail-Languages", langs)); GNUNET_free (langs); } From 3137d8dc13742055e0857b249037fe0430bf9578 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 8 Apr 2023 08:10:56 +0200 Subject: [PATCH 16/50] adding FIXME --- src/exchangedb/exchange_do_deposit.sql | 1 + src/exchangedb/pg_do_deposit.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/exchangedb/exchange_do_deposit.sql b/src/exchangedb/exchange_do_deposit.sql index a2f5ba53a..53fcfb1bc 100644 --- a/src/exchangedb/exchange_do_deposit.sql +++ b/src/exchangedb/exchange_do_deposit.sql @@ -123,6 +123,7 @@ THEN -- Deposit exists, but with differences. Not allowed. out_balance_ok=FALSE; out_conflict=TRUE; + -- FIXME: out_exchange_timestamp not set on this path? RETURN; END IF; diff --git a/src/exchangedb/pg_do_deposit.c b/src/exchangedb/pg_do_deposit.c index 771c50af3..f3d0856ac 100644 --- a/src/exchangedb/pg_do_deposit.c +++ b/src/exchangedb/pg_do_deposit.c @@ -25,6 +25,8 @@ #include "pg_do_deposit.h" #include "pg_helper.h" #include "pg_compute_shard.h" + + enum GNUNET_DB_QueryStatus TEH_PG_do_deposit ( void *cls, @@ -69,8 +71,6 @@ TEH_PG_do_deposit ( GNUNET_PQ_result_spec_end }; - /* Used in #postgres_do_deposit() to execute a deposit, - checking the coin's balance in the process as needed. */ PREPARE (pg, "call_deposit", "SELECT " From cbabddf013fea1c6b86782b3843ff0ccbcba0bd7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 8 Apr 2023 08:29:30 +0200 Subject: [PATCH 17/50] fix #7792 --- src/exchangedb/exchange_do_deposit.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/exchangedb/exchange_do_deposit.sql b/src/exchangedb/exchange_do_deposit.sql index 53fcfb1bc..6e522b354 100644 --- a/src/exchangedb/exchange_do_deposit.sql +++ b/src/exchangedb/exchange_do_deposit.sql @@ -123,7 +123,7 @@ THEN -- Deposit exists, but with differences. Not allowed. out_balance_ok=FALSE; out_conflict=TRUE; - -- FIXME: out_exchange_timestamp not set on this path? + out_exchange_timestamp=0; RETURN; END IF; From 677ac4a5c8570115134cda7537c1580bce15e5c4 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 8 Apr 2023 09:46:00 +0200 Subject: [PATCH 18/50] return text/plain by default (fixes #7747) --- src/mhd/mhd_legal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mhd/mhd_legal.c b/src/mhd/mhd_legal.c index 37042a563..2c4127117 100644 --- a/src/mhd/mhd_legal.c +++ b/src/mhd/mhd_legal.c @@ -232,7 +232,7 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn, MHD_HEADER_KIND, MHD_HTTP_HEADER_ACCEPT); if (NULL == mime) - mime = "text/html"; + mime = "text/plain"; lang = MHD_lookup_connection_value (conn, MHD_HEADER_KIND, MHD_HTTP_HEADER_ACCEPT_LANGUAGE); @@ -385,9 +385,9 @@ load_terms (struct TALER_MHD_Legal *legal, const char *mime; unsigned int priority; } mm[] = { + { .ext = ".txt", .mime = "text/plain", .priority = 150 }, { .ext = ".html", .mime = "text/html", .priority = 100 }, { .ext = ".htm", .mime = "text/html", .priority = 99 }, - { .ext = ".txt", .mime = "text/plain", .priority = 50 }, { .ext = ".md", .mime = "text/markdown", .priority = 50 }, { .ext = ".pdf", .mime = "application/pdf", .priority = 25 }, { .ext = ".jpg", .mime = "image/jpeg" }, From 090c532b3adcf404c3b602c899c1e995762e0ace Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 10 Apr 2023 10:48:32 +0200 Subject: [PATCH 19/50] return AML status together with KYC status --- src/exchange/taler-exchange-httpd_kyc-check.c | 21 ++++++++++ .../pg_lookup_kyc_requirement_by_row.c | 19 ++++++--- .../pg_lookup_kyc_requirement_by_row.h | 3 ++ src/include/taler_exchange_service.h | 26 +++++++++++++ src/include/taler_exchangedb_plugin.h | 2 + src/lib/exchange_api_kyc_check.c | 39 ++++++++++++++++++- 6 files changed, 104 insertions(+), 6 deletions(-) diff --git a/src/exchange/taler-exchange-httpd_kyc-check.c b/src/exchange/taler-exchange-httpd_kyc-check.c index c88859268..bf4e4dea1 100644 --- a/src/exchange/taler-exchange-httpd_kyc-check.c +++ b/src/exchange/taler-exchange-httpd_kyc-check.c @@ -112,6 +112,11 @@ struct KycPoller */ const char *section_name; + /** + * Set to AML status of the account. + */ + enum TALER_AmlDecisionState aml_status; + /** * Set to error encountered with KYC logic, if any. */ @@ -303,6 +308,7 @@ kyc_check (void *cls, TEH_plugin->cls, kyp->requirement_row, &requirements, + &kyp->aml_status, &h_payto); if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) { @@ -580,6 +586,17 @@ TEH_handler_kyc_check ( if ( (NULL == kyp->ih) && (! kyp->kyc_required) ) { + if (TALER_AML_NORMAL != kyp->aml_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "KYC is OK, but AML active: %d\n", + (int) kyp->aml_status); + return TALER_MHD_REPLY_JSON_PACK ( + rc->connection, + MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, + GNUNET_JSON_pack_uint64 ("aml_status", + kyp->aml_status)); + } /* KYC not required */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "KYC not required %llu\n", @@ -628,6 +645,8 @@ TEH_handler_kyc_check ( return TALER_MHD_REPLY_JSON_PACK ( rc->connection, MHD_HTTP_ACCEPTED, + GNUNET_JSON_pack_uint64 ("aml_status", + kyp->aml_status), GNUNET_JSON_pack_string ("kyc_url", kyp->kyc_url)); } @@ -665,6 +684,8 @@ TEH_handler_kyc_check ( &sig), GNUNET_JSON_pack_data_auto ("exchange_pub", &pub), + GNUNET_JSON_pack_uint64 ("aml_status", + kyp->aml_status), GNUNET_JSON_pack_object_incref ("kyc_details", kyp->kyc_details), GNUNET_JSON_pack_timestamp ("now", diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.c b/src/exchangedb/pg_lookup_kyc_requirement_by_row.c index 6542aa28f..9651359e2 100644 --- a/src/exchangedb/pg_lookup_kyc_requirement_by_row.c +++ b/src/exchangedb/pg_lookup_kyc_requirement_by_row.c @@ -30,9 +30,11 @@ TEH_PG_lookup_kyc_requirement_by_row ( void *cls, uint64_t requirement_row, char **requirements, + enum TALER_AmlDecisionState *aml_status, struct TALER_PaytoHashP *h_payto) { struct PostgresClosure *pg = cls; + uint32_t status; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&requirement_row), GNUNET_PQ_query_param_end @@ -42,19 +44,26 @@ TEH_PG_lookup_kyc_requirement_by_row ( requirements), GNUNET_PQ_result_spec_auto_from_type ("h_payto", h_payto), + GNUNET_PQ_result_spec_uint32 ("status", + &status), GNUNET_PQ_result_spec_end }; -/* Used in #postgres_lookup_kyc_requirement_by_row() */ + enum GNUNET_DB_QueryStatus qs; + PREPARE (pg, "lookup_legitimization_requirement_by_row", "SELECT " - " required_checks" - ",h_payto" - " FROM legitimization_requirements" + " lr.required_checks" + ",lr.h_payto" + ",aml.status" + " FROM legitimization_requirements lr" + " JOIN aml_status aml USING (h_payto)" " WHERE legitimization_requirement_serial_id=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select ( + qs = GNUNET_PQ_eval_prepared_singleton_select ( pg->conn, "lookup_legitimization_requirement_by_row", params, rs); + *aml_status = (enum TALER_AmlDecisionState) status; + return qs; } diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.h b/src/exchangedb/pg_lookup_kyc_requirement_by_row.h index 12d726187..3d223c985 100644 --- a/src/exchangedb/pg_lookup_kyc_requirement_by_row.h +++ b/src/exchangedb/pg_lookup_kyc_requirement_by_row.h @@ -32,6 +32,7 @@ * @param cls closure * @param requirement_row identifies requirement to look up * @param[out] requirements provider that must be checked + * @param[out] aml_status set to the AML status of the account * @param[out] h_payto account that must be KYC'ed * @return database transaction status */ @@ -40,5 +41,7 @@ TEH_PG_lookup_kyc_requirement_by_row ( void *cls, uint64_t requirement_row, char **requirements, + enum TALER_AmlDecisionState *aml_status, struct TALER_PaytoHashP *h_payto); + #endif diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index 2bf71a17e..4099d6bb0 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -3490,8 +3490,16 @@ struct TALER_EXCHANGE_KycStatus */ struct TALER_ExchangeSignatureP exchange_sig; + /** + * AML status for the account. + */ + enum TALER_AmlDecisionState aml_status; + } success; + /** + * KYC is required. + */ struct { @@ -3502,8 +3510,26 @@ struct TALER_EXCHANGE_KycStatus */ const char *kyc_url; + /** + * AML status for the account. + */ + enum TALER_AmlDecisionState aml_status; + } accepted; + /** + * KYC is OK, but account needs positive AML decision. + */ + struct + { + + /** + * AML status for the account. + */ + enum TALER_AmlDecisionState aml_status; + + } unavailable_for_legal_reasons; + } details; }; diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index a0caf4f85..32a18f638 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -6457,6 +6457,7 @@ struct TALER_EXCHANGEDB_Plugin * @param cls closure * @param legi_row identifies requirement to look up * @param[out] requirements space-separated list of requirements + * @param[out] aml_status set to the AML status of the account * @param[out] h_payto account that must be KYC'ed * @return database transaction status */ @@ -6465,6 +6466,7 @@ struct TALER_EXCHANGEDB_Plugin void *cls, uint64_t requirement_row, char **requirements, + enum TALER_AmlDecisionState *aml_status, struct TALER_PaytoHashP *h_payto); diff --git a/src/lib/exchange_api_kyc_check.c b/src/lib/exchange_api_kyc_check.c index 68a40a962..2f03730a8 100644 --- a/src/lib/exchange_api_kyc_check.c +++ b/src/lib/exchange_api_kyc_check.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2021 Taler Systems SA + Copyright (C) 2021-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 @@ -97,6 +97,7 @@ handle_kyc_check_finished (void *cls, case MHD_HTTP_OK: { json_t *kyc_details; + uint32_t status; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("exchange_sig", &ks.details.success.exchange_sig), @@ -106,6 +107,8 @@ handle_kyc_check_finished (void *cls, &ks.details.success.timestamp), GNUNET_JSON_spec_json ("kyc_details", &kyc_details), + GNUNET_JSON_spec_uint32 ("aml_status", + &status), GNUNET_JSON_spec_end () }; const struct TALER_EXCHANGE_Keys *key_state; @@ -121,6 +124,8 @@ handle_kyc_check_finished (void *cls, break; } ks.details.success.kyc_details = kyc_details; + ks.details.success.aml_status + = (enum TALER_AmlDecisionState) status; key_state = TALER_EXCHANGE_get_keys (kch->exchange); if (GNUNET_OK != TALER_EXCHANGE_test_signing_key (key_state, @@ -155,9 +160,12 @@ handle_kyc_check_finished (void *cls, } case MHD_HTTP_ACCEPTED: { + uint32_t status; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_string ("kyc_url", &ks.details.accepted.kyc_url), + GNUNET_JSON_spec_uint32 ("aml_status", + &status), GNUNET_JSON_spec_end () }; @@ -171,6 +179,8 @@ handle_kyc_check_finished (void *cls, ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; } + ks.details.accepted.aml_status + = (enum TALER_AmlDecisionState) status; kch->cb (kch->cb_cls, &ks); GNUNET_JSON_parse_free (spec); @@ -190,6 +200,33 @@ handle_kyc_check_finished (void *cls, case MHD_HTTP_NOT_FOUND: ks.ec = TALER_JSON_get_error_code (j); break; + case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: + { + uint32_t status; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_uint32 ("aml_status", + &status), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (j, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + ks.http_status = 0; + ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; + } + ks.details.unavailable_for_legal_reasons.aml_status + = (enum TALER_AmlDecisionState) status; + kch->cb (kch->cb_cls, + &ks); + GNUNET_JSON_parse_free (spec); + TALER_EXCHANGE_kyc_check_cancel (kch); + return; + } case MHD_HTTP_INTERNAL_SERVER_ERROR: ks.ec = TALER_JSON_get_error_code (j); /* Server had an internal issue; we should retry, but this API From 27c9fef5ea725ad9b80acbf7f99f6fa6486d59c7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 10 Apr 2023 10:52:45 +0200 Subject: [PATCH 20/50] use LEFT JOIN as aml_status table may be empty --- src/exchangedb/pg_lookup_kyc_requirement_by_row.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.c b/src/exchangedb/pg_lookup_kyc_requirement_by_row.c index 9651359e2..6f9d76786 100644 --- a/src/exchangedb/pg_lookup_kyc_requirement_by_row.c +++ b/src/exchangedb/pg_lookup_kyc_requirement_by_row.c @@ -34,7 +34,7 @@ TEH_PG_lookup_kyc_requirement_by_row ( struct TALER_PaytoHashP *h_payto) { struct PostgresClosure *pg = cls; - uint32_t status; + uint32_t status = TALER_AML_NORMAL; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&requirement_row), GNUNET_PQ_query_param_end @@ -44,8 +44,10 @@ TEH_PG_lookup_kyc_requirement_by_row ( requirements), GNUNET_PQ_result_spec_auto_from_type ("h_payto", h_payto), - GNUNET_PQ_result_spec_uint32 ("status", - &status), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint32 ("status", + &status), + NULL), GNUNET_PQ_result_spec_end }; enum GNUNET_DB_QueryStatus qs; @@ -57,7 +59,7 @@ TEH_PG_lookup_kyc_requirement_by_row ( ",lr.h_payto" ",aml.status" " FROM legitimization_requirements lr" - " JOIN aml_status aml USING (h_payto)" + " LEFT JOIN aml_status aml USING (h_payto)" " WHERE legitimization_requirement_serial_id=$1;"); qs = GNUNET_PQ_eval_prepared_singleton_select ( pg->conn, From 122c926493f2a22820f280fd2546e495e6b5874d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 10 Apr 2023 13:51:36 +0200 Subject: [PATCH 21/50] avoid crashing, fail test instead --- .../testing_api_cmd_take_aml_decision.c | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/testing/testing_api_cmd_take_aml_decision.c b/src/testing/testing_api_cmd_take_aml_decision.c index 871cdb712..21ba9af6f 100644 --- a/src/testing/testing_api_cmd_take_aml_decision.c +++ b/src/testing/testing_api_cmd_take_aml_decision.c @@ -151,9 +151,14 @@ take_aml_decision_run (void *cls, TALER_TESTING_interpreter_fail (is); return; } - GNUNET_assert (GNUNET_OK == - TALER_TESTING_get_trait_h_payto (ref, - &h_payto)); + if (GNUNET_OK != + TALER_TESTING_get_trait_h_payto (ref, + &h_payto)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } ref = TALER_TESTING_interpreter_lookup_command (is, ds->officer_ref_cmd); if (NULL == ref) @@ -162,9 +167,14 @@ take_aml_decision_run (void *cls, TALER_TESTING_interpreter_fail (is); return; } - GNUNET_assert (GNUNET_OK == - TALER_TESTING_get_trait_officer_priv (ref, - &officer_priv)); + if (GNUNET_OK != + TALER_TESTING_get_trait_officer_priv (ref, + &officer_priv)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } ds->h_payto = *h_payto; if (NULL != ds->kyc_requirement) { From 4e9c43954e8e8ce74cfde2ea647b0e87676a0ef7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 10 Apr 2023 23:28:40 +0200 Subject: [PATCH 22/50] -fix SQL query --- src/exchangedb/pg_select_aml_threshold.c | 1 + src/include/taler_crypto_lib.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/exchangedb/pg_select_aml_threshold.c b/src/exchangedb/pg_select_aml_threshold.c index 7a79b70c1..f78a71fff 100644 --- a/src/exchangedb/pg_select_aml_threshold.c +++ b/src/exchangedb/pg_select_aml_threshold.c @@ -56,6 +56,7 @@ TEH_PG_select_aml_threshold ( "SELECT" " threshold_val" ",threshold_frac" + ",status" ",kyc_requirement" " FROM aml_status" " WHERE h_payto=$1;"); diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 4f52d78fa..61d92483f 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -1947,6 +1947,7 @@ void TALER_payto_hash (const char *payto, struct TALER_PaytoHashP *h_payto); + /** * Details about a planchet that the customer wants to obtain * a withdrawal authorization. This is the information that From eb2b4a131bd6f69e91e0efdfc1798e53bb022e89 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 13 Apr 2023 17:30:53 +0200 Subject: [PATCH 23/50] add logic to check signature over fees in /wire response (fixes #7802) --- src/lib/exchange_api_wire.c | 42 ++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/lib/exchange_api_wire.c b/src/lib/exchange_api_wire.c index 995a0933c..c23ea62d8 100644 --- a/src/lib/exchange_api_wire.c +++ b/src/lib/exchange_api_wire.c @@ -111,11 +111,13 @@ free_fees (struct FeeMap *fm) /** * Parse wire @a fees and return map. * + * @param master_pub master public key to use to check signatures * @param fees json AggregateTransferFee to parse * @return NULL on error */ static struct FeeMap * -parse_fees (json_t *fees) +parse_fees (const struct TALER_MasterPublicKeyP *master_pub, + json_t *fees) { struct FeeMap *fm = NULL; const char *key; @@ -164,6 +166,19 @@ parse_fees (json_t *fees) free_fees (fm); return NULL; } + if (GNUNET_OK != + TALER_exchange_offline_wire_fee_verify ( + key, + wa->start_date, + wa->end_date, + &wa->fees, + master_pub, + &wa->master_sig)) + { + GNUNET_break_op (0); + free_fees (fm); + return NULL; + } if (idx + 1 < len) wa->next = &fe->fee_list[idx + 1]; else @@ -227,8 +242,10 @@ handle_wire_finished (void *cls, json_t *fees; unsigned int num_accounts; struct FeeMap *fm; - const struct TALER_EXCHANGE_Keys *key_state; + struct TALER_MasterPublicKeyP master_pub; struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("master_public_key", + &master_pub), GNUNET_JSON_spec_json ("accounts", &accounts), GNUNET_JSON_spec_json ("fees", @@ -249,6 +266,21 @@ handle_wire_finished (void *cls, hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } + { + const struct TALER_EXCHANGE_Keys *key_state; + + key_state = TALER_EXCHANGE_get_keys (wh->exchange); + if (0 != GNUNET_memcmp (&key_state->master_pub, + &master_pub)) + { + /* bogus reply: master public key in /wire differs from that in /keys */ + GNUNET_break_op (0); + hr.http_status = 0; + hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + break; + } + } + if (0 == (num_accounts = json_array_size (accounts))) { /* bogus reply */ @@ -258,7 +290,8 @@ handle_wire_finished (void *cls, hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - if (NULL == (fm = parse_fees (fees))) + if (NULL == (fm = parse_fees (&master_pub, + fees))) { /* bogus reply */ GNUNET_break_op (0); @@ -268,7 +301,6 @@ handle_wire_finished (void *cls, break; } - key_state = TALER_EXCHANGE_get_keys (wh->exchange); /* parse accounts */ { struct TALER_EXCHANGE_WireAccount was[num_accounts]; @@ -290,7 +322,7 @@ handle_wire_finished (void *cls, i); if (GNUNET_OK != TALER_JSON_exchange_wire_signature_check (account, - &key_state->master_pub)) + &master_pub)) { /* bogus reply */ GNUNET_break_op (0); From 07a089f4f167854f8ed3036475efc8171ade5d69 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 15 Apr 2023 14:38:32 +0200 Subject: [PATCH 24/50] -fix memory leak --- src/exchangedb/exchange_do_batch_coin_known.sql | 2 +- src/lib/auditor_api_deposit_confirmation.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/exchangedb/exchange_do_batch_coin_known.sql b/src/exchangedb/exchange_do_batch_coin_known.sql index 38d795959..f6a14cfab 100644 --- a/src/exchangedb/exchange_do_batch_coin_known.sql +++ b/src/exchangedb/exchange_do_batch_coin_known.sql @@ -390,7 +390,7 @@ FROM exists; RETURN; END $$; -/*** THIS SQL CODE WORKS ***/ +/*** Experiment using a loop ***/ /* CREATE OR REPLACE FUNCTION exchange_do_batch2_known_coin( IN in_coin_pub1 BYTEA, diff --git a/src/lib/auditor_api_deposit_confirmation.c b/src/lib/auditor_api_deposit_confirmation.c index afbeda75a..55a05d962 100644 --- a/src/lib/auditor_api_deposit_confirmation.c +++ b/src/lib/auditor_api_deposit_confirmation.c @@ -362,10 +362,16 @@ TALER_AUDITOR_deposit_confirmation ( dh->ctx.headers, &handle_deposit_confirmation_finished, dh); - /* Disable 100 continue processing */ - GNUNET_CURL_extend_headers (dh->job, - curl_slist_append (NULL, - "Expect:")); + { + /* Disable 100 continue processing */ + struct curl_slist *x_headers; + + x_headers = curl_slist_append (NULL, + "Expect:"); + GNUNET_CURL_extend_headers (dh->job, + x_headers); + curl_slist_free_all (x_headers); + } return dh; } From 2c28f7ebd05d31943f470dfdb410e4ce0955c8a3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 15 Apr 2023 15:14:05 +0200 Subject: [PATCH 25/50] reduce max requests limit per default --- src/exchange/exchange.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/exchange/exchange.conf b/src/exchange/exchange.conf index 750e71724..38e5816ff 100644 --- a/src/exchange/exchange.conf +++ b/src/exchange/exchange.conf @@ -19,7 +19,7 @@ MAX_KEYS_CACHING = forever # After how many requests should the exchange auto-restart # (to address potential issues with memory fragmentation)? # If this option is not specified, auto-restarting is disabled. -# MAX_REQUESTS = 10000000 +# MAX_REQUESTS = 100000 # How to access our database DB = postgres From eec4dc80ef726818f0908eb401168c648610e836 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 15 Apr 2023 19:53:38 +0200 Subject: [PATCH 26/50] always check for the entire batch being idempotent, not only when it is too late to repeat the request --- .../taler-exchange-httpd_batch-withdraw.c | 230 +++++++++--------- 1 file changed, 118 insertions(+), 112 deletions(-) diff --git a/src/exchange/taler-exchange-httpd_batch-withdraw.c b/src/exchange/taler-exchange-httpd_batch-withdraw.c index 6cd467d51..c3065e1df 100644 --- a/src/exchange/taler-exchange-httpd_batch-withdraw.c +++ b/src/exchange/taler-exchange-httpd_batch-withdraw.c @@ -77,6 +77,11 @@ struct BatchWithdrawContext */ const struct TALER_ReservePublicKeyP *reserve_pub; + /** + * request context + */ + const struct TEH_RequestContext *rc; + /** * KYC status of the reserve used for the operation. */ @@ -183,6 +188,99 @@ aml_amount_cb ( } +/** + * Generates our final (successful) response. + * + * @param rc request context + * @param wc operation context + * @return MHD queue status + */ +static MHD_RESULT +generate_reply_success (const struct TEH_RequestContext *rc, + const struct BatchWithdrawContext *wc) +{ + json_t *sigs; + + if (! wc->kyc.ok) + { + /* KYC required */ + return TEH_RESPONSE_reply_kyc_required (rc->connection, + &wc->h_payto, + &wc->kyc); + } + if (TALER_AML_NORMAL != wc->aml_decision) + return TEH_RESPONSE_reply_aml_blocked (rc->connection, + wc->aml_decision); + + sigs = json_array (); + GNUNET_assert (NULL != sigs); + for (unsigned int i = 0; iplanchets_length; i++) + { + struct PlanchetContext *pc = &wc->planchets[i]; + + GNUNET_assert ( + 0 == + json_array_append_new ( + sigs, + GNUNET_JSON_PACK ( + TALER_JSON_pack_blinded_denom_sig ( + "ev_sig", + &pc->collectable.sig)))); + } + TEH_METRICS_batch_withdraw_num_coins += wc->planchets_length; + return TALER_MHD_REPLY_JSON_PACK ( + rc->connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_array_steal ("ev_sigs", + sigs)); +} + + +/** + * Check if the @a wc is replayed and we already have an + * answer. If so, replay the existing answer and return the + * HTTP response. + * + * @param wc parsed request data + * @param[out] mret HTTP status, set if we return true + * @return true if the request is idempotent with an existing request + * false if we did not find the request in the DB and did not set @a mret + */ +static bool +check_request_idempotent (const struct BatchWithdrawContext *wc, + MHD_RESULT *mret) +{ + const struct TEH_RequestContext *rc = wc->rc; + + for (unsigned int i = 0; iplanchets_length; i++) + { + struct PlanchetContext *pc = &wc->planchets[i]; + enum GNUNET_DB_QueryStatus qs; + + qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls, + &pc->h_coin_envelope, + &pc->collectable); + if (0 > qs) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + *mret = TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "get_withdraw_info"); + return true; /* well, kind-of */ + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + return false; + } + /* generate idempotent reply */ + TEH_METRICS_num_requests[TEH_MT_REQUEST_IDEMPOTENT_BATCH_WITHDRAW]++; + *mret = generate_reply_success (rc, + wc); + return true; +} + + /** * Function implementing withdraw transaction. Runs the * transaction logic; IF it returns a non-error code, the transaction @@ -448,12 +546,18 @@ batch_withdraw_transaction (void *cls, if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) || (conflict) ) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Idempotent coin in batch, not allowed. Aborting.\n"); - *mhd_ret = TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - TALER_EC_EXCHANGE_WITHDRAW_BATCH_IDEMPOTENT_PLANCHET, - NULL); + if (! check_request_idempotent (wc, + mhd_ret)) + { + /* We do not support *some* of the coins of the request being + idempotent while others being fresh. */ + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Idempotent coin in batch, not allowed. Aborting.\n"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_CONFLICT, + TALER_EC_EXCHANGE_WITHDRAW_BATCH_IDEMPOTENT_PLANCHET, + NULL); + } return GNUNET_DB_STATUS_HARD_ERROR; } if (nonce_reuse) @@ -471,99 +575,6 @@ batch_withdraw_transaction (void *cls, } -/** - * Generates our final (successful) response. - * - * @param rc request context - * @param wc operation context - * @return MHD queue status - */ -static MHD_RESULT -generate_reply_success (const struct TEH_RequestContext *rc, - const struct BatchWithdrawContext *wc) -{ - json_t *sigs; - - if (! wc->kyc.ok) - { - /* KYC required */ - return TEH_RESPONSE_reply_kyc_required (rc->connection, - &wc->h_payto, - &wc->kyc); - } - if (TALER_AML_NORMAL != wc->aml_decision) - return TEH_RESPONSE_reply_aml_blocked (rc->connection, - wc->aml_decision); - - sigs = json_array (); - GNUNET_assert (NULL != sigs); - for (unsigned int i = 0; iplanchets_length; i++) - { - struct PlanchetContext *pc = &wc->planchets[i]; - - GNUNET_assert ( - 0 == - json_array_append_new ( - sigs, - GNUNET_JSON_PACK ( - TALER_JSON_pack_blinded_denom_sig ( - "ev_sig", - &pc->collectable.sig)))); - } - TEH_METRICS_batch_withdraw_num_coins += wc->planchets_length; - return TALER_MHD_REPLY_JSON_PACK ( - rc->connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_array_steal ("ev_sigs", - sigs)); -} - - -/** - * Check if the @a rc is replayed and we already have an - * answer. If so, replay the existing answer and return the - * HTTP response. - * - * @param rc request context - * @param wc parsed request data - * @param[out] mret HTTP status, set if we return true - * @return true if the request is idempotent with an existing request - * false if we did not find the request in the DB and did not set @a mret - */ -static bool -check_request_idempotent (const struct TEH_RequestContext *rc, - const struct BatchWithdrawContext *wc, - MHD_RESULT *mret) -{ - for (unsigned int i = 0; iplanchets_length; i++) - { - struct PlanchetContext *pc = &wc->planchets[i]; - enum GNUNET_DB_QueryStatus qs; - - qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls, - &pc->h_coin_envelope, - &pc->collectable); - if (0 > qs) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - if (GNUNET_DB_STATUS_HARD_ERROR == qs) - *mret = TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - "get_withdraw_info"); - return true; /* well, kind-of */ - } - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) - return false; - } - /* generate idempotent reply */ - TEH_METRICS_num_requests[TEH_MT_REQUEST_IDEMPOTENT_BATCH_WITHDRAW]++; - *mret = generate_reply_success (rc, - wc); - return true; -} - - /** * The request was parsed successfully. Prepare * our side for the main DB transaction. @@ -691,8 +702,7 @@ parse_planchets (const struct TEH_RequestContext *rc, ksh = TEH_keys_get_state (); if (NULL == ksh) { - if (! check_request_idempotent (rc, - wc, + if (! check_request_idempotent (wc, &mret)) { return TALER_MHD_reply_with_error (rc->connection, @@ -713,8 +723,7 @@ parse_planchets (const struct TEH_RequestContext *rc, NULL); if (NULL == dk) { - if (! check_request_idempotent (rc, - wc, + if (! check_request_idempotent (wc, &mret)) { return TEH_RESPONSE_reply_unknown_denom_pub_hash ( @@ -726,8 +735,7 @@ parse_planchets (const struct TEH_RequestContext *rc, if (GNUNET_TIME_absolute_is_past (dk->meta.expire_withdraw.abs_time)) { /* This denomination is past the expiration time for withdraws */ - if (! check_request_idempotent (rc, - wc, + if (! check_request_idempotent (wc, &mret)) { return TEH_RESPONSE_reply_expired_denom_pub_hash ( @@ -751,8 +759,7 @@ parse_planchets (const struct TEH_RequestContext *rc, if (dk->recoup_possible) { /* This denomination has been revoked */ - if (! check_request_idempotent (rc, - wc, + if (! check_request_idempotent (wc, &mret)) { return TEH_RESPONSE_reply_expired_denom_pub_hash ( @@ -832,7 +839,10 @@ TEH_handler_batch_withdraw (struct TEH_RequestContext *rc, const struct TALER_ReservePublicKeyP *reserve_pub, const json_t *root) { - struct BatchWithdrawContext wc; + struct BatchWithdrawContext wc = { + .reserve_pub = reserve_pub, + .rc = rc + }; json_t *planchets; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_json ("planchets", @@ -840,13 +850,9 @@ TEH_handler_batch_withdraw (struct TEH_RequestContext *rc, GNUNET_JSON_spec_end () }; - memset (&wc, - 0, - sizeof (wc)); GNUNET_assert (GNUNET_OK == TALER_amount_set_zero (TEH_currency, &wc.batch_total)); - wc.reserve_pub = reserve_pub; { enum GNUNET_GenericReturnValue res; From 32c6999a83efbd08dcb36997941af8902974081a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 15 Apr 2023 22:19:33 +0200 Subject: [PATCH 27/50] update gana --- contrib/gana | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/gana b/contrib/gana index 59de2acb7..bf43b20a0 160000 --- a/contrib/gana +++ b/contrib/gana @@ -1 +1 @@ -Subproject commit 59de2acb7c716c816ed15786b5369e56c325770c +Subproject commit bf43b20a0362ac19bcf1bab9c33215e55d8d9f36 From 376de032b514b9f85f9b6ec3a8616aa418a2a413 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 15 Apr 2023 23:11:36 +0200 Subject: [PATCH 28/50] create warnings on missing table syncs --- src/exchangedb/pg_insert_records_by_table.c | 9 ++- src/exchangedb/pg_lookup_records_by_table.c | 10 +-- src/include/taler_exchangedb_plugin.h | 72 ++++++++++++++++++++- 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c index d6630797a..1ccf41b42 100644 --- a/src/exchangedb/pg_insert_records_by_table.c +++ b/src/exchangedb/pg_insert_records_by_table.c @@ -1877,7 +1877,7 @@ TEH_PG_insert_records_by_table (void *cls, const struct TALER_EXCHANGEDB_TableData *td) { struct PostgresClosure *pg = cls; - InsertRecordCallback rh; + InsertRecordCallback rh = NULL; switch (td->table) { @@ -2007,7 +2007,10 @@ TEH_PG_insert_records_by_table (void *cls, case TALER_EXCHANGEDB_RT_PROFIT_DRAINS: rh = &irbt_cb_table_profit_drains; break; - default: + } + + if (NULL == rh) + { GNUNET_break (0); return GNUNET_DB_STATUS_HARD_ERROR; } @@ -2016,4 +2019,4 @@ TEH_PG_insert_records_by_table (void *cls, } -/* end of irbt_callbacks.c */ +/* end of pg_insert_records_by_table.c */ diff --git a/src/exchangedb/pg_lookup_records_by_table.c b/src/exchangedb/pg_lookup_records_by_table.c index 806896e78..aa9ab046d 100644 --- 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, 2021, 2022 Taler Systems SA + Copyright (C) 2020-2023 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 @@ -2321,8 +2321,8 @@ TEH_PG_lookup_records_by_table (void *cls, .cb = cb, .cb_cls = cb_cls }; - GNUNET_PQ_PostgresResultHandler rh; - const char *statement; + GNUNET_PQ_PostgresResultHandler rh = NULL; + const char *statement = NULL; enum GNUNET_DB_QueryStatus qs; switch (table) @@ -2885,7 +2885,9 @@ TEH_PG_lookup_records_by_table (void *cls, " ORDER BY profit_drain_serial_id ASC;"); rh = &lrbt_cb_table_profit_drains; break; - default: + } + if (NULL == rh) + { GNUNET_break (0); return GNUNET_DB_STATUS_HARD_ERROR; } diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 32a18f638..1ed5ab585 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA + Copyright (C) 2014-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 @@ -234,6 +234,7 @@ 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, @@ -276,6 +277,13 @@ enum TALER_EXCHANGEDB_ReplicatedTable TALER_EXCHANGEDB_RT_WADS_IN, TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES, TALER_EXCHANGEDB_RT_PROFIT_DRAINS, + /* From exchange-0003.sql: */ + TALER_EXCHAGNEDB_RT_AML_STAFF, + TALER_EXCHAGNEDB_RT_AML_HISTORY, + TALER_EXCHAGNEDB_RT_KYC_ATTRIBUTES, + TALER_EXCHANGEDB_RT_PURSE_DELETION, + TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS, + TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS, }; @@ -701,6 +709,67 @@ struct TALER_EXCHANGEDB_TableData struct TALER_MasterSignatureP master_sig; } profit_drains; + struct + { + struct TALER_AmlOfficerPublicKeyP decider_pub; + struct TALER_MasterSignatureP master_sig; + char *decider_name; + bool is_active; + bool read_only; + struct GNUNET_TIME_Timestamp last_change; + } aml_staff; + + struct + { + struct TALER_PaytoHashP h_payto; + struct TALER_Amount new_threshold; + enum TALER_AmlDecisionState new_status; + struct GNUNET_TIME_Timestamp decision_time; + char *justification; + char *kyc_requirements; /* NULL allowed! */ + uint64_t kyc_req_row; + struct TALER_AmlOfficerPublicKeyP decider_pub; + struct TALER_AmlOfficerSignatureP decider_sig; + } aml_history; + + struct + { + struct TALER_PaytoHashP h_payto; + struct GNUNET_ShortHashCode kyc_prox; + char *provider; + char *birthdate; /* NULL allowed! */ + struct GNUNET_TIME_Timestamp collection_time; + struct GNUNET_TIME_Timestamp expiration_time; + void *encrypted_attributes; + size_t encrypted_attributes_size; + } kyc_attributes; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PurseContractSignatureP purse_sig; + } purse_deletion; + + struct + { + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + struct TALER_Amount amount_with_fee; + uint16_t max_age; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + uint32_t noreveal_index; + struct GNUNET_TIME_Absolute timestamp; + } withdraw_age_commitments; + + struct + { + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + // FIXME-Oec: h_commitment --- schema says it is 32 byte, but it was 64 above??!? + uint32_t freshcoin_index; + uint64_t denominations_serial; + // FIXME-Oec: h_coin_ev --- schema says it is 32 byte!? + } withdraw_age_reveals; + } details; }; @@ -1106,6 +1175,7 @@ struct TALER_EXCHANGEDB_AgeWithdrawCommitment /** * Maximum age that the coins are restricted to. + * FIXME-Oec: use 16-bit integer (see DB schema!) */ uint32_t max_age; From 136d2b2e70852628c18245e85fd9c6821f810557 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 15 Apr 2023 23:43:20 +0200 Subject: [PATCH 29/50] implement more of lookup_records_by_table --- src/exchangedb/pg_lookup_records_by_table.c | 448 ++++++++++++++++++++ src/exchangedb/pg_lookup_serial_by_table.c | 54 +++ src/include/taler_exchangedb_plugin.h | 6 +- 3 files changed, 505 insertions(+), 3 deletions(-) diff --git a/src/exchangedb/pg_lookup_records_by_table.c b/src/exchangedb/pg_lookup_records_by_table.c index aa9ab046d..a23c034c5 100644 --- a/src/exchangedb/pg_lookup_records_by_table.c +++ b/src/exchangedb/pg_lookup_records_by_table.c @@ -2295,6 +2295,374 @@ lrbt_cb_table_profit_drains (void *cls, } +/** + * Function called with aml_staff 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_aml_staff (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_AML_STAFF + }; + + for (unsigned int i = 0; ierror = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with aml_history 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_aml_history (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct PostgresClosure *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_AML_HISTORY + }; + + for (unsigned int i = 0; ierror = true; + return; + } + td.details.aml_history.new_status + = (enum TALER_AmlDecisionState) status32; + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with kyc_attributes 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_attributes (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES + }; + + for (unsigned int i = 0; ierror = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with purse_deletion 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_purse_deletion (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_PURSE_DELETION + }; + + for (unsigned int i = 0; ierror = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with withdraw_age_commitments 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_withdraw_age_commitments (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct PostgresClosure *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS + }; + + for (unsigned int i = 0; ierror = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with withdraw_age_reveals 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_withdraw_age_reveals (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS + }; + + for (unsigned int i = 0; ierror = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + /** * Assign statement to @a n and PREPARE * @a sql under name @a n. @@ -2885,6 +3253,86 @@ TEH_PG_lookup_records_by_table (void *cls, " ORDER BY profit_drain_serial_id ASC;"); rh = &lrbt_cb_table_profit_drains; break; + + case TALER_EXCHANGEDB_RT_AML_STAFF: + XPREPARE ("select_above_serial_by_table_aml_staff", + "SELECT" + " aml_staff_uuid" + ",decider_pub" + ",master_sig" + ",decider_name" + ",is_active" + ",read_only" + ",last_change" + " FROM aml_staff" + " WHERE aml_staff_uuid > $1" + " ORDER BY aml_staff_uuid ASC;"); + rh = &lrbt_cb_table_aml_staff; + break; + case TALER_EXCHANGEDB_RT_AML_HISTORY: + XPREPARE ("select_above_serial_by_table_aml_history", + "SELECT" + " aml_history_serial_id" + ",h_payto" + ",new_threshold_val" + ",new_threshold_frac" + ",new_status" + ",decision_time" + ",justification" + ",kyc_requirements" + ",kyc_req_row" + ",decider_pub" + ",decider_sig" + " FROM aml_history" + " WHERE aml_history_serial_id > $1" + " ORDER BY aml_history_serial_id ASC;"); + rh = &lrbt_cb_table_aml_history; + break; + case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES: + XPREPARE ("select_above_serial_by_table_kyc_attributes", + "SELECT" + " kyc_attributes_serial_id" + ",h_payto" + ",kyc_prox" + ",provider" + ",birthdate" + ",collection_time" + ",expiration_time" + ",encrypted_attributes" + " FROM kyc_attributes" + " WHERE kyc_attributes_serial_id > $1" + " ORDER BY kyc_attributes_serial_id ASC;"); + rh = &lrbt_cb_table_kyc_attributes; + break; + case TALER_EXCHANGEDB_RT_PURSE_DELETION: + XPREPARE ("select_above_serial_by_table_purse_deletion", + "SELECT" + " purse_deletion_serial_id" + ",purse_pub" + ",purse_sig" + " FROM purse_deletion" + " WHERE purse_deletion_serial_id > $1" + " ORDER BY purse_deletion_serial_id ASC;"); + rh = &lrbt_cb_table_purse_deletion; + break; + case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS: + XPREPARE ("select_above_serial_by_table_withdraw_age_commitments", + "SELECT" + " withdraw_age_commitment_id" + ",h_commitment" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",max_age" + ",reserve_pub" + ",reserve_sig" + ",noreveal_index" + ",timestamp" + " FROM withdraw_age_commitments" + " WHERE withdraw_age_commitment_id > $1" + " ORDER BY withdraw_age_commitment_id ASC;"); + rh = &lrbt_cb_table_withdraw_age_commitments; + break; + } if (NULL == rh) { diff --git a/src/exchangedb/pg_lookup_serial_by_table.c b/src/exchangedb/pg_lookup_serial_by_table.c index 7e150cd28..d2554af2e 100644 --- a/src/exchangedb/pg_lookup_serial_by_table.c +++ b/src/exchangedb/pg_lookup_serial_by_table.c @@ -390,6 +390,60 @@ TEH_PG_lookup_serial_by_table (void *cls, " LIMIT 1;"); statement = "select_serial_by_table_profit_drains"; break; + case TALER_EXCHANGEDB_RT_AML_STAFF: + XPREPARE ("select_serial_by_table_aml_staff", + "SELECT" + " aml_staff_uuid AS serial" + " FROM aml_staff" + " ORDER BY aml_staff_uuid DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_aml_staff"; + break; + case TALER_EXCHANGEDB_RT_AML_HISTORY: + XPREPARE ("select_serial_by_table_aml_history", + "SELECT" + " aml_history_serial_id AS serial" + " FROM aml_history" + " ORDER BY aml_history_serial_id DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_aml_history"; + break; + case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES: + XPREPARE ("select_serial_by_table_kyc_attributes", + "SELECT" + " kyc_attributes_serial_id AS serial" + " FROM kyc_attributes" + " ORDER BY kyc_attributes_serial_id DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_kyc_attributes"; + break; + case TALER_EXCHANGEDB_RT_PURSE_DELETION: + XPREPARE ("select_serial_by_table_purse_deletion", + "SELECT" + " purse_deletion_serial_id AS serial" + " FROM purse_deletion" + " ORDER BY purse_deletion_serial_id DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_purse_deletion"; + break; + case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS: + XPREPARE ("select_serial_by_table_withdraw_age_commitments", + "SELECT" + " withdraw_age_commitment_id AS serial" + " FROM withdraw_age_commitments" + " ORDER BY withdraw_age_commitment_id DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_withdraw_age_commitments"; + break; + case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS: + XPREPARE ("select_serial_by_table_withdraw_age_reveals", + "SELECT" + " withdraw_age_reveals_id AS serial" + " FROM withdraw_age_reveals" + " ORDER BY withdraw_age_reveals_id DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_withdraw_age_reveals"; + break; } if (NULL == statement) { diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 1ed5ab585..f60c3cf05 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -278,9 +278,9 @@ enum TALER_EXCHANGEDB_ReplicatedTable TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES, TALER_EXCHANGEDB_RT_PROFIT_DRAINS, /* From exchange-0003.sql: */ - TALER_EXCHAGNEDB_RT_AML_STAFF, - TALER_EXCHAGNEDB_RT_AML_HISTORY, - TALER_EXCHAGNEDB_RT_KYC_ATTRIBUTES, + TALER_EXCHANGEDB_RT_AML_STAFF, + TALER_EXCHANGEDB_RT_AML_HISTORY, + TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES, TALER_EXCHANGEDB_RT_PURSE_DELETION, TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS, TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS, From 2906ded1a6a407344a1d2eef3e58b06e65bc7576 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 16 Apr 2023 09:41:37 +0200 Subject: [PATCH 30/50] work on insert_records_by_table --- src/exchangedb/pg_insert_records_by_table.c | 297 +++++++++++++++++++- 1 file changed, 295 insertions(+), 2 deletions(-) diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c index 1ccf41b42..73e6ccda1 100644 --- a/src/exchangedb/pg_insert_records_by_table.c +++ b/src/exchangedb/pg_insert_records_by_table.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet - Copyright (C) 2020, 2021, 2022 Taler Systems SA + Copyright (C) 2020-2023 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 @@ -1872,6 +1872,282 @@ irbt_cb_table_profit_drains (struct PostgresClosure *pg, } +/** + * Function called with aml_staff records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_aml_staff (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.aml_staff.decider_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.aml_staff.master_sig), + GNUNET_PQ_query_param_string ( + td->details.aml_staff.decider_name), + GNUNET_PQ_query_param_bool ( + td->details.aml_staff.is_active), + GNUNET_PQ_query_param_bool ( + td->details.aml_staff.read_only), + GNUNET_PQ_query_param_timestamp ( + &td->details.aml_staff.last_change), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_aml_staff", + "INSERT INTO aml_staff" + "(aml_staff_uuid" + ",decider_pub" + ",master_sig" + ",decider_name" + ",is_active" + ",read_only" + ",last_change" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_aml_staff", + params); +} + + +/** + * Function called with aml_history records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_aml_history (struct PostgresClosure *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + uint32_t status32 = td->details.aml_history.new_status; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.aml_history.h_payto), + TALER_PQ_query_param_amount ( + &td->details.aml_history.new_threshold), + GNUNET_PQ_query_param_uint32 ( + &status32), + GNUNET_PQ_query_param_timestamp ( + &td->details.aml_history.decision_time), + GNUNET_PQ_query_param_string ( + td->details.aml_history.justification), + (NULL == td->details.aml_history.kyc_requirements) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string ( + td->details.aml_history.kyc_requirements), + GNUNET_PQ_query_param_uint64 ( + &td->details.aml_history.kyc_req_row), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.aml_history.decider_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.aml_history.decider_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_aml_history", + "INSERT INTO aml_history" + "(aml_history_serial_id" + ",h_payto" + ",new_threshold_val" + ",new_threshold_frac" + ",new_status" + ",decision_time" + ",justification" + ",kyc_requirements" + ",kyc_req_row" + ",decider_pub" + ",decider_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_aml_history", + params); +} + + +/** + * Function called with kyc_attributes records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_kyc_attributes (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_attributes.h_payto), + GNUNET_PQ_query_param_auto_from_type ( + &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 ( + &td->details.kyc_attributes.expiration_time), + GNUNET_PQ_query_param_fixed_size ( + &td->details.kyc_attributes.encrypted_attributes, + td->details.kyc_attributes.encrypted_attributes_size), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_kyc_attributes", + "INSERT INTO kyc_attributes" + "(kyc_attributes_serial_id" + ",h_payto" + ",kyc_prox" + ",provider" + ",birthdate" + ",collection_time" + ",expiration_time" + ",encrypted_attributes" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_kyc_attributes", + params); +} + + +/** + * Function called with purse_deletion records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_purse_deletion (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.purse_deletion.purse_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.purse_deletion.purse_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_purse_deletion", + "INSERT INTO purse_deletion" + "(purse_deletion_serial_id" + ",purse_pub" + ",purse_sig" + ") VALUES " + "($1, $2, $3);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_purse_deletion", + params); +} + + +/** + * Function called with withdraw_age_commitments records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_withdraw_age_commitments (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.withdraw_age_commitments.h_commitment), + TALER_PQ_query_param_amount ( + &td->details.withdraw_age_commitments.amount_with_fee), + GNUNET_PQ_query_param_uint16 ( + &td->details.withdraw_age_commitments.max_age), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.withdraw_age_commitments.reserve_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.withdraw_age_commitments.reserve_sig), + GNUNET_PQ_query_param_uint32 ( + &td->details.withdraw_age_commitments.noreveal_index), + GNUNET_PQ_query_param_absolute_time ( + &td->details.withdraw_age_commitments.timestamp), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_withdraw_age_commitments", + "INSERT INTO withdraw_age_commitments" + "(withdraw_age_commitment_id" + ",h_commitment" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",max_age" + ",reserve_pub" + ",reserve_sig" + ",noreveal_index" + ",timestamp" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_withdraw_age_commitments", + params); +} + + +/** + * Function called with withdraw_age_reveals records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_withdraw_age_reveals (struct PostgresClosure *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), +#if FIXME_OEC + GNUNET_PQ_query_param_auto_from_type ( + &td->details.withdraw_age_reveals.h_commitment), +#endif + GNUNET_PQ_query_param_uint32 ( + &td->details.withdraw_age_reveals.freshcoin_index), + GNUNET_PQ_query_param_uint64 ( + &td->details.withdraw_age_reveals.denominations_serial), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_withdraw_age_reveals", + "INSERT INTO withdraw_age_reveals" + "(withdraw_age_reveals_id" + ",FIXME_OEC" + ",freshcoin_index" + ",denominations_serial" + ",FIXME_OEC" + ") VALUES " + "($1, $2, $3, $4, $5);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_withdraw_age_reveals", + params); +} + + enum GNUNET_DB_QueryStatus TEH_PG_insert_records_by_table (void *cls, const struct TALER_EXCHANGEDB_TableData *td) @@ -2007,8 +2283,25 @@ TEH_PG_insert_records_by_table (void *cls, case TALER_EXCHANGEDB_RT_PROFIT_DRAINS: rh = &irbt_cb_table_profit_drains; break; + case TALER_EXCHANGEDB_RT_AML_STAFF: + rh = &irbt_cb_table_aml_staff; + break; + case TALER_EXCHANGEDB_RT_AML_HISTORY: + rh = &irbt_cb_table_aml_history; + break; + case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES: + rh = &irbt_cb_table_kyc_attributes; + break; + case TALER_EXCHANGEDB_RT_PURSE_DELETION: + rh = &irbt_cb_table_purse_deletion; + break; + case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS: + rh = &irbt_cb_table_withdraw_age_commitments; + break; + case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS: + rh = &irbt_cb_table_withdraw_age_reveals; + break; } - if (NULL == rh) { GNUNET_break (0); From 5121c6b1cfd71db641d0de8974091e295c22668a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 16 Apr 2023 10:05:38 +0200 Subject: [PATCH 31/50] work on lookup_records_by_table --- src/exchangedb/pg_lookup_records_by_table.c | 276 ++++++++++++++++++++ 1 file changed, 276 insertions(+) diff --git a/src/exchangedb/pg_lookup_records_by_table.c b/src/exchangedb/pg_lookup_records_by_table.c index a23c034c5..51894f23f 100644 --- a/src/exchangedb/pg_lookup_records_by_table.c +++ b/src/exchangedb/pg_lookup_records_by_table.c @@ -231,6 +231,109 @@ lrbt_cb_table_wire_targets (void *cls, } +/** + * Function called with legitimization_processes 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_legitimization_processes (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES + }; + + for (unsigned int i = 0; ierror = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with legitimization_requirements 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_legitimization_requirements (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_REQUIREMENTS + }; + + for (unsigned int i = 0; ierror = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + /** * Function called with reserves table entries. * @@ -400,6 +503,123 @@ lrbt_cb_table_reserves_close (void *cls, } +/** + * Function called with reserves_open_requests 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_reserves_open_requests (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct PostgresClosure *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS + }; + + for (unsigned int i = 0; ierror = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with reserves_open_deposits 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_reserves_open_deposits (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct PostgresClosure *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS + }; + + for (unsigned int i = 0; ierror = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + /** * Function called with reserves_out table entries. * @@ -2743,6 +2963,31 @@ TEH_PG_lookup_records_by_table (void *cls, " ORDER BY wire_target_serial_id ASC;"); rh = &lrbt_cb_table_wire_targets; break; + case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES: + XPREPARE ("select_above_serial_by_table_legitimization_processes", + "SELECT" + " legitimization_process_serial_id AS serial" + ",h_payto" + ",expiration_time" + ",provider_section" + ",provider_user_id" + ",provider_legitimization_id" + " FROM legitimization_processes" + " WHERE legitimization_process_serial_id > $1" + " ORDER BY legitimization_process_serial_id ASC;"); + rh = &lrbt_cb_table_legitimization_processes; + break; + case TALER_EXCHANGEDB_RT_LEGITIMIZATION_REQUIREMENTS: + XPREPARE ("select_above_serial_by_table_legitimization_requirements", + "SELECT" + " legitimization_requirement_serial_id AS serial" + ",h_payto" + ",required_checks" + " FROM legitimization_requirements" + " WHERE legitimization_requirement_serial_id > $1" + " ORDER BY legitimization_requirement_serial_id ASC;"); + rh = &lrbt_cb_table_legitimization_requirements; + break; case TALER_EXCHANGEDB_RT_RESERVES: XPREPARE ("select_above_serial_by_table_reserves", "SELECT" @@ -2788,6 +3033,37 @@ TEH_PG_lookup_records_by_table (void *cls, " ORDER BY close_uuid ASC;"); rh = &lrbt_cb_table_reserves_close; break; + case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS: + XPREPARE ("select_above_serial_by_table_reserves_open_requests", + "SELECT" + " open_request_uuid AS serial" + ",reserve_pub" + ",request_timestamp" + ",expiration_date" + ",reserve_sig" + ",reserve_payment_val" + ",reserve_payment_frac" + ",requested_purse_limit" + " FROM reserves_open_requests" + " WHERE open_request_uuid > $1" + " ORDER BY open_request_uuid ASC;"); + rh = &lrbt_cb_table_reserves_open_requests; + break; + case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS: + XPREPARE ("select_above_serial_by_table_reserves_open_deposits", + "SELECT" + " reserves_open_deposit_uuid AS serial" + ",reserve_sig" + ",reserve_pub" + ",coin_pub" + ",coin_sig" + ",contribution_val" + ",contribution_frac" + " FROM reserves_open_deposits" + " WHERE reserves_open_deposit_uuid > $1" + " ORDER BY reserves_open_deposit_uuid ASC;"); + rh = &lrbt_cb_table_reserves_open_deposits; + break; case TALER_EXCHANGEDB_RT_RESERVES_OUT: XPREPARE ("select_above_serial_by_table_reserves_out", "SELECT" From 10c779bbc6b50e7eaca813fa920f0c083c275b15 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 16 Apr 2023 21:25:48 +0200 Subject: [PATCH 32/50] add FIXME --- src/kyclogic/plugin_kyclogic_oauth2.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/kyclogic/plugin_kyclogic_oauth2.c b/src/kyclogic/plugin_kyclogic_oauth2.c index d4aaf4494..228525e28 100644 --- a/src/kyclogic/plugin_kyclogic_oauth2.c +++ b/src/kyclogic/plugin_kyclogic_oauth2.c @@ -514,6 +514,11 @@ initiate_task (void *cls) pd->client_id, redirect_uri_encoded); GNUNET_free (redirect_uri_encoded); + /* FIXME-API: why do we *redirect* the client here, + instead of making the HTTP request *ourselves* + and forwarding the response? This prevents us + from using authentication on initiation, + (which is desirable for challenger!) */ ih->cb (ih->cb_cls, TALER_EC_NONE, url, From ade7586c3069b57a33ca94da291f64e6ee27ea44 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 16 Apr 2023 21:26:01 +0200 Subject: [PATCH 33/50] add missing resource --- src/exchangedb/spi/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/exchangedb/spi/Makefile diff --git a/src/exchangedb/spi/Makefile b/src/exchangedb/spi/Makefile new file mode 100644 index 000000000..9c84bf75b --- /dev/null +++ b/src/exchangedb/spi/Makefile @@ -0,0 +1,8 @@ +EXTENSION = own_test +MODULES = own_test +DATA = own_test.sql + +# postgresql build stuff +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) From 8463572beae5c5e8df59e12107a8cecee3ea8680 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 16 Apr 2023 22:07:36 +0200 Subject: [PATCH 34/50] fix SPI build --- src/exchangedb/spi/Makefile | 1 + src/exchangedb/spi/README.md | 60 +++++++------- src/exchangedb/spi/own_test.c | 36 ++++----- src/exchangedb/spi/own_test.sql | 135 ++++++++++++++------------------ 4 files changed, 107 insertions(+), 125 deletions(-) diff --git a/src/exchangedb/spi/Makefile b/src/exchangedb/spi/Makefile index 9c84bf75b..d654d91e9 100644 --- a/src/exchangedb/spi/Makefile +++ b/src/exchangedb/spi/Makefile @@ -1,6 +1,7 @@ EXTENSION = own_test MODULES = own_test DATA = own_test.sql +PG_CPPFLAGS = -I /usr/include/postgresql # postgresql build stuff PG_CONFIG = pg_config diff --git a/src/exchangedb/spi/README.md b/src/exchangedb/spi/README.md index ec6a9016a..47eb37b94 100644 --- a/src/exchangedb/spi/README.md +++ b/src/exchangedb/spi/README.md @@ -1,41 +1,37 @@ - Server Programming Interface (SPI) + Server Programming Interface (SPI) -Dependencies: -============= - -These are the direct dependencies for running SPI functions : - - - -Step 1: -"postgresql-server-dev-" --- sudo apt-get install libpq-dev postgresql-server-dev-13 - -Step 2: -To solve gssapi/gssapi.h, use the following command: -apt-get install libkrb5-dev - -Step 3: -apt-cache search openssl | grep -- -dev -apt-get install libssl-dev - -Compile: +Overview ======== -gcc -shared -o .so .c -CALL FUNCTIONS: -=============== +This folder contains results from an experiment by Joseph Xu +to use the Postgres SPI. They are not currently used at all +by the GNU Taler exchange. -psql -c "SELECT ();" db_name -Structure: -========== +Dependencies +============ -usr/include/postgres/ +These are the direct dependencies for compiling the code: -usr/include/postgres/13/server/ +# apt-get install libpq-dev postgresql-server-dev-13 +# apt-get install libkrb5-dev +# apt-get install libssl-dev -make -make install -psql \ No newline at end of file + +Compilation +=========== + +$ make + +Loading functions +================= + +# make install +$ psql "$DB_NAME" < own_test.sql + + +Calling functions +================== + +$ psql -c "SELECT $FUNCTION_NAME($ARGS);" "$DB_NAME" diff --git a/src/exchangedb/spi/own_test.c b/src/exchangedb/spi/own_test.c index 7da89cbd2..ac72fad7b 100644 --- a/src/exchangedb/spi/own_test.c +++ b/src/exchangedb/spi/own_test.c @@ -2,17 +2,17 @@ #include #include -#include -#include +#include +#include #include #include #include #include #include -#include "utils/array.h" +#include #include -#include "utils/numeric.h" -#include "utils/timestamp.h" +#include +#include #include #ifdef PG_MODULE_MAGIC @@ -66,7 +66,7 @@ pg_spi_prepare_example (PG_FUNCTION_ARGS) { if (prepared_plan == NULL) { - new_plan = SPI_prepare ("SELECT 1 FROM joseph_test.X", 0, NULL); + new_plan = SPI_prepare ("SELECT 1 FROM X", 0, NULL); prepared_plan = SPI_saveplan (new_plan); if (prepared_plan == NULL) @@ -112,7 +112,7 @@ pg_spi_prepare_example_without_saveplan (PG_FUNCTION_ARGS) } { - new_plan = SPI_prepare ("SELECT 1 FROM joseph_test.X", 0, NULL); + new_plan = SPI_prepare ("SELECT 1 FROM X", 0, NULL); ret = SPI_execute_plan (new_plan, NULL, 0,false, 0); if (ret != SPI_OK_SELECT) { @@ -142,7 +142,7 @@ Datum pg_spi_select_from_x (PG_FUNCTION_ARGS) { int ret; - char *query = "SELECT 1 FROM joseph_test.X"; + char *query = "SELECT 1 FROM X"; uint64 proc; ret = SPI_connect (); @@ -172,7 +172,7 @@ pg_spi_insert_int (PG_FUNCTION_ARGS) int nargs; Oid argtypes[1]; Datum values[1]; - char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; + char *query = "INSERT INTO X (a) VALUES ($1)"; ret = SPI_connect (); if (ret != SPI_OK_CONNECT) @@ -204,7 +204,7 @@ pg_spi_prepare_insert (PG_FUNCTION_ARGS) int nargs; Oid argtypes[1]; Datum values[1]; - char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; + const char *query = "INSERT INTO X (a) VALUES ($1)"; SPIPlanPtr new_plan; ret = SPI_connect (); if (ret != SPI_OK_CONNECT) @@ -252,7 +252,7 @@ pg_spi_prepare_insert_bytea(PG_FUNCTION_ARGS) Datum values[1]; Oid argtypes2[1]; Datum val[1]; - char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; + char *query = "INSERT INTO X (a) VALUES ($1)"; SPIPlanPtr new_plan; ret = SPI_connect(); if (ret != SPI_OK_CONNECT) @@ -296,7 +296,7 @@ pg_spi_prepare_insert_without_saveplan (PG_FUNCTION_ARGS) int nargs; Oid argtypes[1]; Datum values[1]; - char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; + const char *query = "INSERT INTO X (a) VALUES ($1)"; SPIPlanPtr new_plan; ret = SPI_connect (); if (ret != SPI_OK_CONNECT) @@ -333,7 +333,7 @@ pg_spi_select_pair_from_y(PG_FUNCTION_ARGS) int ret; valuest result; bool isnull; - char *query = "SELECT 1,1 FROM joseph_test.Y"; + char *query = "SELECT 1,1 FROM Y"; result.col1 = 0; result.col2 = 0; @@ -368,7 +368,7 @@ pg_spi_select_with_cond(PG_FUNCTION_ARGS) Oid argtypes[1]; Datum values[1]; uint64 proc; - query = "SELECT col1 FROM joseph_test.Y WHERE col2 = $1"; + query = "SELECT col1 FROM Y WHERE col2 = $1"; ret = SPI_connect(); if (ret != SPI_OK_CONNECT) { @@ -401,7 +401,7 @@ Datum pg_spi_prepare_select_with_cond(PG_FUNCTION_ARGS) { uint64 proc; int nargs; Oid argtypes[1]; - char *query = "SELECT col1 FROM joseph_test.Y WHERE col1 = $1"; + char *query = "SELECT col1 FROM Y WHERE col1 = $1"; int result = 0; ret = SPI_connect(); @@ -461,7 +461,7 @@ pg_spi_prepare_select_with_cond_without_saveplan (PG_FUNCTION_ARGS) uint64 proc; int nargs; Oid argtypes[1]; - char *query = "SELECT col1 FROM joseph_test.Y WHERE col2 = $1"; + char *query = "SELECT col1 FROM Y WHERE col2 = $1"; int result = 0; ret = SPI_connect (); @@ -519,7 +519,7 @@ pg_spi_update_y (PG_FUNCTION_ARGS) int nargs; Oid argtypes[1]; Datum values[1]; - char *query = "UPDATE joseph_test.Y SET col1 = 4 WHERE (col2 = $1)"; + const char *query = "UPDATE Y SET col1 = 4 WHERE (col2 = $1)"; ret = SPI_connect (); if (ret != SPI_OK_CONNECT) @@ -552,7 +552,7 @@ pg_spi_prepare_update (PG_FUNCTION_ARGS) int nargs; Oid argtypes[1]; Datum values[1]; - char *query = "UPDATE joseph_test.Y SET col1 = 4 WHERE (col2 = $1)"; + const char *query = "UPDATE Y SET col1 = 4 WHERE (col2 = $1)"; ret = SPI_connect (); if (ret != SPI_OK_CONNECT) diff --git a/src/exchangedb/spi/own_test.sql b/src/exchangedb/spi/own_test.sql index 9fe42c0a4..12729d068 100644 --- a/src/exchangedb/spi/own_test.sql +++ b/src/exchangedb/spi/own_test.sql @@ -1,42 +1,20 @@ - -DROP TABLE joseph_test.X; -CREATE TABLE joseph_test.X ( +DROP TABLE IF EXISTS X; +CREATE TABLE X ( a integer ); -INSERT INTO joseph_test.X (a) VALUES (1), (2), (3), (4), (5), (6), (7); - -DROP TABLE joseph_test.Y; -CREATE TABLE joseph_test.Y (col1 INT, col2 INT); -INSERT INTO joseph_test.Y (col1,col2) VALUES (1,2), (2,0), (0,4), (4,0), (0,6), (6,7), (7,8); - -DROP TABLE joseph_test.Z; -CREATE TABLE joseph_test.Z(col1 BYTEA); -DROP TABLE deposits; -/*CREATE TABLE deposits( - deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY - ,shard INT8 NOT NULL - ,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32) - ,known_coin_id INT8 NOT NULL - ,amount_with_fee_val INT8 NOT NULL - ,amount_with_fee_frac INT4 NOT NULL - ,wallet_timestamp INT8 NOT NULL - ,exchange_timestamp INT8 NOT NULL - ,refund_deadline INT8 NOT NULL - ,wire_deadline INT8 NOT NULL - ,merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32) - ,h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64) - ,coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64) - ,wire_salt BYTEA NOT NULL CHECK (LENGTH(wire_salt)=16) - ,wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32) - ,done BOOLEAN NOT NULL DEFAULT FALSE - ,policy_blocked BOOLEAN NOT NULL DEFAULT FALSE - ,policy_details_serial_id INT8); -*/ ---INSERT INTO deposits VALUES (); +INSERT INTO X (a) + VALUES (1), (2), (3), (4), (5), (6), (7); +DROP TABLE IF EXISTS Y; +CREATE TABLE Y (col1 INT, col2 INT); +INSERT INTO Y (col1,col2) + VALUES (1,2), (2,0), (0,4), (4,0), (0,6), (6,7), (7,8); +DROP TABLE IF EXISTS Z; +CREATE TABLE Z (col1 BYTEA); +DROP TABLE IF EXISTS deposits; CREATE TABLE deposits( deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY ,shard INT8 NOT NULL @@ -58,79 +36,81 @@ CREATE TABLE deposits( ,policy_details_serial_id INT8); -CREATE OR REPLACE FUNCTION pg_spi_insert_int() +DROP FUNCTION IF EXISTS pg_spi_insert_int; +CREATE FUNCTION pg_spi_insert_int() RETURNS VOID - LANGUAGE c COST 100 + LANGUAGE c VOLATILE COST 100 AS '$libdir/own_test', 'pg_spi_insert_int'; -DROP FUNCTION pg_spi_select_from_x(); -CREATE OR REPLACE FUNCTION pg_spi_select_from_x() + +DROP FUNCTION IF EXISTS pg_spi_select_from_x; +CREATE FUNCTION pg_spi_select_from_x() RETURNS INT8 LANGUAGE c COST 100 AS '$libdir/own_test', 'pg_spi_select_from_x'; -/*DROP FUNCTION pg_spi_select_pair_from_y(); -CREATE OR REPLACE FUNCTION pg_spi_select_pair_from_y() +/* +CREATE FUNCTION pg_spi_select_pair_from_y() RETURNS valuest LANGUAGE c COST 100 AS '$libdir/own_test', 'pg_spi_select_pair_from_y'; */ -/*CREATE OR REPLACE FUNCTION pg_spi_select_with_cond() +/*CREATE FUNCTION pg_spi_select_with_cond() RETURNS INT8 LANGUAGE c COST 100 AS '$libdir/own_test', 'pg_spi_select_with_cond'; */ -DROP FUNCTION pg_spi_update_y(); -CREATE OR REPLACE FUNCTION pg_spi_update_y() - RETURNS VOID - LANGUAGE c COST 100 -AS '$libdir/own_test', 'pg_spi_update_y'; -DROP FUNCTION pg_spi_prepare_example(); -CREATE OR REPLACE FUNCTION pg_spi_prepare_example() +DROP FUNCTION IF EXISTS pg_spi_update_y; +CREATE FUNCTION pg_spi_update_y() + RETURNS VOID + LANGUAGE c VOLATILE COST 100 +AS '$libdir/own_test', 'pg_spi_update_y'; + +DROP FUNCTION IF EXISTS pg_spi_prepare_example; +CREATE FUNCTION pg_spi_prepare_example() RETURNS INT8 LANGUAGE c COST 100 AS '$libdir/own_test', 'pg_spi_prepare_example'; -DROP FUNCTION pg_spi_prepare_example_without_saveplan(); -CREATE OR REPLACE FUNCTION pg_spi_prepare_example_without_saveplan() +DROP FUNCTION IF EXISTS pg_spi_prepare_example_without_saveplan; +CREATE FUNCTION pg_spi_prepare_example_without_saveplan() RETURNS INT8 LANGUAGE c COST 100 AS '$libdir/own_test', 'pg_spi_prepare_example_without_saveplan'; -CREATE OR REPLACE FUNCTION pg_spi_prepare_insert() +DROP FUNCTION IF EXISTS pg_spi_prepare_insert; +CREATE FUNCTION pg_spi_prepare_insert() RETURNS VOID - LANGUAGE c COST 100 + LANGUAGE c VOLATILE COST 100 AS '$libdir/own_test', 'pg_spi_prepare_insert'; -CREATE OR REPLACE FUNCTION pg_spi_prepare_insert_without_saveplan() +DROP FUNCTION IF EXISTS pg_spi_prepare_insert_without_saveplan; +CREATE FUNCTION pg_spi_prepare_insert_without_saveplan() RETURNS VOID - LANGUAGE c COST 100 + LANGUAGE c VOLATILE COST 100 AS '$libdir/own_test', 'pg_spi_prepare_insert_without_saveplan'; -/*DROP FUNCTION pg_spi_prepare_select_with_cond(); -CREATE OR REPLACE FUNCTION pg_spi_prepare_select_with_cond() +/* +CREATE FUNCTION pg_spi_prepare_select_with_cond() RETURNS INT8 LANGUAGE c COST 100 AS '$libdir/own_test', 'pg_spi_prepare_select_with_cond'; */ -DROP FUNCTION pg_spi_prepare_select_with_cond_without_saveplan(); -CREATE OR REPLACE FUNCTION pg_spi_prepare_select_with_cond_without_saveplan() + +DROP FUNCTION IF EXISTS pg_spi_prepare_select_with_cond_without_saveplan; +CREATE FUNCTION pg_spi_prepare_select_with_cond_without_saveplan() RETURNS INT8 LANGUAGE c COST 100 AS '$libdir/own_test', 'pg_spi_prepare_select_with_cond_without_saveplan'; -DROP FUNCTION pg_spi_prepare_update(); -CREATE OR REPLACE FUNCTION pg_spi_prepare_update() +DROP FUNCTION IF EXISTS pg_spi_prepare_update; +CREATE FUNCTION pg_spi_prepare_update() RETURNS VOID - LANGUAGE c COST 100 + LANGUAGE c VOLATILE COST 100 AS '$libdir/own_test', 'pg_spi_prepare_update'; -DROP FUNCTION pg_spi_get_dep_ref_fees( - IN in_timestamp INT8 - ,IN merchant_pub BYTEA - ,IN wire_target_h_payto BYTEA - ,IN wtid BYTEA); -CREATE OR REPLACE FUNCTION pg_spi_get_dep_ref_fees( +DROP FUNCTION IF EXISTS pg_spi_get_dep_ref_fees; +CREATE FUNCTION pg_spi_get_dep_ref_fees( IN in_timestamp INT8 ,IN merchant_pub BYTEA ,IN wire_target_h_payto BYTEA @@ -140,7 +120,8 @@ CREATE OR REPLACE FUNCTION pg_spi_get_dep_ref_fees( LANGUAGE c VOLATILE COST 100 AS '$libdir/own_test', 'pg_spi_get_dep_ref_fees'; -CREATE OR REPLACE FUNCTION update_pg_spi_get_dep_ref_fees( +DROP FUNCTION IF EXISTS update_pg_spi_get_dep_ref_fees; +CREATE FUNCTION update_pg_spi_get_dep_ref_fees( IN in_refund_deadline INT8, IN in_merchant_pub BYTEA, IN in_wire_target_h_payto BYTEA @@ -165,43 +146,47 @@ RETURN QUERY amount_with_fee_frac; END $$; -CREATE OR REPLACE FUNCTION stored_procedure_update( +DROP FUNCTION IF EXISTS stored_procedure_update; +CREATE FUNCTION stored_procedure_update( IN in_number INT8 ) RETURNS VOID LANGUAGE plpgsql AS $$ BEGIN - UPDATE joseph_test.Y + UPDATE Y SET col1 = 4 WHERE col2 = in_number; END $$; -CREATE OR REPLACE FUNCTION stored_procedure_select(OUT out_value INT8) +DROP FUNCTION IF EXISTS stored_procedure_select; +CREATE FUNCTION stored_procedure_select(OUT out_value INT8) RETURNS INT8 LANGUAGE plpgsql AS $$ BEGIN SELECT 1 INTO out_value - FROM joseph_test.X; + FROM X; RETURN; END $$; -CREATE OR REPLACE FUNCTION stored_procedure_insert( +DROP FUNCTION IF EXISTS stored_procedure_insert; +CREATE FUNCTION stored_procedure_insert( IN in_number INT8, OUT out_number INT8) RETURNS INT8 LANGUAGE plpgsql AS $$ BEGIN - INSERT INTO joseph_test.X (a) + INSERT INTO X (a) VALUES (in_number) RETURNING a INTO out_number; END $$; -CREATE OR REPLACE FUNCTION stored_procedure_select_with_cond( +DROP FUNCTION IF EXISTS stored_procedure_select_with_cond; +CREATE FUNCTION stored_procedure_select_with_cond( IN in_number INT8, OUT out_number INT8 ) @@ -210,7 +195,7 @@ LANGUAGE plpgsql AS $$ BEGIN SELECT col1 INTO out_number - FROM joseph_test.Y + FROM Y WHERE col2 = in_number; RETURN; END $$; From 8952a87b85a4b44233ff6a9191d3f773124f6407 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 18 Apr 2023 20:24:10 +0200 Subject: [PATCH 35/50] avoid overloading of global variable --- contrib/gana | 2 +- src/exchange/taler-exchange-wirewatch.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/contrib/gana b/contrib/gana index bf43b20a0..7adfb722a 160000 --- a/contrib/gana +++ b/contrib/gana @@ -1 +1 @@ -Subproject commit bf43b20a0362ac19bcf1bab9c33215e55d8d9f36 +Subproject commit 7adfb722ac988170a31cdfd8132073eb7f2a6c43 diff --git a/src/exchange/taler-exchange-wirewatch.c b/src/exchange/taler-exchange-wirewatch.c index 168e7b9b7..9f954c27f 100644 --- a/src/exchange/taler-exchange-wirewatch.c +++ b/src/exchange/taler-exchange-wirewatch.c @@ -495,12 +495,12 @@ transaction_completed (void) * We got incoming transaction details from the bank. Add them * to the database. * - * @param batch_size desired batch size + * @param wrap_size desired bulk insert size * @param details array of transaction details * @param details_length length of the @a details array */ static void -process_reply (unsigned int batch_size, +process_reply (unsigned int wrap_size, const struct TALER_BANK_CreditDetails *details, unsigned int details_length) { @@ -570,7 +570,7 @@ process_reply (unsigned int batch_size, qs = db_plugin->reserves_in_insert (db_plugin->cls, reserves, details_length, - batch_size, + wrap_size, qss); switch (qs) { @@ -581,7 +581,7 @@ process_reply (unsigned int batch_size, case GNUNET_DB_STATUS_SOFT_ERROR: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got DB soft error for batch2_reserves_in_insert (%u). Rolling back.\n", - batch_size); + wrap_size); handle_soft_error (); return; default: @@ -686,25 +686,25 @@ static void history_cb (void *cls, const struct TALER_BANK_CreditHistoryResponse *reply) { - static int batch_mode = -2; + static int wrap_size = -2; (void) cls; - if (-2 == batch_mode) + if (-2 == wrap_size) { - const char *mode = getenv ("TALER_WIREWATCH_BATCH_SIZE"); + const char *mode = getenv ("TALER_WIREWATCH_WARP_SIZE"); char dummy; if ( (NULL == mode) || (1 != sscanf (mode, "%d%c", - &batch_mode, + &wrap_size, &dummy)) ) { if (NULL != mode) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Bad batch mode `%s' specified\n", mode); - batch_mode = 8; /* maximum supported is currently 8 */ + wrap_size = 8; /* maximum supported is currently 8 */ } } GNUNET_assert (NULL == task); @@ -715,7 +715,7 @@ history_cb (void *cls, switch (reply->http_status) { case MHD_HTTP_OK: - process_reply (batch_mode, + process_reply (wrap_size, reply->details.success.details, reply->details.success.details_length); return; From 44e0e005959cc4c5f189cda59bb2f61dc4f8a63a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 18 Apr 2023 20:44:33 +0200 Subject: [PATCH 36/50] fix some major bugs in pg_reserves_in_insert --- src/exchangedb/pg_reserves_in_insert.c | 335 +++++++++++-------------- 1 file changed, 142 insertions(+), 193 deletions(-) diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c index e4d1b6e77..71c57f844 100644 --- a/src/exchangedb/pg_reserves_in_insert.c +++ b/src/exchangedb/pg_reserves_in_insert.c @@ -59,34 +59,26 @@ static enum GNUNET_DB_QueryStatus insert1 (struct PostgresClosure *pg, const struct TALER_EXCHANGEDB_ReserveInInfo reserves[1], struct GNUNET_TIME_Timestamp gc, - struct TALER_PaytoHashP h_payto, char *const *notify_s, struct GNUNET_TIME_Timestamp reserve_expiration, bool *transaction_duplicate, bool *conflict, - uint64_t *reserve_uuid, - enum GNUNET_DB_QueryStatus results[1]) + uint64_t *reserve_uuid) { enum GNUNET_DB_QueryStatus qs; - PREPARE (pg, - "batch1_reserve_create", - "SELECT " - " out_reserve_found AS conflicted" - ",transaction_duplicate" - ",ruuid AS reserve_uuid" - " FROM exchange_do_batch_reserves_in_insert" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);"); - + struct TALER_PaytoHashP h_payto0; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_timestamp (&gc), GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), TALER_PQ_query_param_amount (reserves[0].balance), GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto0), GNUNET_PQ_query_param_string (reserves[0].sender_account_details), + GNUNET_PQ_query_param_string (notify_s[0]), GNUNET_PQ_query_param_end }; @@ -100,8 +92,16 @@ insert1 (struct PostgresClosure *pg, GNUNET_PQ_result_spec_end }; + PREPARE (pg, + "batch1_reserve_create", + "SELECT " + " out_reserve_found AS conflicted" + ",transaction_duplicate" + ",ruuid AS reserve_uuid" + " FROM exchange_do_batch_reserves_in_insert" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);"); TALER_payto_hash (reserves[0].sender_account_details, - &h_payto); + &h_payto0); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "batch1_reserve_create", params, @@ -111,7 +111,6 @@ insert1 (struct PostgresClosure *pg, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to create reserves 1(%d)\n", qs); - results[0] = qs; return qs; } GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs); @@ -119,10 +118,8 @@ insert1 (struct PostgresClosure *pg, { GNUNET_break (0); TEH_PG_rollback (pg); - results[0] = GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR; } - results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; return qs; } @@ -131,36 +128,24 @@ static enum GNUNET_DB_QueryStatus insert2 (struct PostgresClosure *pg, const struct TALER_EXCHANGEDB_ReserveInInfo reserves[2], struct GNUNET_TIME_Timestamp gc, - struct TALER_PaytoHashP h_payto, char *const*notify_s, struct GNUNET_TIME_Timestamp reserve_expiration, bool *transaction_duplicate, bool *conflict, - uint64_t *reserve_uuid, - enum GNUNET_DB_QueryStatus results[1]) + uint64_t *reserve_uuid) { enum GNUNET_DB_QueryStatus qs1; - PREPARE (pg, - "batch2_reserve_create", - "SELECT " - "out_reserve_found AS conflicted" - ",out_reserve_found2 AS conflicted2" - ",transaction_duplicate" - ",transaction_duplicate2" - ",ruuid AS reserve_uuid" - ",ruuid2 AS reserve_uuid2" - " FROM exchange_do_batch2_reserves_insert" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20);"); - + struct TALER_PaytoHashP h_payto[2]; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_timestamp (&gc), GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), TALER_PQ_query_param_amount (reserves[0].balance), GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[0]), GNUNET_PQ_query_param_string (reserves[0].sender_account_details), GNUNET_PQ_query_param_string (notify_s[0]), @@ -171,7 +156,7 @@ insert2 (struct PostgresClosure *pg, TALER_PQ_query_param_amount (reserves[1].balance), GNUNET_PQ_query_param_string (reserves[1].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[1]), GNUNET_PQ_query_param_string (reserves[1].sender_account_details), GNUNET_PQ_query_param_end }; @@ -191,12 +176,21 @@ insert2 (struct PostgresClosure *pg, GNUNET_PQ_result_spec_end }; + PREPARE (pg, + "batch2_reserve_create", + "SELECT " + "out_reserve_found AS conflicted" + ",out_reserve_found2 AS conflicted2" + ",transaction_duplicate" + ",transaction_duplicate2" + ",ruuid AS reserve_uuid" + ",ruuid2 AS reserve_uuid2" + " FROM exchange_do_batch2_reserves_insert" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20);"); TALER_payto_hash (reserves[0].sender_account_details, - &h_payto); + &h_payto[0]); TALER_payto_hash (reserves[1].sender_account_details, - &h_payto); - - + &h_payto[1]); qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "batch2_reserve_create", params, @@ -206,26 +200,17 @@ insert2 (struct PostgresClosure *pg, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to create reserves 2(%d)\n", qs1); - results[0] = qs1; return qs1; } GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1); - /* results[i] = (transaction_duplicate) - ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/ - - if ( - ((! conflict[0]) && (transaction_duplicate[0])) - || ((! conflict[1]) && (transaction_duplicate[1])) - ) + if ( ((! conflict[0]) && (transaction_duplicate[0])) || + ((! conflict[1]) && (transaction_duplicate[1])) ) { GNUNET_break (0); - TEH_PG_rollback (pg); // ROLLBACK - results[0] = GNUNET_DB_STATUS_HARD_ERROR; + TEH_PG_rollback (pg); return GNUNET_DB_STATUS_HARD_ERROR; } - results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; return qs1; } @@ -234,42 +219,24 @@ static enum GNUNET_DB_QueryStatus insert4 (struct PostgresClosure *pg, const struct TALER_EXCHANGEDB_ReserveInInfo reserves[4], struct GNUNET_TIME_Timestamp gc, - struct TALER_PaytoHashP h_payto, char *const*notify_s, struct GNUNET_TIME_Timestamp reserve_expiration, bool *transaction_duplicate, bool *conflict, - uint64_t *reserve_uuid, - enum GNUNET_DB_QueryStatus results[1]) + uint64_t *reserve_uuid) { enum GNUNET_DB_QueryStatus qs3; - PREPARE (pg, - "batch4_reserve_create", - "SELECT " - "out_reserve_found AS conflicted" - ",out_reserve_found2 AS conflicted2" - ",out_reserve_found3 AS conflicted3" - ",out_reserve_found4 AS conflicted4" - ",transaction_duplicate" - ",transaction_duplicate2" - ",transaction_duplicate3" - ",transaction_duplicate4" - ",ruuid AS reserve_uuid" - ",ruuid2 AS reserve_uuid2" - ",ruuid3 AS reserve_uuid3" - ",ruuid4 AS reserve_uuid4" - " FROM exchange_do_batch4_reserves_insert" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38);"); - + struct TALER_PaytoHashP h_payto[4]; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_timestamp (&gc), GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), TALER_PQ_query_param_amount (reserves[0].balance), GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[0]), GNUNET_PQ_query_param_string (reserves[0].sender_account_details), GNUNET_PQ_query_param_string (notify_s[0]), @@ -282,7 +249,7 @@ insert4 (struct PostgresClosure *pg, TALER_PQ_query_param_amount (reserves[1].balance), GNUNET_PQ_query_param_string (reserves[1].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[1]), GNUNET_PQ_query_param_string (reserves[1].sender_account_details), GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub), @@ -290,7 +257,7 @@ insert4 (struct PostgresClosure *pg, TALER_PQ_query_param_amount (reserves[2].balance), GNUNET_PQ_query_param_string (reserves[2].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[2]), GNUNET_PQ_query_param_string (reserves[2].sender_account_details), GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub), @@ -298,7 +265,7 @@ insert4 (struct PostgresClosure *pg, TALER_PQ_query_param_amount (reserves[3].balance), GNUNET_PQ_query_param_string (reserves[3].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[3]), GNUNET_PQ_query_param_string (reserves[3].sender_account_details), GNUNET_PQ_query_param_end @@ -332,15 +299,27 @@ insert4 (struct PostgresClosure *pg, GNUNET_PQ_result_spec_end }; - TALER_payto_hash (reserves[0].sender_account_details, - &h_payto); - TALER_payto_hash (reserves[1].sender_account_details, - &h_payto); - TALER_payto_hash (reserves[2].sender_account_details, - &h_payto); - TALER_payto_hash (reserves[3].sender_account_details, - &h_payto); + PREPARE (pg, + "batch4_reserve_create", + "SELECT " + "out_reserve_found AS conflicted" + ",out_reserve_found2 AS conflicted2" + ",out_reserve_found3 AS conflicted3" + ",out_reserve_found4 AS conflicted4" + ",transaction_duplicate" + ",transaction_duplicate2" + ",transaction_duplicate3" + ",transaction_duplicate4" + ",ruuid AS reserve_uuid" + ",ruuid2 AS reserve_uuid2" + ",ruuid3 AS reserve_uuid3" + ",ruuid4 AS reserve_uuid4" + " FROM exchange_do_batch4_reserves_insert" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38);"); + for (unsigned int i = 0; i<4; i++) + TALER_payto_hash (reserves[i].sender_account_details, + &h_payto[i]); qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "batch4_reserve_create", params, @@ -350,7 +329,6 @@ insert4 (struct PostgresClosure *pg, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to create reserves4 (%d)\n", qs3); - results[0] = qs3; return qs3; } @@ -365,10 +343,8 @@ insert4 (struct PostgresClosure *pg, { GNUNET_break (0); TEH_PG_rollback (pg); - results[0] = GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR; } - results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; return qs3; } @@ -377,55 +353,26 @@ static enum GNUNET_DB_QueryStatus insert8 (struct PostgresClosure *pg, const struct TALER_EXCHANGEDB_ReserveInInfo reserves[8], struct GNUNET_TIME_Timestamp gc, - struct TALER_PaytoHashP h_payto, char *const*notify_s, struct GNUNET_TIME_Timestamp reserve_expiration, bool *transaction_duplicate, bool *conflict, - uint64_t *reserve_uuid, - enum GNUNET_DB_QueryStatus results[1]) + uint64_t *reserve_uuid) { enum GNUNET_DB_QueryStatus qs3; - PREPARE (pg, - "batch8_reserve_create", - "SELECT" - " out_reserve_found AS conflicted" - ",out_reserve_found2 AS conflicted2" - ",out_reserve_found3 AS conflicted3" - ",out_reserve_found4 AS conflicted4" - ",out_reserve_found5 AS conflicted5" - ",out_reserve_found6 AS conflicted6" - ",out_reserve_found7 AS conflicted7" - ",out_reserve_found8 AS conflicted8" - ",transaction_duplicate" - ",transaction_duplicate2" - ",transaction_duplicate3" - ",transaction_duplicate4" - ",transaction_duplicate5" - ",transaction_duplicate6" - ",transaction_duplicate7" - ",transaction_duplicate8" - ",ruuid AS reserve_uuid" - ",ruuid2 AS reserve_uuid2" - ",ruuid3 AS reserve_uuid3" - ",ruuid4 AS reserve_uuid4" - ",ruuid5 AS reserve_uuid5" - ",ruuid6 AS reserve_uuid6" - ",ruuid7 AS reserve_uuid7" - ",ruuid8 AS reserve_uuid8" - " FROM exchange_do_batch8_reserves_insert" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39, $40, $41,$42,$43,$44,$45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$70,$71,$72,$73,$74);"); - + struct TALER_PaytoHashP h_payto[8]; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_timestamp (&gc), GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), TALER_PQ_query_param_amount (reserves[0].balance), GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[0]), GNUNET_PQ_query_param_string (reserves[0].sender_account_details), + GNUNET_PQ_query_param_string (notify_s[0]), GNUNET_PQ_query_param_string (notify_s[1]), GNUNET_PQ_query_param_string (notify_s[2]), @@ -440,7 +387,7 @@ insert8 (struct PostgresClosure *pg, TALER_PQ_query_param_amount (reserves[1].balance), GNUNET_PQ_query_param_string (reserves[1].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[1]), GNUNET_PQ_query_param_string (reserves[1].sender_account_details), GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub), @@ -448,7 +395,7 @@ insert8 (struct PostgresClosure *pg, TALER_PQ_query_param_amount (reserves[2].balance), GNUNET_PQ_query_param_string (reserves[2].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[2]), GNUNET_PQ_query_param_string (reserves[2].sender_account_details), GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub), @@ -456,7 +403,7 @@ insert8 (struct PostgresClosure *pg, TALER_PQ_query_param_amount (reserves[3].balance), GNUNET_PQ_query_param_string (reserves[3].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[3]), GNUNET_PQ_query_param_string (reserves[3].sender_account_details), GNUNET_PQ_query_param_auto_from_type (reserves[4].reserve_pub), @@ -464,7 +411,7 @@ insert8 (struct PostgresClosure *pg, TALER_PQ_query_param_amount (reserves[4].balance), GNUNET_PQ_query_param_string (reserves[4].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[4].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[4]), GNUNET_PQ_query_param_string (reserves[4].sender_account_details), GNUNET_PQ_query_param_timestamp (&reserve_expiration), @@ -473,7 +420,7 @@ insert8 (struct PostgresClosure *pg, TALER_PQ_query_param_amount (reserves[5].balance), GNUNET_PQ_query_param_string (reserves[5].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[5].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[5]), GNUNET_PQ_query_param_string (reserves[5].sender_account_details), GNUNET_PQ_query_param_auto_from_type (reserves[6].reserve_pub), @@ -481,7 +428,7 @@ insert8 (struct PostgresClosure *pg, TALER_PQ_query_param_amount (reserves[6].balance), GNUNET_PQ_query_param_string (reserves[6].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[6].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[6]), GNUNET_PQ_query_param_string (reserves[6].sender_account_details), GNUNET_PQ_query_param_auto_from_type (reserves[7].reserve_pub), @@ -489,7 +436,7 @@ insert8 (struct PostgresClosure *pg, TALER_PQ_query_param_amount (reserves[7].balance), GNUNET_PQ_query_param_string (reserves[7].exchange_account_name), GNUNET_PQ_query_param_timestamp (&reserves[7].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_payto[7]), GNUNET_PQ_query_param_string (reserves[7].sender_account_details), GNUNET_PQ_query_param_end @@ -547,23 +494,39 @@ insert8 (struct PostgresClosure *pg, GNUNET_PQ_result_spec_end }; - TALER_payto_hash (reserves[0].sender_account_details, - &h_payto); - TALER_payto_hash (reserves[1].sender_account_details, - &h_payto); - TALER_payto_hash (reserves[2].sender_account_details, - &h_payto); - TALER_payto_hash (reserves[3].sender_account_details, - &h_payto); - TALER_payto_hash (reserves[4].sender_account_details, - &h_payto); - TALER_payto_hash (reserves[5].sender_account_details, - &h_payto); - TALER_payto_hash (reserves[6].sender_account_details, - &h_payto); - TALER_payto_hash (reserves[7].sender_account_details, - &h_payto); + PREPARE (pg, + "batch8_reserve_create", + "SELECT" + " out_reserve_found AS conflicted" + ",out_reserve_found2 AS conflicted2" + ",out_reserve_found3 AS conflicted3" + ",out_reserve_found4 AS conflicted4" + ",out_reserve_found5 AS conflicted5" + ",out_reserve_found6 AS conflicted6" + ",out_reserve_found7 AS conflicted7" + ",out_reserve_found8 AS conflicted8" + ",transaction_duplicate" + ",transaction_duplicate2" + ",transaction_duplicate3" + ",transaction_duplicate4" + ",transaction_duplicate5" + ",transaction_duplicate6" + ",transaction_duplicate7" + ",transaction_duplicate8" + ",ruuid AS reserve_uuid" + ",ruuid2 AS reserve_uuid2" + ",ruuid3 AS reserve_uuid3" + ",ruuid4 AS reserve_uuid4" + ",ruuid5 AS reserve_uuid5" + ",ruuid6 AS reserve_uuid6" + ",ruuid7 AS reserve_uuid7" + ",ruuid8 AS reserve_uuid8" + " FROM exchange_do_batch8_reserves_insert" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39, $40, $41,$42,$43,$44,$45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$70,$71,$72,$73,$74);"); + for (unsigned int i = 0; i<8; i++) + TALER_payto_hash (reserves[i].sender_account_details, + &h_payto[i]); qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "batch8_reserve_create", params, @@ -573,15 +536,10 @@ insert8 (struct PostgresClosure *pg, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to create reserves8 (%d)\n", qs3); - results[0] = qs3; return qs3; } GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3); - /* results[i] = (transaction_duplicate) - ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/ - if ( ((! conflict[0]) && (transaction_duplicate[0])) || ((! conflict[1]) && (transaction_duplicate[1])) @@ -595,32 +553,28 @@ insert8 (struct PostgresClosure *pg, { GNUNET_break (0); TEH_PG_rollback (pg); - results[0] = GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR; } - results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; return qs3; } enum GNUNET_DB_QueryStatus -TEH_PG_reserves_in_insert (void *cls, - const struct - TALER_EXCHANGEDB_ReserveInInfo *reserves, - unsigned int reserves_length, - unsigned int batch_size, - enum GNUNET_DB_QueryStatus *results) +TEH_PG_reserves_in_insert ( + void *cls, + const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, + unsigned int reserves_length, + unsigned int batch_size, + enum GNUNET_DB_QueryStatus *results) { struct PostgresClosure *pg = cls; enum GNUNET_DB_QueryStatus qs1; enum GNUNET_DB_QueryStatus qs2; enum GNUNET_DB_QueryStatus qs4; enum GNUNET_DB_QueryStatus qs5; - struct TALER_PaytoHashP h_payto; uint64_t reserve_uuid[reserves_length]; bool transaction_duplicate[reserves_length]; bool need_update = false; - bool t_duplicate = false; struct GNUNET_TIME_Timestamp reserve_expiration = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time); struct GNUNET_TIME_Timestamp gc @@ -672,19 +626,18 @@ TEH_PG_reserves_in_insert (void *cls, qs1 = insert8 (pg, &reserves[i], gc, - h_payto, ¬ify_s[i], reserve_expiration, &transaction_duplicate[i], &conflicts[i], - &reserve_uuid[i], - &results[i]); + &reserve_uuid[i]); if (qs1<0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to create reserve batch_8 (%d)\n", qs1); + results[i] = qs1; return qs1; } need_update |= conflicts[i]; @@ -695,14 +648,10 @@ TEH_PG_reserves_in_insert (void *cls, need_update |= conflicts[i + 5]; need_update |= conflicts[i + 6]; need_update |= conflicts[i + 7]; - t_duplicate |= transaction_duplicate[i]; - t_duplicate |= transaction_duplicate[i + 1]; - t_duplicate |= transaction_duplicate[i + 2]; - t_duplicate |= transaction_duplicate[i + 3]; - t_duplicate |= transaction_duplicate[i + 4]; - t_duplicate |= transaction_duplicate[i + 5]; - t_duplicate |= transaction_duplicate[i + 6]; - t_duplicate |= transaction_duplicate[i + 7]; + for (unsigned int j = 0; j<8; j++) + results[i + j] = transaction_duplicate[i + j] + ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; i += 8; continue; } @@ -715,29 +664,27 @@ TEH_PG_reserves_in_insert (void *cls, qs4 = insert4 (pg, &reserves[i], gc, - h_payto, ¬ify_s[i], reserve_expiration, &transaction_duplicate[i], &conflicts[i], - &reserve_uuid[i], - &results[i]); - + &reserve_uuid[i]); if (qs4<0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to create reserve batch_4 (%d)\n", qs4); + results[i] = qs4; return qs4; } need_update |= conflicts[i]; need_update |= conflicts[i + 1]; need_update |= conflicts[i + 2]; need_update |= conflicts[i + 3]; - t_duplicate |= transaction_duplicate[i]; - t_duplicate |= transaction_duplicate[i + 1]; - t_duplicate |= transaction_duplicate[i + 2]; - t_duplicate |= transaction_duplicate[i + 3]; + for (unsigned int j = 0; j<4; j++) + results[i + j] = transaction_duplicate[i + j] + ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; i += 4; break; case 3: @@ -745,52 +692,50 @@ TEH_PG_reserves_in_insert (void *cls, qs5 = insert2 (pg, &reserves[i], gc, - h_payto, ¬ify_s[i], reserve_expiration, &transaction_duplicate[i], &conflicts[i], - &reserve_uuid[i], - &results[i]); + &reserve_uuid[i]); if (qs5<0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to create reserve batch_2 (%d)\n", qs5); + results[i] = qs5; return qs5; } need_update |= conflicts[i]; need_update |= conflicts[i + 1]; - t_duplicate |= transaction_duplicate[i]; - t_duplicate |= transaction_duplicate[i + 1]; - results[i] = (t_duplicate) - ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + for (unsigned int j = 0; j<2; j++) + results[i + j] = transaction_duplicate[i + j] + ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; i += 2; break; case 1: qs2 = insert1 (pg, &reserves[i], gc, - h_payto, ¬ify_s[i], reserve_expiration, &transaction_duplicate[i], &conflicts[i], - &reserve_uuid[i], - &results[i]); + &reserve_uuid[i]); fprintf (stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], conflicts[i], transaction_duplicate[i]); if (qs2<0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to create reserve batch_1 (%d)\n)" - ,qs2); + "Failed to create reserve batch_1 (%d)\n)", + qs2); + results[i] = qs2; return qs2; } need_update |= conflicts[i]; - t_duplicate |= transaction_duplicate[i]; - + results[i] = (transaction_duplicate[i]) + ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; i += 1; break; case 0: @@ -825,7 +770,6 @@ TEH_PG_reserves_in_insert (void *cls, } } - enum GNUNET_DB_QueryStatus qs3; PREPARE (pg, "reserves_update", "SELECT" @@ -838,6 +782,7 @@ TEH_PG_reserves_in_insert (void *cls, continue; { bool duplicate; + struct TALER_PaytoHashP h_payto; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub), GNUNET_PQ_query_param_timestamp (&reserve_expiration), @@ -853,6 +798,10 @@ TEH_PG_reserves_in_insert (void *cls, &duplicate), GNUNET_PQ_result_spec_end }; + enum GNUNET_DB_QueryStatus qs3; + + TALER_payto_hash (reserves[i].sender_account_details, + &h_payto); qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "reserves_update", params, From ee6ec1f55d1557101341ac7a02cf5985aaed63e1 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 21 Apr 2023 10:50:35 +0200 Subject: [PATCH 37/50] -fix bug in sync --- contrib/gana | 2 +- src/exchangedb/pg_insert_records_by_table.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/gana b/contrib/gana index 7adfb722a..1ec4596bf 160000 --- a/contrib/gana +++ b/contrib/gana @@ -1 +1 @@ -Subproject commit 7adfb722ac988170a31cdfd8132073eb7f2a6c43 +Subproject commit 1ec4596bf4925ee24fc06d3e74d2a553b8239870 diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c index 73e6ccda1..5f6de25de 100644 --- a/src/exchangedb/pg_insert_records_by_table.c +++ b/src/exchangedb/pg_insert_records_by_table.c @@ -1407,7 +1407,7 @@ irbt_cb_table_purse_decision (struct PostgresClosure *pg, GNUNET_PQ_query_param_timestamp ( &td->details.purse_decision.action_timestamp), GNUNET_PQ_query_param_bool ( - &td->details.purse_decision.refunded), + td->details.purse_decision.refunded), GNUNET_PQ_query_param_end }; From 03deaeb1080289a9228e4eb39c2f4bb29980c89c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 21 Apr 2023 10:54:50 +0200 Subject: [PATCH 38/50] -fix doxygen --- contrib/microhttpd.tag | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contrib/microhttpd.tag b/contrib/microhttpd.tag index d80405036..5156a1a3a 100644 --- a/contrib/microhttpd.tag +++ b/contrib/microhttpd.tag @@ -46,6 +46,12 @@ microhttpd.h + + #define + MHD_HTTP_CONTENT_TOO_LARGE + microhttpd.h + + #define MHD_HTTP_REQUEST_TIMEOUT From 5290453e3630fdca0a4c79806db6a3e0c04d4746 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 21 Apr 2023 22:30:37 +0200 Subject: [PATCH 39/50] clean up reserve_get logic --- contrib/gana | 2 +- .../taler-exchange-httpd_reserves_get.c | 315 ++++++++---------- src/exchangedb/pg_reserves_in_insert.c | 6 +- 3 files changed, 146 insertions(+), 177 deletions(-) diff --git a/contrib/gana b/contrib/gana index 1ec4596bf..bf43b20a0 160000 --- a/contrib/gana +++ b/contrib/gana @@ -1 +1 @@ -Subproject commit 1ec4596bf4925ee24fc06d3e74d2a553b8239870 +Subproject commit bf43b20a0362ac19bcf1bab9c33215e55d8d9f36 diff --git a/src/exchange/taler-exchange-httpd_reserves_get.c b/src/exchange/taler-exchange-httpd_reserves_get.c index 88f7aca9c..003db9260 100644 --- a/src/exchange/taler-exchange-httpd_reserves_get.c +++ b/src/exchange/taler-exchange-httpd_reserves_get.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -62,6 +62,16 @@ struct ReservePoller */ struct GNUNET_TIME_Absolute timeout; + /** + * Public key of the reserve the inquiry is about. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Balance of the reserve, set in the callback. + */ + struct TALER_Amount balance; + /** * True if we are still suspended. */ @@ -84,13 +94,10 @@ static struct ReservePoller *rp_tail; void TEH_reserves_get_cleanup () { - struct ReservePoller *rp; - - while (NULL != (rp = rp_head)) + for (struct ReservePoller *rp = rp_head; + NULL != rp; + rp = rp->next) { - GNUNET_CONTAINER_DLL_remove (rp_head, - rp_tail, - rp); if (rp->suspended) { rp->suspended = false; @@ -115,11 +122,14 @@ rp_cleanup (struct TEH_RequestContext *rc) if (NULL != rp->eh) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Cancelling DB event listening\n"); + "Cancelling DB event listening on cleanup (odd unless during shutdown)\n"); TEH_plugin->event_listen_cancel (TEH_plugin->cls, rp->eh); rp->eh = NULL; } + GNUNET_CONTAINER_DLL_remove (rp_head, + rp_tail, + rp); GNUNET_free (rp); } @@ -143,20 +153,14 @@ db_event_cb (void *cls, (void) extra; (void) extra_size; - if (NULL == rp) - return; /* event triggered while main transaction - was still running */ if (! rp->suspended) return; /* might get multiple wake-up events */ - rp->suspended = false; GNUNET_async_scope_enter (&rc->async_scope_id, &old_scope); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Resuming from long-polling on reserve\n"); TEH_check_invariants (); - GNUNET_CONTAINER_DLL_remove (rp_head, - rp_tail, - rp); + rp->suspended = false; MHD_resume_connection (rp->connection); TALER_MHD_daemon_trigger (); TEH_check_invariants (); @@ -164,191 +168,154 @@ db_event_cb (void *cls, } -/** - * Closure for #reserve_history_transaction. - */ -struct ReserveHistoryContext -{ - /** - * Public key of the reserve the inquiry is about. - */ - struct TALER_ReservePublicKeyP reserve_pub; - - /** - * Balance of the reserve, set in the callback. - */ - struct TALER_Amount balance; - - /** - * Set to true if we did not find the reserve. - */ - bool not_found; -}; - - -/** - * Function implementing /reserves/ GET transaction. - * Execute a /reserves/ GET. Given the public key of a reserve, - * return the associated transaction history. Runs the - * transaction logic; IF it returns a non-error code, the transaction - * logic MUST NOT queue a MHD response. IF it returns an hard error, - * the transaction logic MUST queue a MHD response and set @a mhd_ret. - * IF it returns the soft error code, the function MAY be called again - * to retry and MUST not queue a MHD response. - * - * @param cls a `struct ReserveHistoryContext *` - * @param connection MHD request which triggered the transaction - * @param[out] mhd_ret set to MHD response status for @a connection, - * if transaction failed (!) - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -reserve_balance_transaction (void *cls, - struct MHD_Connection *connection, - MHD_RESULT *mhd_ret) -{ - struct ReserveHistoryContext *rsc = cls; - enum GNUNET_DB_QueryStatus qs; - - qs = TEH_plugin->get_reserve_balance (TEH_plugin->cls, - &rsc->reserve_pub, - &rsc->balance); - if (GNUNET_DB_STATUS_HARD_ERROR == qs) - { - GNUNET_break (0); - *mhd_ret - = TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - "get_reserve_balance"); - } - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) - rsc->not_found = true; - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) - rsc->not_found = false; - return qs; -} - - MHD_RESULT TEH_handler_reserves_get (struct TEH_RequestContext *rc, const char *const args[1]) { - struct ReserveHistoryContext rsc; - struct GNUNET_TIME_Relative timeout = GNUNET_TIME_UNIT_ZERO; - struct GNUNET_DB_EventHandler *eh = NULL; + struct ReservePoller *rp = rc->rh_ctx; - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (args[0], - strlen (args[0]), - &rsc.reserve_pub, - sizeof (rsc.reserve_pub))) + if (NULL == rp) { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_RESERVE_PUB_MALFORMED, - args[0]); - } - { - const char *long_poll_timeout_ms; + struct GNUNET_TIME_Relative timeout + = GNUNET_TIME_UNIT_ZERO; - long_poll_timeout_ms - = MHD_lookup_connection_value (rc->connection, - MHD_GET_ARGUMENT_KIND, - "timeout_ms"); - if (NULL != long_poll_timeout_ms) + rp = GNUNET_new (struct ReservePoller); + rp->connection = rc->connection; + rc->rh_ctx = rp; + rc->rh_cleaner = &rp_cleanup; + GNUNET_CONTAINER_DLL_insert (rp_head, + rp_tail, + rp); + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[0], + strlen (args[0]), + &rp->reserve_pub, + sizeof (rp->reserve_pub))) { - unsigned int timeout_ms; - char dummy; - - if (1 != sscanf (long_poll_timeout_ms, - "%u%c", - &timeout_ms, - &dummy)) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "timeout_ms (must be non-negative number)"); - } - timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, - timeout_ms); + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_RESERVE_PUB_MALFORMED, + args[0]); } + { + const char *long_poll_timeout_ms; + + long_poll_timeout_ms + = MHD_lookup_connection_value (rc->connection, + MHD_GET_ARGUMENT_KIND, + "timeout_ms"); + if (NULL != long_poll_timeout_ms) + { + unsigned int timeout_ms; + char dummy; + + if (1 != sscanf (long_poll_timeout_ms, + "%u%c", + &timeout_ms, + &dummy)) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "timeout_ms (must be non-negative number)"); + } + timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, + timeout_ms); + } + } + rp->timeout = GNUNET_TIME_relative_to_absolute (timeout); } - if ( (! GNUNET_TIME_relative_is_zero (timeout)) && - (NULL == rc->rh_ctx) ) + + if ( (GNUNET_TIME_absolute_is_future (rp->timeout)) && + (NULL == rp->eh) ) { struct TALER_ReserveEventP rep = { .header.size = htons (sizeof (rep)), .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING), - .reserve_pub = rsc.reserve_pub + .reserve_pub = rp->reserve_pub }; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting DB event listening\n"); - eh = TEH_plugin->event_listen (TEH_plugin->cls, - timeout, - &rep.header, - &db_event_cb, - rc); + rp->eh = TEH_plugin->event_listen ( + TEH_plugin->cls, + GNUNET_TIME_absolute_get_remaining (rp->timeout), + &rep.header, + &db_event_cb, + rp); } { - MHD_RESULT mhd_ret; + enum GNUNET_DB_QueryStatus qs; - if (GNUNET_OK != - TEH_DB_run_transaction (rc->connection, - "get reserve balance", - TEH_MT_REQUEST_OTHER, - &mhd_ret, - &reserve_balance_transaction, - &rsc)) + qs = TEH_plugin->get_reserve_balance (TEH_plugin->cls, + &rp->reserve_pub, + &rp->balance); + switch (qs) { - if (NULL != eh) + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_break (0); /* single-shot query should never have soft-errors */ + if (NULL != rp->eh) + { TEH_plugin->event_listen_cancel (TEH_plugin->cls, - eh); - return mhd_ret; - } - } - /* generate proper response */ - if (rsc.not_found) - { - struct ReservePoller *rp = rc->rh_ctx; - - if ( (NULL != rp) || - (GNUNET_TIME_relative_is_zero (timeout)) ) - { + rp->eh); + rp->eh = NULL; + } return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_EXCHANGE_RESERVES_STATUS_UNKNOWN, - args[0]); + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_SOFT_FAILURE, + "get_reserve_balance"); + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + if (NULL != rp->eh) + { + TEH_plugin->event_listen_cancel (TEH_plugin->cls, + rp->eh); + rp->eh = NULL; + } + return TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "get_reserve_balance"); + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + if (NULL != rp->eh) + { + TEH_plugin->event_listen_cancel (TEH_plugin->cls, + rp->eh); + rp->eh = NULL; + } + return TALER_MHD_REPLY_JSON_PACK (rc->connection, + MHD_HTTP_OK, + TALER_JSON_pack_amount ("balance", + &rp->balance)); + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + if ( (NULL != rp) || + (GNUNET_TIME_absolute_is_future (rp->timeout)) ) + { + if (NULL != rp->eh) + { + TEH_plugin->event_listen_cancel (TEH_plugin->cls, + rp->eh); + rp->eh = NULL; + } + return TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_EXCHANGE_RESERVES_STATUS_UNKNOWN, + args[0]); + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Long-polling on reserve for %s\n", + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_remaining (rp->timeout), + true)); + rp->suspended = true; + MHD_suspend_connection (rc->connection); + return MHD_YES; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Long-polling on reserve for %s\n", - GNUNET_STRINGS_relative_time_to_string (timeout, - GNUNET_YES)); - rp = GNUNET_new (struct ReservePoller); - rp->connection = rc->connection; - rp->timeout = GNUNET_TIME_relative_to_absolute (timeout); - rp->eh = eh; - rc->rh_ctx = rp; - rc->rh_cleaner = &rp_cleanup; - rp->suspended = true; - GNUNET_CONTAINER_DLL_insert (rp_head, - rp_tail, - rp); - MHD_suspend_connection (rc->connection); - return MHD_YES; } - if (NULL != eh) - TEH_plugin->event_listen_cancel (TEH_plugin->cls, - eh); - return TALER_MHD_REPLY_JSON_PACK ( - rc->connection, - MHD_HTTP_OK, - TALER_JSON_pack_amount ("balance", - &rsc.balance)); + GNUNET_break (0); + return MHD_NO; } diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c index 71c57f844..876774de9 100644 --- a/src/exchangedb/pg_reserves_in_insert.c +++ b/src/exchangedb/pg_reserves_in_insert.c @@ -722,8 +722,6 @@ TEH_PG_reserves_in_insert ( &transaction_duplicate[i], &conflicts[i], &reserve_uuid[i]); - fprintf (stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], - conflicts[i], transaction_duplicate[i]); if (qs2<0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -825,7 +823,11 @@ TEH_PG_reserves_in_insert ( cs = TEH_PG_commit (pg); if (cs < 0) + { + for (unsigned int i = 0; i Date: Sat, 22 Apr 2023 01:20:41 +0200 Subject: [PATCH 40/50] misc bugfixes in reserves_in batch logic --- .../taler-exchange-httpd_reserves_get.c | 40 +- .../exchange_do_reserves_in_insert.sql | 1349 ++++++++--------- src/exchangedb/pg_reserves_in_insert.c | 1018 +++++-------- src/testing/testing_api_cmd_exec_wirewatch.c | 1 - src/testing/testing_api_loop.c | 2 +- 5 files changed, 1082 insertions(+), 1328 deletions(-) diff --git a/src/exchange/taler-exchange-httpd_reserves_get.c b/src/exchange/taler-exchange-httpd_reserves_get.c index 003db9260..c22e62bf5 100644 --- a/src/exchange/taler-exchange-httpd_reserves_get.c +++ b/src/exchange/taler-exchange-httpd_reserves_get.c @@ -147,18 +147,13 @@ db_event_cb (void *cls, const void *extra, size_t extra_size) { - struct TEH_RequestContext *rc = cls; - struct ReservePoller *rp = rc->rh_ctx; + struct ReservePoller *rp = cls; struct GNUNET_AsyncScopeSave old_scope; (void) extra; (void) extra_size; if (! rp->suspended) return; /* might get multiple wake-up events */ - GNUNET_async_scope_enter (&rc->async_scope_id, - &old_scope); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Resuming from long-polling on reserve\n"); TEH_check_invariants (); rp->suspended = false; MHD_resume_connection (rp->connection); @@ -238,7 +233,8 @@ TEH_handler_reserves_get (struct TEH_RequestContext *rc, }; GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Starting DB event listening\n"); + "Starting DB event listening until %s\n", + GNUNET_TIME_absolute2s (rp->timeout)); rp->eh = TEH_plugin->event_listen ( TEH_plugin->cls, GNUNET_TIME_absolute_get_remaining (rp->timeout), @@ -256,49 +252,27 @@ TEH_handler_reserves_get (struct TEH_RequestContext *rc, { case GNUNET_DB_STATUS_SOFT_ERROR: GNUNET_break (0); /* single-shot query should never have soft-errors */ - if (NULL != rp->eh) - { - TEH_plugin->event_listen_cancel (TEH_plugin->cls, - rp->eh); - rp->eh = NULL; - } return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_SOFT_FAILURE, "get_reserve_balance"); case GNUNET_DB_STATUS_HARD_ERROR: GNUNET_break (0); - if (NULL != rp->eh) - { - TEH_plugin->event_listen_cancel (TEH_plugin->cls, - rp->eh); - rp->eh = NULL; - } return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, "get_reserve_balance"); case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - if (NULL != rp->eh) - { - TEH_plugin->event_listen_cancel (TEH_plugin->cls, - rp->eh); - rp->eh = NULL; - } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got reserve balance of %s\n", + TALER_amount2s (&rp->balance)); return TALER_MHD_REPLY_JSON_PACK (rc->connection, MHD_HTTP_OK, TALER_JSON_pack_amount ("balance", &rp->balance)); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - if ( (NULL != rp) || - (GNUNET_TIME_absolute_is_future (rp->timeout)) ) + if (! GNUNET_TIME_absolute_is_future (rp->timeout)) { - if (NULL != rp->eh) - { - TEH_plugin->event_listen_cancel (TEH_plugin->cls, - rp->eh); - rp->eh = NULL; - } return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_NOT_FOUND, TALER_EC_EXCHANGE_RESERVES_STATUS_UNKNOWN, diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql index 3a217accf..e7506dc85 100644 --- a/src/exchangedb/exchange_do_reserves_in_insert.sql +++ b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -23,12 +23,12 @@ CREATE OR REPLACE FUNCTION exchange_do_batch_reserves_in_insert( IN in_credit_frac INT4, IN in_exchange_account_name VARCHAR, IN in_execution_date INT8, - IN in_wire_source_h_payto BYTEA, ---h_payto + IN in_wire_source_h_payto BYTEA, IN in_payto_uri VARCHAR, - IN in_notify text, - OUT out_reserve_found BOOLEAN, - OUT transaction_duplicate BOOLEAN, - OUT ruuid INT8) + IN in_notify TEXT, + OUT out_reserve_found0 BOOLEAN, + OUT transaction_duplicate0 BOOLEAN, + OUT ruuid0 INT8) LANGUAGE plpgsql AS $$ DECLARE @@ -38,11 +38,10 @@ DECLARE DECLARE curs_trans refcursor; BEGIN - ruuid = 0; - out_reserve_found = TRUE; - transaction_duplicate = TRUE; + ruuid0 = 0; + out_reserve_found0 = TRUE; + transaction_duplicate0 = TRUE; ---SIMPLE INSERT ON CONFLICT DO NOTHING INSERT INTO wire_targets (wire_target_h_payto ,payto_uri) @@ -65,18 +64,16 @@ BEGIN ,in_credit_frac ,in_reserve_expiration ,in_gc_date) - ON CONFLICT DO NOTHING - RETURNING reserve_uuid, reserve_pub) - SELECT * FROM reserve_changes; + ON CONFLICT DO NOTHING + RETURNING reserve_uuid, reserve_pub) + SELECT reserve_uuid, reserve_pub FROM reserve_changes; + FETCH FROM curs INTO i; IF FOUND THEN -- We made a change, so the reserve did not previously exist. - IF in_reserve_pub = i.reserve_pub - THEN - out_reserve_found = FALSE; - ruuid = i.reserve_uuid; - END IF; + out_reserve_found0 = FALSE; + ruuid0 = i.reserve_uuid; END IF; CLOSE curs; @@ -100,56 +97,56 @@ BEGIN ,in_execution_date) ON CONFLICT DO NOTHING RETURNING reserve_pub) - SELECT * FROM reserve_transaction; + SELECT reserve_pub FROM reserve_transaction; + FETCH FROM curs_trans INTO i; IF FOUND THEN - IF i.reserve_pub = in_reserve_pub - THEN - -- HAPPY PATH THERE IS NO DUPLICATE TRANS - transaction_duplicate = FALSE; - EXECUTE FORMAT ( + transaction_duplicate0 = FALSE; + EXECUTE FORMAT ( 'NOTIFY %s' ,in_notify); - END IF; END IF; + CLOSE curs_trans; + RETURN; END $$; + CREATE OR REPLACE FUNCTION exchange_do_batch2_reserves_insert( IN in_gc_date INT8, IN in_reserve_expiration INT8, - IN in_reserve_pub BYTEA, - IN in_wire_ref INT8, - IN in_credit_val INT8, - IN in_credit_frac INT4, - IN in_exchange_account_name VARCHAR, - IN in_execution_date INT8, - IN in_wire_source_h_payto BYTEA, ---h_payto - IN in_payto_uri VARCHAR, - IN in_notify text, - IN in2_notify text, - IN in2_reserve_pub BYTEA, - IN in2_wire_ref INT8, - IN in2_credit_val INT8, - IN in2_credit_frac INT4, - IN in2_exchange_account_name VARCHAR, - IN in2_execution_date INT8, - IN in2_wire_source_h_payto BYTEA, ---h_payto - IN in2_payto_uri VARCHAR, - OUT out_reserve_found BOOLEAN, - OUT out_reserve_found2 BOOLEAN, - OUT transaction_duplicate BOOLEAN, - OUT transaction_duplicate2 BOOLEAN, - OUT ruuid INT8, - OUT ruuid2 INT8) + IN in0_reserve_pub BYTEA, + IN in0_wire_ref INT8, + IN in0_credit_val INT8, + IN in0_credit_frac INT4, + IN in0_exchange_account_name VARCHAR, + IN in0_execution_date INT8, + IN in0_wire_source_h_payto BYTEA, + IN in0_payto_uri VARCHAR, + IN in0_notify TEXT, + IN in1_reserve_pub BYTEA, + IN in1_wire_ref INT8, + IN in1_credit_val INT8, + IN in1_credit_frac INT4, + IN in1_exchange_account_name VARCHAR, + IN in1_execution_date INT8, + IN in1_wire_source_h_payto BYTEA, + IN in1_payto_uri VARCHAR, + IN in1_notify TEXT, + OUT out_reserve_found0 BOOLEAN, + OUT out_reserve_found1 BOOLEAN, + OUT transaction_duplicate0 BOOLEAN, + OUT transaction_duplicate1 BOOLEAN, + OUT ruuid0 INT8, + OUT ruuid1 INT8) LANGUAGE plpgsql AS $$ DECLARE curs_reserve_exist REFCURSOR; DECLARE - curs_transaction_exist refcursor; + curs_transaction_exist REFCURSOR; DECLARE i RECORD; DECLARE @@ -157,21 +154,21 @@ DECLARE DECLARE k INT8; BEGIN - transaction_duplicate=TRUE; - transaction_duplicate2=TRUE; - out_reserve_found = TRUE; - out_reserve_found2 = TRUE; - ruuid=0; - ruuid2=0; - k=0; + transaction_duplicate0 = TRUE; + transaction_duplicate1 = TRUE; + out_reserve_found0 = TRUE; + out_reserve_found1 = TRUE; + ruuid0=0; + ruuid1=0; + INSERT INTO wire_targets (wire_target_h_payto ,payto_uri) VALUES - (in_wire_source_h_payto - ,in_payto_uri), - (in2_wire_source_h_payto - ,in2_payto_uri) + (in0_wire_source_h_payto + ,in0_payto_uri), + (in1_wire_source_h_payto + ,in1_payto_uri) ON CONFLICT DO NOTHING; OPEN curs_reserve_exist FOR @@ -183,39 +180,51 @@ BEGIN ,expiration_date ,gc_date) VALUES - (in_reserve_pub - ,in_credit_val - ,in_credit_frac + (in0_reserve_pub + ,in0_credit_val + ,in0_credit_frac ,in_reserve_expiration ,in_gc_date), - (in2_reserve_pub - ,in2_credit_val - ,in2_credit_frac + (in1_reserve_pub + ,in1_credit_val + ,in1_credit_frac ,in_reserve_expiration ,in_gc_date) - ON CONFLICT DO NOTHING - RETURNING reserve_uuid,reserve_pub) - SELECT * FROM reserve_changes; - WHILE k < 2 LOOP + ON CONFLICT DO NOTHING + RETURNING reserve_uuid, reserve_pub) + SELECT reserve_uuid, reserve_pub FROM reserve_changes; + + k=0; + <> LOOP FETCH FROM curs_reserve_exist INTO i; - IF FOUND + IF NOT FOUND THEN - IF in_reserve_pub = i.reserve_pub - THEN - ruuid = i.reserve_uuid; - IF in_reserve_pub <> in2_reserve_pub - THEN - out_reserve_found = FALSE; - END IF; - END IF; - IF in2_reserve_pub = i.reserve_pub - THEN - out_reserve_found2 = FALSE; - ruuid2 = i.reserve_uuid; - END IF; + EXIT loop_reserve; END IF; - k=k+1; - END LOOP; + + <> LOOP + CASE k + WHEN 0 THEN + k = k + 1; + IF in0_reserve_pub = i.reserve_pub + THEN + ruuid0 = i.reserve_uuid; + out_reserve_found0 = FALSE; + CONTINUE loop_reserve; + END IF; + CONTINUE loop_k; + WHEN 1 THEN + IF in1_reserve_pub = i.reserve_pub + THEN + ruuid1 = i.reserve_uuid; + out_reserve_found1 = FALSE; + EXIT loop_reserve; + END IF; + EXIT loop_k; + END CASE; + END LOOP loop_k; + END LOOP loop_reserve; + CLOSE curs_reserve_exist; OPEN curs_transaction_exist FOR @@ -229,160 +238,153 @@ BEGIN ,wire_source_h_payto ,execution_date) VALUES - (in_reserve_pub - ,in_wire_ref - ,in_credit_val - ,in_credit_frac - ,in_exchange_account_name - ,in_wire_source_h_payto - ,in_execution_date), - (in2_reserve_pub - ,in2_wire_ref - ,in2_credit_val - ,in2_credit_frac - ,in2_exchange_account_name - ,in2_wire_source_h_payto - ,in2_execution_date) + (in0_reserve_pub + ,in0_wire_ref + ,in0_credit_val + ,in0_credit_frac + ,in0_exchange_account_name + ,in0_wire_source_h_payto + ,in0_execution_date), + (in1_reserve_pub + ,in1_wire_ref + ,in1_credit_val + ,in1_credit_frac + ,in1_exchange_account_name + ,in1_wire_source_h_payto + ,in1_execution_date) ON CONFLICT DO NOTHING RETURNING reserve_pub) - SELECT * FROM reserve_in_exist; + SELECT reserve_pub FROM reserve_in_exist; + FETCH FROM curs_transaction_exist INTO r; - IF FOUND - THEN - IF in_reserve_pub = r.reserve_pub + + k=0; + <> LOOP + FETCH FROM curs_transaction_exist INTO i; + IF NOT FOUND THEN - transaction_duplicate = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in_notify); + EXIT loop_transaction; END IF; - IF in2_reserve_pub = r.reserve_pub - THEN - transaction_duplicate2 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in2_notify); - END IF; - FETCH FROM curs_transaction_exist INTO r; - IF FOUND - THEN - IF in_reserve_pub = r.reserve_pub - THEN - transaction_duplicate = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in_notify); - END IF; - IF in2_reserve_pub = r.reserve_pub - THEN - transaction_duplicate2 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in2_notify); - END IF; - END IF; - END IF; -/* IF transaction_duplicate - OR transaction_duplicate2 - THEN - CLOSE curs_transaction_exist; - ROLLBACK; - RETURN; - END IF;*/ + + <> LOOP + CASE k + WHEN 0 THEN + k = k + 1; + IF in0_reserve_pub = r.reserve_pub + THEN + transaction_duplicate0 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in0_notify); + CONTINUE loop_transaction; + END IF; + CONTINUE loop2_k; + WHEN 1 THEN + IF in0_reserve_pub = r.reserve_pub + THEN + transaction_duplicate1 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in1_notify); + EXIT loop_transaction; + END IF; + END CASE; + END LOOP loop2_k; + END LOOP loop_transaction; + CLOSE curs_transaction_exist; + RETURN; END $$; + CREATE OR REPLACE FUNCTION exchange_do_batch4_reserves_insert( IN in_gc_date INT8, IN in_reserve_expiration INT8, - IN in_reserve_pub BYTEA, - IN in_wire_ref INT8, - IN in_credit_val INT8, - IN in_credit_frac INT4, - IN in_exchange_account_name VARCHAR, - IN in_execution_date INT8, - IN in_wire_source_h_payto BYTEA, ---h_payto - IN in_payto_uri VARCHAR, - IN in_notify text, - IN in2_notify text, - IN in3_notify text, - IN in4_notify text, + IN in0_reserve_pub BYTEA, + IN in0_wire_ref INT8, + IN in0_credit_val INT8, + IN in0_credit_frac INT4, + IN in0_exchange_account_name VARCHAR, + IN in0_execution_date INT8, + IN in0_wire_source_h_payto BYTEA, + IN in0_payto_uri VARCHAR, + IN in0_notify TEXT, + IN in1_reserve_pub BYTEA, + IN in1_wire_ref INT8, + IN in1_credit_val INT8, + IN in1_credit_frac INT4, + IN in1_exchange_account_name VARCHAR, + IN in1_execution_date INT8, + IN in1_wire_source_h_payto BYTEA, + IN in1_payto_uri VARCHAR, + IN in1_notify TEXT, IN in2_reserve_pub BYTEA, IN in2_wire_ref INT8, IN in2_credit_val INT8, IN in2_credit_frac INT4, IN in2_exchange_account_name VARCHAR, IN in2_execute_date INT8, - IN in2_wire_source_h_payto BYTEA, ---h_payto + IN in2_wire_source_h_payto BYTEA, IN in2_payto_uri VARCHAR, + IN in2_notify TEXT, IN in3_reserve_pub BYTEA, IN in3_wire_ref INT8, IN in3_credit_val INT8, IN in3_credit_frac INT4, IN in3_exchange_account_name VARCHAR, IN in3_execute_date INT8, - IN in3_wire_source_h_payto BYTEA, ---h_payto + IN in3_wire_source_h_payto BYTEA, IN in3_payto_uri VARCHAR, - IN in4_reserve_pub BYTEA, - IN in4_wire_ref INT8, - IN in4_credit_val INT8, - IN in4_credit_frac INT4, - IN in4_exchange_account_name VARCHAR, - IN in4_execution_date INT8, - IN in4_wire_source_h_payto BYTEA, ---h_payto - IN in4_payto_uri VARCHAR, - OUT out_reserve_found BOOLEAN, + IN in3_notify TEXT, + OUT out_reserve_found0 BOOLEAN, + OUT out_reserve_found1 BOOLEAN, OUT out_reserve_found2 BOOLEAN, OUT out_reserve_found3 BOOLEAN, - OUT out_reserve_found4 BOOLEAN, - OUT transaction_duplicate BOOLEAN, + OUT transaction_duplicate0 BOOLEAN, + OUT transaction_duplicate1 BOOLEAN, OUT transaction_duplicate2 BOOLEAN, OUT transaction_duplicate3 BOOLEAN, - OUT transaction_duplicate4 BOOLEAN, - OUT ruuid INT8, + OUT ruuid0 INT8, + OUT ruuid1 INT8, OUT ruuid2 INT8, - OUT ruuid3 INT8, - OUT ruuid4 INT8) + OUT ruuid3 INT8) LANGUAGE plpgsql AS $$ DECLARE - curs_reserve_exist refcursor; + curs_reserve_exist REFCURSOR; DECLARE k INT8; DECLARE - curs_transaction_exist refcursor; + curs_transaction_exist REFCURSOR; DECLARE i RECORD; - BEGIN ---INITIALIZATION - transaction_duplicate=TRUE; + transaction_duplicate0=TRUE; + transaction_duplicate1=TRUE; transaction_duplicate2=TRUE; transaction_duplicate3=TRUE; - transaction_duplicate4=TRUE; - out_reserve_found = TRUE; + out_reserve_found0 = TRUE; + out_reserve_found1 = TRUE; out_reserve_found2 = TRUE; out_reserve_found3 = TRUE; - out_reserve_found4 = TRUE; - ruuid=0; + ruuid0=0; + ruuid1=0; ruuid2=0; ruuid3=0; - ruuid4=0; - k=0; - --SIMPLE INSERT ON CONFLICT DO NOTHING + INSERT INTO wire_targets (wire_target_h_payto ,payto_uri) VALUES - (in_wire_source_h_payto - ,in_payto_uri), + (in0_wire_source_h_payto + ,in0_payto_uri), + (in1_wire_source_h_payto + ,in1_payto_uri), (in2_wire_source_h_payto ,in2_payto_uri), (in3_wire_source_h_payto - ,in3_payto_uri), - (in4_wire_source_h_payto - ,in4_payto_uri) + ,in3_payto_uri) ON CONFLICT DO NOTHING; OPEN curs_reserve_exist FOR @@ -394,9 +396,14 @@ BEGIN ,expiration_date ,gc_date) VALUES - (in_reserve_pub - ,in_credit_val - ,in_credit_frac + (in0_reserve_pub + ,in0_credit_val + ,in0_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in1_reserve_pub + ,in1_credit_val + ,in1_credit_frac ,in_reserve_expiration ,in_gc_date), (in2_reserve_pub @@ -408,310 +415,313 @@ BEGIN ,in3_credit_val ,in3_credit_frac ,in_reserve_expiration - ,in_gc_date), - (in4_reserve_pub - ,in4_credit_val - ,in4_credit_frac - ,in_reserve_expiration ,in_gc_date) - ON CONFLICT DO NOTHING - RETURNING reserve_uuid,reserve_pub) - SELECT * FROM reserve_changes; - - WHILE k < 4 LOOP - FETCH FROM curs_reserve_exist INTO i; - IF FOUND - THEN - IF in_reserve_pub = i.reserve_pub - THEN - ruuid = i.reserve_uuid; - IF in_reserve_pub - NOT IN (in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub) - THEN - out_reserve_found = FALSE; - END IF; - END IF; - IF in2_reserve_pub = i.reserve_pub - THEN - ruuid2 = i.reserve_uuid; - IF in2_reserve_pub - NOT IN (in_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub) - THEN - out_reserve_found2 = FALSE; - END IF; - END IF; - IF in3_reserve_pub = i.reserve_pub - THEN - ruuid3 = i.reserve_uuid; - IF in3_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in4_reserve_pub) - THEN - out_reserve_found3 = FALSE; - END IF; - END IF; - IF in4_reserve_pub = i.reserve_pub - THEN - ruuid4 = i.reserve_uuid; - IF in4_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub) - THEN - out_reserve_found4 = FALSE; - END IF; - END IF; - END IF; - k=k+1; - END LOOP; - CLOSE curs_reserve_exist; + ON CONFLICT DO NOTHING + RETURNING reserve_uuid,reserve_pub) + SELECT reserve_uuid, reserve_pub FROM reserve_changes; k=0; - OPEN curs_transaction_exist FOR - WITH reserve_in_changes AS ( - INSERT INTO reserves_in - (reserve_pub - ,wire_reference - ,credit_val - ,credit_frac - ,exchange_account_section - ,wire_source_h_payto - ,execution_date) - VALUES - (in_reserve_pub - ,in_wire_ref - ,in_credit_val - ,in_credit_frac - ,in_exchange_account_name - ,in_wire_source_h_payto - ,in_execution_date), - (in2_reserve_pub - ,in2_wire_ref - ,in2_credit_val - ,in2_credit_frac - ,in2_exchange_account_name - ,in2_wire_source_h_payto - ,in2_execution_date), - (in3_reserve_pub - ,in3_wire_ref - ,in3_credit_val - ,in3_credit_frac - ,in3_exchange_account_name - ,in3_wire_source_h_payto - ,in3_execution_date), - (in4_reserve_pub - ,in4_wire_ref - ,in4_credit_val - ,in4_credit_frac - ,in4_exchange_account_name - ,in4_wire_source_h_payto - ,in4_execution_date) - ON CONFLICT DO NOTHING - RETURNING reserve_pub) - SELECT * FROM reserve_in_changes; - WHILE k < 4 LOOP - FETCH FROM curs_transaction_exist INTO i; - IF FOUND + <> LOOP + FETCH FROM curs_reserve_exist INTO i; + IF NOT FOUND THEN - IF in_reserve_pub = i.reserve_pub - THEN - transaction_duplicate = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in_notify); - END IF; - IF in2_reserve_pub = i.reserve_pub - THEN - transaction_duplicate2 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in2_notify); - END IF; - IF in3_reserve_pub = i.reserve_pub - THEN - transaction_duplicate3 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in3_notify); - END IF; - IF in4_reserve_pub = i.reserve_pub - THEN - transaction_duplicate4 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in4_notify); - END IF; + EXIT loop_reserve; END IF; - k=k+1; - END LOOP; - /**ROLLBACK TRANSACTION IN SORTED PROCEDURE IS IT PROSSIBLE ?**/ - /*IF transaction_duplicate - OR transaction_duplicate2 - OR transaction_duplicate3 - OR transaction_duplicate4 - THEN - RAISE EXCEPTION 'Reserve did not exist, but INSERT into reserves_in gave conflict'; - ROLLBACK; - CLOSE curs_transaction_exist; - RETURN; - END IF;*/ - CLOSE curs_transaction_exist; - RETURN; + <> LOOP + CASE k + WHEN 0 THEN + k = k + 1; + IF in0_reserve_pub = i.reserve_pub + THEN + ruuid0 = i.reserve_uuid; + out_reserve_found0 = FALSE; + CONTINUE loop_reserve; + END IF; + CONTINUE loop_k; + WHEN 1 THEN + k = k + 1; + IF in1_reserve_pub = i.reserve_pub + THEN + ruuid1 = i.reserve_uuid; + out_reserve_found1 = FALSE; + CONTINUE loop_reserve; + END IF; + CONTINUE loop_k; + WHEN 2 THEN + k = k + 1; + IF in2_reserve_pub = i.reserve_pub + THEN + ruuid2 = i.reserve_uuid; + out_reserve_found2 = FALSE; + CONTINUE loop_reserve; + END IF; + CONTINUE loop_k; + WHEN 3 THEN + IF in3_reserve_pub = i.reserve_pub + THEN + ruuid3 = i.reserve_uuid; + out_reserve_found3 = FALSE; + EXIT loop_reserve; + END IF; + EXIT loop_k; + END CASE; + END LOOP loop_k; + END LOOP loop_reserve; + + CLOSE curs_reserve_exist; + + OPEN curs_transaction_exist FOR + WITH reserve_changes AS ( + INSERT INTO reserves_in + (reserve_pub + ,wire_reference + ,credit_val + ,credit_frac + ,exchange_account_section + ,wire_source_h_payto + ,execution_date) + VALUES + (in0_reserve_pub + ,in0_wire_ref + ,in0_credit_val + ,in0_credit_frac + ,in0_exchange_account_name + ,in0_wire_source_h_payto + ,in0_execution_date), + (in1_reserve_pub + ,in1_wire_ref + ,in1_credit_val + ,in1_credit_frac + ,in1_exchange_account_name + ,in1_wire_source_h_payto + ,in1_execution_date), + (in2_reserve_pub + ,in2_wire_ref + ,in2_credit_val + ,in2_credit_frac + ,in2_exchange_account_name + ,in2_wire_source_h_payto + ,in2_execution_date), + (in3_reserve_pub + ,in3_wire_ref + ,in3_credit_val + ,in3_credit_frac + ,in3_exchange_account_name + ,in3_wire_source_h_payto + ,in3_execution_date) + ON CONFLICT DO NOTHING + RETURNING reserve_pub) + SELECT reserve_uuid, reserve_pub FROM reserve_changes; + + k=0; + <> LOOP + FETCH FROM curs_transaction_exist INTO i; + IF NOT FOUND + THEN + EXIT loop_transaction; + END IF; + + <> LOOP + CASE k + WHEN 0 THEN + k = k + 1; + IF in0_reserve_pub = r.reserve_pub + THEN + transaction_duplicate0 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in0_notify); + CONTINUE loop_transaction; + END IF; + CONTINUE loop2_k; + WHEN 1 THEN + k = k + 1; + IF in1_reserve_pub = r.reserve_pub + THEN + transaction_duplicate1 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in1_notify); + CONTINUE loop_transaction; + END IF; + CONTINUE loop2_k; + WHEN 2 THEN + k = k + 1; + IF in2_reserve_pub = r.reserve_pub + THEN + transaction_duplicate2 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in2_notify); + CONTINUE loop_transaction; + END IF; + CONTINUE loop2_k; + WHEN 3 THEN + IF in3_reserve_pub = r.reserve_pub + THEN + transaction_duplicate3 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in3_notify); + EXIT loop_transaction; + END IF; + END CASE; + END LOOP loop2_k; + END LOOP loop_transaction; + + CLOSE curs_transaction_exist; + + RETURN; END $$; + CREATE OR REPLACE FUNCTION exchange_do_batch8_reserves_insert( IN in_gc_date INT8, IN in_reserve_expiration INT8, - IN in_reserve_pub BYTEA, - IN in_wire_ref INT8, - IN in_credit_val INT8, - IN in_credit_frac INT4, - IN in_exchange_account_name VARCHAR, - IN in_execution_date INT8, - IN in_wire_source_h_payto BYTEA, ---h_payto - IN in_payto_uri VARCHAR, - IN in_notify text, - IN in2_notify text, - IN in3_notify text, - IN in4_notify text, - IN in5_notify text, - IN in6_notify text, - IN in7_notify text, - IN in8_notify text, + IN in0_reserve_pub BYTEA, + IN in0_wire_ref INT8, + IN in0_credit_val INT8, + IN in0_credit_frac INT4, + IN in0_exchange_account_name VARCHAR, + IN in0_execution_date INT8, + IN in0_wire_source_h_payto BYTEA, + IN in0_payto_uri VARCHAR, + IN in0_notify TEXT, + IN in1_reserve_pub BYTEA, + IN in1_wire_ref INT8, + IN in1_credit_val INT8, + IN in1_credit_frac INT4, + IN in1_exchange_account_name VARCHAR, + IN in1_execution_date INT8, + IN in1_wire_source_h_payto BYTEA, + IN in1_payto_uri VARCHAR, + IN in1_notify TEXT, IN in2_reserve_pub BYTEA, IN in2_wire_ref INT8, IN in2_credit_val INT8, IN in2_credit_frac INT4, IN in2_exchange_account_name VARCHAR, IN in2_execution_date INT8, - IN in2_wire_source_h_payto BYTEA, ---h_payto + IN in2_wire_source_h_payto BYTEA, IN in2_payto_uri VARCHAR, + IN in2_notify TEXT, IN in3_reserve_pub BYTEA, IN in3_wire_ref INT8, IN in3_credit_val INT8, IN in3_credit_frac INT4, IN in3_exchange_account_name VARCHAR, IN in3_execution_date INT8, - IN in3_wire_source_h_payto BYTEA, ---h_payto + IN in3_wire_source_h_payto BYTEA, IN in3_payto_uri VARCHAR, + IN in3_notify TEXT, IN in4_reserve_pub BYTEA, IN in4_wire_ref INT8, IN in4_credit_val INT8, IN in4_credit_frac INT4, IN in4_exchange_account_name VARCHAR, IN in4_execution_date INT8, - IN in4_wire_source_h_payto BYTEA, ---h_payto + IN in4_wire_source_h_payto BYTEA, IN in4_payto_uri VARCHAR, + IN in4_notify TEXT, IN in5_reserve_pub BYTEA, IN in5_wire_ref INT8, IN in5_credit_val INT8, IN in5_credit_frac INT4, IN in5_exchange_account_name VARCHAR, IN in5_execution_date INT8, - IN in5_wire_source_h_payto BYTEA, ---h_payto + IN in5_wire_source_h_payto BYTEA, IN in5_payto_uri VARCHAR, + IN in5_notify TEXT, IN in6_reserve_pub BYTEA, IN in6_wire_ref INT8, IN in6_credit_val INT8, IN in6_credit_frac INT4, IN in6_exchange_account_name VARCHAR, IN in6_execution_date INT8, - IN in6_wire_source_h_payto BYTEA, ---h_payto + IN in6_wire_source_h_payto BYTEA, IN in6_payto_uri VARCHAR, + IN in6_notify TEXT, IN in7_reserve_pub BYTEA, IN in7_wire_ref INT8, IN in7_credit_val INT8, IN in7_credit_frac INT4, IN in7_exchange_account_name VARCHAR, IN in7_execution_date INT8, - IN in7_wire_source_h_payto BYTEA, ---h_payto + IN in7_wire_source_h_payto BYTEA, IN in7_payto_uri VARCHAR, - IN in8_reserve_pub BYTEA, - IN in8_wire_ref INT8, - IN in8_credit_val INT8, - IN in8_credit_frac INT4, - IN in8_exchange_account_name VARCHAR, - IN in8_execution_date INT8, - IN in8_wire_source_h_payto BYTEA, ---h_payto - IN in8_payto_uri VARCHAR, - OUT out_reserve_found BOOLEAN, + IN in7_notify TEXT, + OUT out_reserve_found0 BOOLEAN, + OUT out_reserve_found1 BOOLEAN, OUT out_reserve_found2 BOOLEAN, OUT out_reserve_found3 BOOLEAN, OUT out_reserve_found4 BOOLEAN, OUT out_reserve_found5 BOOLEAN, OUT out_reserve_found6 BOOLEAN, OUT out_reserve_found7 BOOLEAN, - OUT out_reserve_found8 BOOLEAN, - OUT transaction_duplicate BOOLEAN, + OUT transaction_duplicate0 BOOLEAN, + OUT transaction_duplicate1 BOOLEAN, OUT transaction_duplicate2 BOOLEAN, OUT transaction_duplicate3 BOOLEAN, OUT transaction_duplicate4 BOOLEAN, OUT transaction_duplicate5 BOOLEAN, OUT transaction_duplicate6 BOOLEAN, OUT transaction_duplicate7 BOOLEAN, - OUT transaction_duplicate8 BOOLEAN, - OUT ruuid INT8, + OUT ruuid0 INT8, + OUT ruuid1 INT8, OUT ruuid2 INT8, OUT ruuid3 INT8, OUT ruuid4 INT8, OUT ruuid5 INT8, OUT ruuid6 INT8, - OUT ruuid7 INT8, - OUT ruuid8 INT8) + OUT ruuid7 INT8) LANGUAGE plpgsql AS $$ DECLARE - curs_reserve_existed refcursor; + curs_reserve_exist REFCURSOR; DECLARE k INT8; DECLARE - curs_transaction_existed refcursor; + curs_transaction_exist REFCURSOR; DECLARE i RECORD; DECLARE r RECORD; BEGIN ---INITIALIZATION - transaction_duplicate=TRUE; + transaction_duplicate0=TRUE; + transaction_duplicate1=TRUE; transaction_duplicate2=TRUE; transaction_duplicate3=TRUE; transaction_duplicate4=TRUE; transaction_duplicate5=TRUE; transaction_duplicate6=TRUE; transaction_duplicate7=TRUE; - transaction_duplicate8=TRUE; - out_reserve_found = TRUE; + out_reserve_found0 = TRUE; + out_reserve_found1 = TRUE; out_reserve_found2 = TRUE; out_reserve_found3 = TRUE; out_reserve_found4 = TRUE; out_reserve_found5 = TRUE; out_reserve_found6 = TRUE; out_reserve_found7 = TRUE; - out_reserve_found8 = TRUE; - ruuid=0; + ruuid0=0; + ruuid1=0; ruuid2=0; ruuid3=0; ruuid4=0; ruuid5=0; ruuid6=0; ruuid7=0; - ruuid8=0; - k=0; - --SIMPLE INSERT ON CONFLICT DO NOTHING INSERT INTO wire_targets (wire_target_h_payto ,payto_uri) VALUES - (in_wire_source_h_payto - ,in_payto_uri), + (in0_wire_source_h_payto + ,in0_payto_uri), + (in1_wire_source_h_payto + ,in1_payto_uri), (in2_wire_source_h_payto ,in2_payto_uri), (in3_wire_source_h_payto @@ -723,12 +733,10 @@ BEGIN (in6_wire_source_h_payto ,in6_payto_uri), (in7_wire_source_h_payto - ,in7_payto_uri), - (in8_wire_source_h_payto - ,in8_payto_uri) + ,in7_payto_uri) ON CONFLICT DO NOTHING; - OPEN curs_reserve_existed FOR + OPEN curs_reserve_exist FOR WITH reserve_changes AS ( INSERT INTO reserves (reserve_pub @@ -737,9 +745,14 @@ BEGIN ,expiration_date ,gc_date) VALUES - (in_reserve_pub - ,in_credit_val - ,in_credit_frac + (in0_reserve_pub + ,in0_credit_val + ,in0_credit_frac + ,in_reserve_expiration + ,in_gc_date), + (in1_reserve_pub + ,in1_credit_val + ,in1_credit_frac ,in_reserve_expiration ,in_gc_date), (in2_reserve_pub @@ -771,295 +784,269 @@ BEGIN ,in7_credit_val ,in7_credit_frac ,in_reserve_expiration - ,in_gc_date), - (in8_reserve_pub - ,in8_credit_val - ,in8_credit_frac - ,in_reserve_expiration ,in_gc_date) - ON CONFLICT DO NOTHING - RETURNING reserve_uuid,reserve_pub) - SELECT * FROM reserve_changes; - - WHILE k < 8 LOOP - - FETCH FROM curs_reserve_existed INTO i; - IF FOUND - THEN - IF in_reserve_pub = i.reserve_pub - THEN - ruuid = i.reserve_uuid; - IF in_reserve_pub - NOT IN (in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found = FALSE; - END IF; - END IF; - IF in2_reserve_pub = i.reserve_pub - THEN - ruuid2 = i.reserve_uuid; - IF in2_reserve_pub - NOT IN (in_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found2 = FALSE; - END IF; - END IF; - IF in3_reserve_pub = i.reserve_pub - THEN - ruuid3 = i.reserve_uuid; - IF in3_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found3 = FALSE; - END IF; - END IF; - IF in4_reserve_pub = i.reserve_pub - THEN - ruuid4 = i.reserve_uuid; - IF in4_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found4 = FALSE; - END IF; - END IF; - IF in5_reserve_pub = i.reserve_pub - THEN - ruuid5 = i.reserve_uuid; - IF in5_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found5 = FALSE; - END IF; - END IF; - IF in6_reserve_pub = i.reserve_pub - THEN - ruuid6 = i.reserve_uuid; - IF in6_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in7_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found6 = FALSE; - END IF; - END IF; - IF in7_reserve_pub = i.reserve_pub - THEN - ruuid7 = i.reserve_uuid; - IF in7_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in8_reserve_pub) - THEN - out_reserve_found7 = FALSE; - END IF; - END IF; - IF in8_reserve_pub = i.reserve_pub - THEN - ruuid8 = i.reserve_uuid; - IF in8_reserve_pub - NOT IN (in_reserve_pub - ,in2_reserve_pub - ,in3_reserve_pub - ,in4_reserve_pub - ,in5_reserve_pub - ,in6_reserve_pub - ,in7_reserve_pub) - THEN - out_reserve_found8 = FALSE; - END IF; - END IF; - END IF; - k=k+1; - END LOOP; - - CLOSE curs_reserve_existed; + ON CONFLICT DO NOTHING + RETURNING reserve_uuid,reserve_pub) + SELECT reserve_uuid, reserve_pub FROM reserve_changes; k=0; - OPEN curs_transaction_existed FOR - WITH reserve_in_changes AS ( - INSERT INTO reserves_in - (reserve_pub - ,wire_reference - ,credit_val - ,credit_frac - ,exchange_account_section - ,wire_source_h_payto - ,execution_date) - VALUES - (in_reserve_pub - ,in_wire_ref - ,in_credit_val - ,in_credit_frac - ,in_exchange_account_name - ,in_wire_source_h_payto - ,in_execution_date), - (in2_reserve_pub - ,in2_wire_ref - ,in2_credit_val - ,in2_credit_frac - ,in2_exchange_account_name - ,in2_wire_source_h_payto - ,in2_execution_date), - (in3_reserve_pub - ,in3_wire_ref - ,in3_credit_val - ,in3_credit_frac - ,in3_exchange_account_name - ,in3_wire_source_h_payto - ,in3_execution_date), - (in4_reserve_pub - ,in4_wire_ref - ,in4_credit_val - ,in4_credit_frac - ,in4_exchange_account_name - ,in4_wire_source_h_payto - ,in4_execution_date), - (in5_reserve_pub - ,in5_wire_ref - ,in5_credit_val - ,in5_credit_frac - ,in5_exchange_account_name - ,in5_wire_source_h_payto - ,in5_execution_date), - (in6_reserve_pub - ,in6_wire_ref - ,in6_credit_val - ,in6_credit_frac - ,in6_exchange_account_name - ,in6_wire_source_h_payto - ,in6_execution_date), - (in7_reserve_pub - ,in7_wire_ref - ,in7_credit_val - ,in7_credit_frac - ,in7_exchange_account_name - ,in7_wire_source_h_payto - ,in7_execution_date), - (in8_reserve_pub - ,in8_wire_ref - ,in8_credit_val - ,in8_credit_frac - ,in8_exchange_account_name - ,in8_wire_source_h_payto - ,in8_execution_date) - ON CONFLICT DO NOTHING - RETURNING reserve_pub) - SELECT * FROM reserve_in_changes; - - WHILE k < 8 LOOP - FETCH FROM curs_transaction_existed INTO r; - IF FOUND + <> LOOP + FETCH FROM curs_reserve_exist INTO i; + IF NOT FOUND THEN - IF in_reserve_pub = r.reserve_pub - THEN - transaction_duplicate = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in_notify); - END IF; - IF in2_reserve_pub = r.reserve_pub - THEN - transaction_duplicate2 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in2_notify); - END IF; - IF in3_reserve_pub = r.reserve_pub - THEN - transaction_duplicate3 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in3_notify); - END IF; - IF in4_reserve_pub = r.reserve_pub - THEN - transaction_duplicate4 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in4_notify); - END IF; - IF in5_reserve_pub = r.reserve_pub - THEN - transaction_duplicate5 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in5_notify); - END IF; - IF in6_reserve_pub = r.reserve_pub - THEN - transaction_duplicate6 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in6_notify); - END IF; - IF in7_reserve_pub = r.reserve_pub - THEN - transaction_duplicate7 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in7_notify); - END IF; - IF in8_reserve_pub = r.reserve_pub - THEN - transaction_duplicate8 = FALSE; - EXECUTE FORMAT ( - 'NOTIFY %s' - ,in8_notify); - END IF; + EXIT loop_reserve; END IF; - k=k+1; - END LOOP; - /* IF transaction_duplicate - OR transaction_duplicate2 - OR transaction_duplicate3 - OR transaction_duplicate4 - OR transaction_duplicate5 - OR transaction_duplicate6 - OR transaction_duplicate7 - OR transaction_duplicate8 - THEN - CLOSE curs_transaction_existed; - ROLLBACK; - RETURN; - END IF;*/ - CLOSE curs_transaction_existed; + + <> LOOP + CASE k + WHEN 0 THEN + k = k + 1; + IF in0_reserve_pub = i.reserve_pub + THEN + ruuid0 = i.reserve_uuid; + out_reserve_found0 = FALSE; + CONTINUE loop_reserve; + END IF; + CONTINUE loop_k; + WHEN 1 THEN + k = k + 1; + IF in1_reserve_pub = i.reserve_pub + THEN + ruuid1 = i.reserve_uuid; + out_reserve_found1 = FALSE; + CONTINUE loop_reserve; + END IF; + CONTINUE loop_k; + WHEN 2 THEN + k = k + 1; + IF in2_reserve_pub = i.reserve_pub + THEN + ruuid2 = i.reserve_uuid; + out_reserve_found2 = FALSE; + CONTINUE loop_reserve; + END IF; + CONTINUE loop_k; + WHEN 3 THEN + k = k + 1; + IF in3_reserve_pub = i.reserve_pub + THEN + ruuid3 = i.reserve_uuid; + out_reserve_found3 = FALSE; + CONTINUE loop_reserve; + END IF; + CONTINUE loop_k; + WHEN 4 THEN + k = k + 1; + IF in4_reserve_pub = i.reserve_pub + THEN + ruuid4 = i.reserve_uuid; + out_reserve_found4 = FALSE; + CONTINUE loop_reserve; + END IF; + CONTINUE loop_k; + WHEN 5 THEN + k = k + 1; + IF in5_reserve_pub = i.reserve_pub + THEN + ruuid5 = i.reserve_uuid; + out_reserve_found5 = FALSE; + CONTINUE loop_reserve; + END IF; + CONTINUE loop_k; + WHEN 6 THEN + k = k + 1; + IF in6_reserve_pub = i.reserve_pub + THEN + ruuid6 = i.reserve_uuid; + out_reserve_found6 = FALSE; + CONTINUE loop_reserve; + END IF; + CONTINUE loop_k; + WHEN 7 THEN + IF in7_reserve_pub = i.reserve_pub + THEN + ruuid7 = i.reserve_uuid; + out_reserve_found7 = FALSE; + EXIT loop_reserve; + END IF; + EXIT loop_k; + END CASE; + END LOOP loop_k; + END LOOP loop_reserve; + + CLOSE curs_reserve_exist; + + OPEN curs_transaction_exist FOR + WITH reserve_changes AS ( + INSERT INTO reserves_in + (reserve_pub + ,wire_reference + ,credit_val + ,credit_frac + ,exchange_account_section + ,wire_source_h_payto + ,execution_date) + VALUES + (in0_reserve_pub + ,in0_wire_ref + ,in0_credit_val + ,in0_credit_frac + ,in0_exchange_account_name + ,in0_wire_source_h_payto + ,in0_execution_date), + (in1_reserve_pub + ,in1_wire_ref + ,in1_credit_val + ,in1_credit_frac + ,in1_exchange_account_name + ,in1_wire_source_h_payto + ,in1_execution_date), + (in2_reserve_pub + ,in2_wire_ref + ,in2_credit_val + ,in2_credit_frac + ,in2_exchange_account_name + ,in2_wire_source_h_payto + ,in2_execution_date), + (in3_reserve_pub + ,in3_wire_ref + ,in3_credit_val + ,in3_credit_frac + ,in3_exchange_account_name + ,in3_wire_source_h_payto + ,in3_execution_date), + (in4_reserve_pub + ,in4_wire_ref + ,in4_credit_val + ,in4_credit_frac + ,in4_exchange_account_name + ,in4_wire_source_h_payto + ,in4_execution_date), + (in5_reserve_pub + ,in5_wire_ref + ,in5_credit_val + ,in5_credit_frac + ,in5_exchange_account_name + ,in5_wire_source_h_payto + ,in5_execution_date), + (in6_reserve_pub + ,in6_wire_ref + ,in6_credit_val + ,in6_credit_frac + ,in6_exchange_account_name + ,in6_wire_source_h_payto + ,in6_execution_date), + (in7_reserve_pub + ,in7_wire_ref + ,in7_credit_val + ,in7_credit_frac + ,in7_exchange_account_name + ,in7_wire_source_h_payto + ,in7_execution_date) + ON CONFLICT DO NOTHING + RETURNING reserve_pub) + SELECT reserve_pub FROM reserve_changes; + + k=0; + <> LOOP + FETCH FROM curs_transaction_exist INTO i; + IF NOT FOUND + THEN + EXIT loop_transaction; + END IF; + + <> LOOP + CASE k + WHEN 0 THEN + k = k + 1; + IF in0_reserve_pub = r.reserve_pub + THEN + transaction_duplicate0 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in0_notify); + CONTINUE loop_transaction; + END IF; + CONTINUE loop2_k; + WHEN 1 THEN + k = k + 1; + IF in1_reserve_pub = r.reserve_pub + THEN + transaction_duplicate1 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in1_notify); + CONTINUE loop_transaction; + END IF; + CONTINUE loop2_k; + WHEN 2 THEN + k = k + 1; + IF in2_reserve_pub = r.reserve_pub + THEN + transaction_duplicate2 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in2_notify); + CONTINUE loop_transaction; + END IF; + CONTINUE loop2_k; + WHEN 3 THEN + k = k + 1; + IF in3_reserve_pub = r.reserve_pub + THEN + transaction_duplicate3 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in3_notify); + CONTINUE loop_transaction; + END IF; + CONTINUE loop2_k; + WHEN 4 THEN + k = k + 1; + IF in4_reserve_pub = r.reserve_pub + THEN + transaction_duplicate4 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in4_notify); + CONTINUE loop_transaction; + END IF; + CONTINUE loop2_k; + WHEN 5 THEN + k = k + 1; + IF in5_reserve_pub = r.reserve_pub + THEN + transaction_duplicate2 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in5_notify); + CONTINUE loop_transaction; + END IF; + CONTINUE loop2_k; + WHEN 6 THEN + k = k + 1; + IF in6_reserve_pub = r.reserve_pub + THEN + transaction_duplicate6 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in6_notify); + CONTINUE loop_transaction; + END IF; + CONTINUE loop2_k; + WHEN 7 THEN + IF in7_reserve_pub = r.reserve_pub + THEN + transaction_duplicate7 = FALSE; + EXECUTE FORMAT ( + 'NOTIFY %s' + ,in7_notify); + EXIT loop_transaction; + END IF; + END CASE; + END LOOP loop2_k; + END LOOP loop_transaction; + + CLOSE curs_transaction_exist; RETURN; END $$; diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c index 876774de9..2e29a1857 100644 --- a/src/exchangedb/pg_reserves_in_insert.c +++ b/src/exchangedb/pg_reserves_in_insert.c @@ -55,53 +55,107 @@ compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub) } +/** + * Record we keep per reserve to process. + */ +struct ReserveRecord +{ + /** + * Details about reserve to insert (input). + */ + const struct TALER_EXCHANGEDB_ReserveInInfo *reserve; + + /** + * Hash of the payto URI in @e reserve. + */ + struct TALER_PaytoHashP h_payto; + + /** + * Notification to trigger on the reserve (input). + */ + char *notify_s; + + /** + * Set to UUID of the reserve (output); + */ + uint64_t reserve_uuid; + + /** + * Set to true if the transaction was an exact duplicate (output). + */ + bool transaction_duplicate; + + /** + * Set to true if the transaction conflicted with an existing reserve (output) + * and needs to be re-done with an UPDATE. + */ + bool conflicts; +}; + + +/** + * Generate the SQL parameters to insert the record @a rr at + * index @a index + */ +#define RR_QUERY_PARAM(rr,index) \ + GNUNET_PQ_query_param_auto_from_type (rr[index].reserve->reserve_pub), \ + GNUNET_PQ_query_param_uint64 (&rr[index].reserve->wire_reference), \ + TALER_PQ_query_param_amount (rr[index].reserve->balance), \ + GNUNET_PQ_query_param_string (rr[index].reserve->exchange_account_name), \ + GNUNET_PQ_query_param_timestamp (&rr[index].reserve->execution_time), \ + GNUNET_PQ_query_param_auto_from_type (&rr[index].h_payto), \ + GNUNET_PQ_query_param_string (rr[index].reserve->sender_account_details), \ + GNUNET_PQ_query_param_string (rr[index].notify_s) + + +/** + * Generate the SQL parameters to obtain results for record @a rr at + * index @a index + */ +#define RR_RESULT_PARAM(rr,index) \ + GNUNET_PQ_result_spec_bool ("conflicted" TALER_S (index), \ + &rr[index].conflicts), \ + GNUNET_PQ_result_spec_bool ("transaction_duplicate" TALER_S (index), \ + &rr[index].transaction_duplicate), \ + GNUNET_PQ_result_spec_uint64 ("reserve_uuid" TALER_S (index), \ + &rr[index].reserve_uuid) + + +/** + * Insert 1 reserve record @a rr into the database. + * + * @param pg database context + * @param gc gc timestamp to use + * @param reserve_expiration expiration time to use + * @param[in,out] rr array of reserve details to use and update + * @return database transaction status + */ static enum GNUNET_DB_QueryStatus insert1 (struct PostgresClosure *pg, - const struct TALER_EXCHANGEDB_ReserveInInfo reserves[1], struct GNUNET_TIME_Timestamp gc, - char *const *notify_s, struct GNUNET_TIME_Timestamp reserve_expiration, - bool *transaction_duplicate, - bool *conflict, - uint64_t *reserve_uuid) + struct ReserveRecord *rr) { enum GNUNET_DB_QueryStatus qs; - struct TALER_PaytoHashP h_payto0; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_timestamp (&gc), GNUNET_PQ_query_param_timestamp (&reserve_expiration), - - GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), - TALER_PQ_query_param_amount (reserves[0].balance), - GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto0), - GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - - GNUNET_PQ_query_param_string (notify_s[0]), + RR_QUERY_PARAM (rr, 0), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("conflicted", - &conflict[0]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate", - &transaction_duplicate[0]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid", - &reserve_uuid[0]), + RR_RESULT_PARAM (rr, 0), GNUNET_PQ_result_spec_end }; PREPARE (pg, "batch1_reserve_create", "SELECT " - " out_reserve_found AS conflicted" - ",transaction_duplicate" - ",ruuid AS reserve_uuid" + " out_reserve_found0 AS conflicted0" + ",transaction_duplicate0 AS transaction_duplicate0" + ",ruuid0 AS reserve_uuid0" " FROM exchange_do_batch_reserves_in_insert" " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);"); - TALER_payto_hash (reserves[0].sender_account_details, - &h_payto0); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "batch1_reserve_create", params, @@ -114,7 +168,7 @@ insert1 (struct PostgresClosure *pg, return qs; } GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs); - if ((! conflict[0]) && transaction_duplicate[0]) + if ((! rr[0].conflicts) && rr[0].transaction_duplicate) { GNUNET_break (0); TEH_PG_rollback (pg); @@ -124,438 +178,418 @@ insert1 (struct PostgresClosure *pg, } +/** + * Insert 2 reserve records @a rr into the database. + * + * @param pg database context + * @param gc gc timestamp to use + * @param reserve_expiration expiration time to use + * @param[in,out] rr array of reserve details to use and update + * @return database transaction status + */ static enum GNUNET_DB_QueryStatus insert2 (struct PostgresClosure *pg, - const struct TALER_EXCHANGEDB_ReserveInInfo reserves[2], struct GNUNET_TIME_Timestamp gc, - char *const*notify_s, struct GNUNET_TIME_Timestamp reserve_expiration, - bool *transaction_duplicate, - bool *conflict, - uint64_t *reserve_uuid) + struct ReserveRecord *rr) { - enum GNUNET_DB_QueryStatus qs1; - struct TALER_PaytoHashP h_payto[2]; + enum GNUNET_DB_QueryStatus qs; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_timestamp (&gc), GNUNET_PQ_query_param_timestamp (&reserve_expiration), - - GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), - TALER_PQ_query_param_amount (reserves[0].balance), - GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[0]), - GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - - GNUNET_PQ_query_param_string (notify_s[0]), - GNUNET_PQ_query_param_string (notify_s[1]), - - GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference), - TALER_PQ_query_param_amount (reserves[1].balance), - GNUNET_PQ_query_param_string (reserves[1].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[1]), - GNUNET_PQ_query_param_string (reserves[1].sender_account_details), + RR_QUERY_PARAM (rr, 0), + RR_QUERY_PARAM (rr, 1), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("conflicted", - &conflict[0]), - GNUNET_PQ_result_spec_bool ("conflicted2", - &conflict[1]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate", - &transaction_duplicate[0]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate2", - &transaction_duplicate[1]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid", - &reserve_uuid[0]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid2", - &reserve_uuid[1]), + RR_RESULT_PARAM (rr, 0), + RR_RESULT_PARAM (rr, 1), GNUNET_PQ_result_spec_end }; PREPARE (pg, "batch2_reserve_create", - "SELECT " - "out_reserve_found AS conflicted" - ",out_reserve_found2 AS conflicted2" - ",transaction_duplicate" - ",transaction_duplicate2" - ",ruuid AS reserve_uuid" - ",ruuid2 AS reserve_uuid2" + "SELECT" + " out_reserve_found0 AS conflicted0" + ",out_reserve_found1 AS conflicted1" + ",transaction_duplicate0" + ",transaction_duplicate1" + ",ruuid0 AS reserve_uuid0" + ",ruuid1 AS reserve_uuid1" " FROM exchange_do_batch2_reserves_insert" " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20);"); - TALER_payto_hash (reserves[0].sender_account_details, - &h_payto[0]); - TALER_payto_hash (reserves[1].sender_account_details, - &h_payto[1]); - qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "batch2_reserve_create", - params, - rs); - if (qs1 < 0) + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "batch2_reserve_create", + params, + rs); + if (qs < 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to create reserves 2(%d)\n", - qs1); - return qs1; + qs); + return qs; } - - GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1); - if ( ((! conflict[0]) && (transaction_duplicate[0])) || - ((! conflict[1]) && (transaction_duplicate[1])) ) + GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs); + for (unsigned int i = 0; i<2; i++) { - GNUNET_break (0); - TEH_PG_rollback (pg); - return GNUNET_DB_STATUS_HARD_ERROR; + if ((! rr[i].conflicts) && (rr[i].transaction_duplicate)) + { + GNUNET_break (0); + TEH_PG_rollback (pg); + return GNUNET_DB_STATUS_HARD_ERROR; + } } - return qs1; + return qs; } +/** + * Insert 4 reserve records @a rr into the database. + * + * @param pg database context + * @param gc gc timestamp to use + * @param reserve_expiration expiration time to use + * @param[in,out] rr array of reserve details to use and update + * @return database transaction status + */ static enum GNUNET_DB_QueryStatus insert4 (struct PostgresClosure *pg, - const struct TALER_EXCHANGEDB_ReserveInInfo reserves[4], struct GNUNET_TIME_Timestamp gc, - char *const*notify_s, struct GNUNET_TIME_Timestamp reserve_expiration, - bool *transaction_duplicate, - bool *conflict, - uint64_t *reserve_uuid) + struct ReserveRecord *rr) { - enum GNUNET_DB_QueryStatus qs3; - struct TALER_PaytoHashP h_payto[4]; + enum GNUNET_DB_QueryStatus qs; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_timestamp (&gc), GNUNET_PQ_query_param_timestamp (&reserve_expiration), - - GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), - TALER_PQ_query_param_amount (reserves[0].balance), - GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[0]), - GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - - GNUNET_PQ_query_param_string (notify_s[0]), - GNUNET_PQ_query_param_string (notify_s[1]), - GNUNET_PQ_query_param_string (notify_s[2]), - GNUNET_PQ_query_param_string (notify_s[3]), - - GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference), - TALER_PQ_query_param_amount (reserves[1].balance), - GNUNET_PQ_query_param_string (reserves[1].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[1]), - GNUNET_PQ_query_param_string (reserves[1].sender_account_details), - - GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference), - TALER_PQ_query_param_amount (reserves[2].balance), - GNUNET_PQ_query_param_string (reserves[2].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[2]), - GNUNET_PQ_query_param_string (reserves[2].sender_account_details), - - GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference), - TALER_PQ_query_param_amount (reserves[3].balance), - GNUNET_PQ_query_param_string (reserves[3].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[3]), - GNUNET_PQ_query_param_string (reserves[3].sender_account_details), - + RR_QUERY_PARAM (rr, 0), + RR_QUERY_PARAM (rr, 1), + RR_QUERY_PARAM (rr, 2), + RR_QUERY_PARAM (rr, 3), GNUNET_PQ_query_param_end }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("conflicted", - &conflict[0]), - GNUNET_PQ_result_spec_bool ("conflicted2", - &conflict[1]), - GNUNET_PQ_result_spec_bool ("conflicted3", - &conflict[2]), - GNUNET_PQ_result_spec_bool ("conflicted4", - &conflict[3]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate", - &transaction_duplicate[0]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate2", - &transaction_duplicate[1]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate3", - &transaction_duplicate[2]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate4", - &transaction_duplicate[3]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid", - &reserve_uuid[0]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid2", - &reserve_uuid[1]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid3", - &reserve_uuid[2]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid4", - &reserve_uuid[3]), + RR_RESULT_PARAM (rr, 0), + RR_RESULT_PARAM (rr, 1), + RR_RESULT_PARAM (rr, 2), + RR_RESULT_PARAM (rr, 3), GNUNET_PQ_result_spec_end }; PREPARE (pg, "batch4_reserve_create", - "SELECT " - "out_reserve_found AS conflicted" + "SELECT" + " out_reserve_found0 AS conflicted0" + ",out_reserve_found1 AS conflicted1" ",out_reserve_found2 AS conflicted2" ",out_reserve_found3 AS conflicted3" - ",out_reserve_found4 AS conflicted4" - ",transaction_duplicate" + ",transaction_duplicate0" + ",transaction_duplicate1" ",transaction_duplicate2" ",transaction_duplicate3" - ",transaction_duplicate4" - ",ruuid AS reserve_uuid" + ",ruuid0 AS reserve_uuid0" + ",ruuid1 AS reserve_uuid1" ",ruuid2 AS reserve_uuid2" ",ruuid3 AS reserve_uuid3" - ",ruuid4 AS reserve_uuid4" " FROM exchange_do_batch4_reserves_insert" " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38);"); - - for (unsigned int i = 0; i<4; i++) - TALER_payto_hash (reserves[i].sender_account_details, - &h_payto[i]); - qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "batch4_reserve_create", - params, - rs); - if (qs3 < 0) + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "batch4_reserve_create", + params, + rs); + if (qs < 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to create reserves4 (%d)\n", - qs3); - return qs3; + qs); + return qs; } - GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3); - - if ( - ((! conflict[0]) && (transaction_duplicate[0])) - || ((! conflict[1]) && (transaction_duplicate[1])) - || ((! conflict[2]) && (transaction_duplicate[2])) - || ((! conflict[3]) && (transaction_duplicate[3])) - ) + GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs); + for (unsigned int i = 0; i<4; i++) { - GNUNET_break (0); - TEH_PG_rollback (pg); - return GNUNET_DB_STATUS_HARD_ERROR; + if ((! rr[i].conflicts) && (rr[i].transaction_duplicate)) + { + GNUNET_break (0); + TEH_PG_rollback (pg); + return GNUNET_DB_STATUS_HARD_ERROR; + } } - return qs3; + return qs; } +/** + * Insert 8 reserve records @a rr into the database. + * + * @param pg database context + * @param gc gc timestamp to use + * @param reserve_expiration expiration time to use + * @param[in,out] rr array of reserve details to use and update + * @return database transaction status + */ static enum GNUNET_DB_QueryStatus insert8 (struct PostgresClosure *pg, - const struct TALER_EXCHANGEDB_ReserveInInfo reserves[8], struct GNUNET_TIME_Timestamp gc, - char *const*notify_s, struct GNUNET_TIME_Timestamp reserve_expiration, - bool *transaction_duplicate, - bool *conflict, - uint64_t *reserve_uuid) + struct ReserveRecord *rr) { - enum GNUNET_DB_QueryStatus qs3; - struct TALER_PaytoHashP h_payto[8]; + enum GNUNET_DB_QueryStatus qs; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_timestamp (&gc), GNUNET_PQ_query_param_timestamp (&reserve_expiration), - - GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), - TALER_PQ_query_param_amount (reserves[0].balance), - GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[0]), - GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - - GNUNET_PQ_query_param_string (notify_s[0]), - GNUNET_PQ_query_param_string (notify_s[1]), - GNUNET_PQ_query_param_string (notify_s[2]), - GNUNET_PQ_query_param_string (notify_s[3]), - GNUNET_PQ_query_param_string (notify_s[4]), - GNUNET_PQ_query_param_string (notify_s[5]), - GNUNET_PQ_query_param_string (notify_s[6]), - GNUNET_PQ_query_param_string (notify_s[7]), - - GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference), - TALER_PQ_query_param_amount (reserves[1].balance), - GNUNET_PQ_query_param_string (reserves[1].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[1]), - GNUNET_PQ_query_param_string (reserves[1].sender_account_details), - - GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference), - TALER_PQ_query_param_amount (reserves[2].balance), - GNUNET_PQ_query_param_string (reserves[2].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[2]), - GNUNET_PQ_query_param_string (reserves[2].sender_account_details), - - GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference), - TALER_PQ_query_param_amount (reserves[3].balance), - GNUNET_PQ_query_param_string (reserves[3].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[3]), - GNUNET_PQ_query_param_string (reserves[3].sender_account_details), - - GNUNET_PQ_query_param_auto_from_type (reserves[4].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[4].wire_reference), - TALER_PQ_query_param_amount (reserves[4].balance), - GNUNET_PQ_query_param_string (reserves[4].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[4].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[4]), - GNUNET_PQ_query_param_string (reserves[4].sender_account_details), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), - - GNUNET_PQ_query_param_auto_from_type (reserves[5].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[5].wire_reference), - TALER_PQ_query_param_amount (reserves[5].balance), - GNUNET_PQ_query_param_string (reserves[5].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[5].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[5]), - GNUNET_PQ_query_param_string (reserves[5].sender_account_details), - - GNUNET_PQ_query_param_auto_from_type (reserves[6].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[6].wire_reference), - TALER_PQ_query_param_amount (reserves[6].balance), - GNUNET_PQ_query_param_string (reserves[6].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[6].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[6]), - GNUNET_PQ_query_param_string (reserves[6].sender_account_details), - - GNUNET_PQ_query_param_auto_from_type (reserves[7].reserve_pub), - GNUNET_PQ_query_param_uint64 (&reserves[7].wire_reference), - TALER_PQ_query_param_amount (reserves[7].balance), - GNUNET_PQ_query_param_string (reserves[7].exchange_account_name), - GNUNET_PQ_query_param_timestamp (&reserves[7].execution_time), - GNUNET_PQ_query_param_auto_from_type (&h_payto[7]), - GNUNET_PQ_query_param_string (reserves[7].sender_account_details), - + RR_QUERY_PARAM (rr, 0), + RR_QUERY_PARAM (rr, 1), + RR_QUERY_PARAM (rr, 2), + RR_QUERY_PARAM (rr, 3), + RR_QUERY_PARAM (rr, 4), + RR_QUERY_PARAM (rr, 5), + RR_QUERY_PARAM (rr, 6), + RR_QUERY_PARAM (rr, 7), GNUNET_PQ_query_param_end }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("conflicted", - &conflict[0]), - GNUNET_PQ_result_spec_bool ("conflicted2", - &conflict[1]), - GNUNET_PQ_result_spec_bool ("conflicted3", - &conflict[2]), - GNUNET_PQ_result_spec_bool ("conflicted4", - &conflict[3]), - GNUNET_PQ_result_spec_bool ("conflicted5", - &conflict[4]), - GNUNET_PQ_result_spec_bool ("conflicted6", - &conflict[5]), - GNUNET_PQ_result_spec_bool ("conflicted7", - &conflict[6]), - GNUNET_PQ_result_spec_bool ("conflicted8", - &conflict[7]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate", - &transaction_duplicate[0]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate2", - &transaction_duplicate[1]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate3", - &transaction_duplicate[2]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate4", - &transaction_duplicate[3]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate5", - &transaction_duplicate[4]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate6", - &transaction_duplicate[5]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate7", - &transaction_duplicate[6]), - GNUNET_PQ_result_spec_bool ("transaction_duplicate8", - &transaction_duplicate[7]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid", - &reserve_uuid[0]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid2", - &reserve_uuid[1]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid3", - &reserve_uuid[2]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid4", - &reserve_uuid[3]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid5", - &reserve_uuid[4]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid6", - &reserve_uuid[5]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid7", - &reserve_uuid[6]), - GNUNET_PQ_result_spec_uint64 ("reserve_uuid8", - &reserve_uuid[7]), + RR_RESULT_PARAM (rr, 0), + RR_RESULT_PARAM (rr, 1), + RR_RESULT_PARAM (rr, 2), + RR_RESULT_PARAM (rr, 3), + RR_RESULT_PARAM (rr, 4), + RR_RESULT_PARAM (rr, 5), + RR_RESULT_PARAM (rr, 6), + RR_RESULT_PARAM (rr, 7), GNUNET_PQ_result_spec_end }; PREPARE (pg, "batch8_reserve_create", "SELECT" - " out_reserve_found AS conflicted" + " out_reserve_found0 AS conflicted0" + ",out_reserve_found1 AS conflicted1" ",out_reserve_found2 AS conflicted2" ",out_reserve_found3 AS conflicted3" ",out_reserve_found4 AS conflicted4" ",out_reserve_found5 AS conflicted5" ",out_reserve_found6 AS conflicted6" ",out_reserve_found7 AS conflicted7" - ",out_reserve_found8 AS conflicted8" - ",transaction_duplicate" + ",transaction_duplicate0" + ",transaction_duplicate1" ",transaction_duplicate2" ",transaction_duplicate3" ",transaction_duplicate4" ",transaction_duplicate5" ",transaction_duplicate6" ",transaction_duplicate7" - ",transaction_duplicate8" - ",ruuid AS reserve_uuid" + ",ruuid0 AS reserve_uuid0" + ",ruuid1 AS reserve_uuid1" ",ruuid2 AS reserve_uuid2" ",ruuid3 AS reserve_uuid3" ",ruuid4 AS reserve_uuid4" ",ruuid5 AS reserve_uuid5" ",ruuid6 AS reserve_uuid6" ",ruuid7 AS reserve_uuid7" - ",ruuid8 AS reserve_uuid8" " FROM exchange_do_batch8_reserves_insert" " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39, $40, $41,$42,$43,$44,$45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$70,$71,$72,$73,$74);"); - for (unsigned int i = 0; i<8; i++) - TALER_payto_hash (reserves[i].sender_account_details, - &h_payto[i]); - qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "batch8_reserve_create", - params, - rs); - if (qs3 < 0) + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "batch8_reserve_create", + params, + rs); + if (qs < 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to create reserves8 (%d)\n", - qs3); - return qs3; + qs); + return qs; } - GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3); - if ( - ((! conflict[0]) && (transaction_duplicate[0])) - || ((! conflict[1]) && (transaction_duplicate[1])) - || ((! conflict[2]) && (transaction_duplicate[2])) - || ((! conflict[3]) && (transaction_duplicate[3])) - || ((! conflict[4]) && (transaction_duplicate[4])) - || ((! conflict[5]) && (transaction_duplicate[5])) - || ((! conflict[6]) && (transaction_duplicate[6])) - || ((! conflict[7]) && (transaction_duplicate[7])) - ) + GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs); + for (unsigned int i = 0; i<8; i++) + { + if ((! rr[i].conflicts) && (rr[i].transaction_duplicate)) + { + GNUNET_break (0); + TEH_PG_rollback (pg); + return GNUNET_DB_STATUS_HARD_ERROR; + } + } + return qs; +} + + +static enum GNUNET_DB_QueryStatus +transact ( + struct PostgresClosure *pg, + struct ReserveRecord *rr, + unsigned int reserves_length, + unsigned int batch_size, + enum GNUNET_DB_QueryStatus *results) +{ + 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 need_update = false; + + if (GNUNET_OK != + TEH_PG_preflight (pg)) { GNUNET_break (0); - TEH_PG_rollback (pg); return GNUNET_DB_STATUS_HARD_ERROR; } - return qs3; + + if (GNUNET_OK != + TEH_PG_start_read_committed (pg, + "READ_COMMITED")) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + + { + unsigned int i = 0; + + while (i < reserves_length) + { + enum GNUNET_DB_QueryStatus qs; + enum GNUNET_DB_QueryStatus + (*fun)(struct PostgresClosure *pg, + struct GNUNET_TIME_Timestamp gc, + struct GNUNET_TIME_Timestamp reserve_expiration, + struct ReserveRecord *rr); + unsigned int lim; + unsigned int bs; + + bs = GNUNET_MIN (batch_size, + reserves_length - i); + switch (bs) + { + case 7: + case 6: + case 5: + case 4: + fun = &insert4; + lim = 4; + break; + case 3: + case 2: + fun = &insert2; + lim = 2; + break; + case 1: + fun = &insert1; + lim = 1; + break; + case 0: + GNUNET_assert (0); + break; + default: + fun = insert8; + lim = 8; + break; + } + + qs = fun (pg, + gc, + reserve_expiration, + &rr[i]); + if (qs < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to create reserve batch_%u (%d)\n", + lim, + qs); + results[i] = qs; + return qs; + } + for (unsigned int j = 0; jreserve_pub), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_uint64 (&rr[i].reserve->wire_reference), + TALER_PQ_query_param_amount (rr[i].reserve->balance), + GNUNET_PQ_query_param_string (rr[i].reserve->exchange_account_name), + GNUNET_PQ_query_param_auto_from_type (&rr[i].h_payto), + GNUNET_PQ_query_param_string (rr[i].notify_s), + 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; + return qs; + } + results[i] = duplicate + ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + } + + { + enum GNUNET_DB_QueryStatus cs = TEH_PG_commit (pg); + + if (0 > cs) + return cs; + } + return reserves_length; } @@ -568,271 +602,31 @@ TEH_PG_reserves_in_insert ( enum GNUNET_DB_QueryStatus *results) { struct PostgresClosure *pg = cls; - enum GNUNET_DB_QueryStatus qs1; - enum GNUNET_DB_QueryStatus qs2; - enum GNUNET_DB_QueryStatus qs4; - enum GNUNET_DB_QueryStatus qs5; - uint64_t reserve_uuid[reserves_length]; - bool transaction_duplicate[reserves_length]; - bool need_update = false; - 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 conflicts[reserves_length]; - char *notify_s[reserves_length]; + struct ReserveRecord rrs[reserves_length]; + enum GNUNET_DB_QueryStatus qs; - if (GNUNET_OK != - TEH_PG_preflight (pg)) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating reserve %s with expiration in %s\n", - TALER_B2S (&(reserves->reserve_pub)), - GNUNET_STRINGS_relative_time_to_string ( - pg->idle_reserve_expiration_time, - GNUNET_NO)); - - if (GNUNET_OK != - TEH_PG_start_read_committed (pg, - "READ_COMMITED")) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - - /* Optimistically assume this is a new reserve, create balance for the first - time; we do this before adding the actual transaction to "reserves_in", - as for a new reserve it can't be a duplicate 'add' operation, and as - the 'add' operation needs the reserve entry as a foreign key. */ for (unsigned int i = 0; ireserve_pub); + rr->reserve = reserve; + TALER_payto_hash (reserves->sender_account_details, + &rr->h_payto); + rr->notify_s = compute_notify_on_reserve (reserve->reserve_pub); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Creating reserve %s with expiration in %s\n", + TALER_B2S (&reserve->reserve_pub), + GNUNET_STRINGS_relative_time_to_string ( + pg->idle_reserve_expiration_time, + false)); } - - unsigned int i = 0; - - while (i < reserves_length) - { - unsigned int bs = GNUNET_MIN (batch_size, - reserves_length - i); - if (bs >= 8) - { - qs1 = insert8 (pg, - &reserves[i], - gc, - ¬ify_s[i], - reserve_expiration, - &transaction_duplicate[i], - &conflicts[i], - &reserve_uuid[i]); - - if (qs1<0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to create reserve batch_8 (%d)\n", - qs1); - results[i] = qs1; - return qs1; - } - need_update |= conflicts[i]; - need_update |= conflicts[i + 1]; - need_update |= conflicts[i + 2]; - need_update |= conflicts[i + 3]; - need_update |= conflicts[i + 4]; - need_update |= conflicts[i + 5]; - need_update |= conflicts[i + 6]; - need_update |= conflicts[i + 7]; - for (unsigned int j = 0; j<8; j++) - results[i + j] = transaction_duplicate[i + j] - ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - i += 8; - continue; - } - switch (bs) - { - case 7: - case 6: - case 5: - case 4: - qs4 = insert4 (pg, - &reserves[i], - gc, - ¬ify_s[i], - reserve_expiration, - &transaction_duplicate[i], - &conflicts[i], - &reserve_uuid[i]); - if (qs4<0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to create reserve batch_4 (%d)\n", - qs4); - results[i] = qs4; - return qs4; - } - need_update |= conflicts[i]; - need_update |= conflicts[i + 1]; - need_update |= conflicts[i + 2]; - need_update |= conflicts[i + 3]; - for (unsigned int j = 0; j<4; j++) - results[i + j] = transaction_duplicate[i + j] - ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - i += 4; - break; - case 3: - case 2: - qs5 = insert2 (pg, - &reserves[i], - gc, - ¬ify_s[i], - reserve_expiration, - &transaction_duplicate[i], - &conflicts[i], - &reserve_uuid[i]); - if (qs5<0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to create reserve batch_2 (%d)\n", - qs5); - results[i] = qs5; - return qs5; - } - need_update |= conflicts[i]; - need_update |= conflicts[i + 1]; - for (unsigned int j = 0; j<2; j++) - results[i + j] = transaction_duplicate[i + j] - ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - i += 2; - break; - case 1: - qs2 = insert1 (pg, - &reserves[i], - gc, - ¬ify_s[i], - reserve_expiration, - &transaction_duplicate[i], - &conflicts[i], - &reserve_uuid[i]); - if (qs2<0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to create reserve batch_1 (%d)\n)", - qs2); - results[i] = qs2; - return qs2; - } - need_update |= conflicts[i]; - results[i] = (transaction_duplicate[i]) - ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - i += 1; - break; - case 0: - GNUNET_assert (0); - break; - } - } /* end while */ - // commit - { - enum GNUNET_DB_QueryStatus cs; - - cs = TEH_PG_commit (pg); - if (cs < 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to commit\n"); - return cs; - } - } - if (! need_update) - { - goto exit; - } - // begin serializable - { - if (GNUNET_OK != - TEH_PG_start (pg, - "reserve-insert-continued")) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - } - - PREPARE (pg, - "reserves_update", - "SELECT" - " out_duplicate AS duplicate " - "FROM exchange_do_batch_reserves_update" - " ($1,$2,$3,$4,$5,$6,$7,$8);"); + qs = transact (pg, + rrs, + reserves_length, + batch_size, + results); for (unsigned int i = 0; iconn, - "reserves_update", - params, - rs); - if (qs3<0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to update reserves (%d)\n", - qs3); - results[i] = qs3; - return qs3; - } - results[i] = duplicate - ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } - } - - { - enum GNUNET_DB_QueryStatus cs; - - cs = TEH_PG_commit (pg); - if (cs < 0) - { - for (unsigned int i = 0; ilabel); is->child_death_task = NULL; From 53157062cb482824b4315aaa60bb548b2977ced2 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 22 Apr 2023 01:40:53 +0200 Subject: [PATCH 41/50] -misc bugs --- .../exchange_do_reserves_in_insert.sql | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql index e7506dc85..1c99f4fd1 100644 --- a/src/exchangedb/exchange_do_reserves_in_insert.sql +++ b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -32,11 +32,11 @@ CREATE OR REPLACE FUNCTION exchange_do_batch_reserves_in_insert( LANGUAGE plpgsql AS $$ DECLARE - curs refcursor; + curs REFCURSOR; DECLARE i RECORD; DECLARE - curs_trans refcursor; + curs_trans REFCURSOR; BEGIN ruuid0 = 0; out_reserve_found0 = TRUE; @@ -228,7 +228,7 @@ BEGIN CLOSE curs_reserve_exist; OPEN curs_transaction_exist FOR - WITH reserve_in_exist AS ( + WITH reserve_transaction AS ( INSERT INTO reserves_in (reserve_pub ,wire_reference @@ -254,7 +254,7 @@ BEGIN ,in1_execution_date) ON CONFLICT DO NOTHING RETURNING reserve_pub) - SELECT reserve_pub FROM reserve_in_exist; + SELECT reserve_pub FROM reserve_transaction; FETCH FROM curs_transaction_exist INTO r; @@ -270,7 +270,7 @@ BEGIN CASE k WHEN 0 THEN k = k + 1; - IF in0_reserve_pub = r.reserve_pub + IF in0_reserve_pub = i.reserve_pub THEN transaction_duplicate0 = FALSE; EXECUTE FORMAT ( @@ -280,7 +280,7 @@ BEGIN END IF; CONTINUE loop2_k; WHEN 1 THEN - IF in0_reserve_pub = r.reserve_pub + IF in0_reserve_pub = i.reserve_pub THEN transaction_duplicate1 = FALSE; EXECUTE FORMAT ( @@ -324,7 +324,7 @@ CREATE OR REPLACE FUNCTION exchange_do_batch4_reserves_insert( IN in2_credit_val INT8, IN in2_credit_frac INT4, IN in2_exchange_account_name VARCHAR, - IN in2_execute_date INT8, + IN in2_execution_date INT8, IN in2_wire_source_h_payto BYTEA, IN in2_payto_uri VARCHAR, IN in2_notify TEXT, @@ -333,7 +333,7 @@ CREATE OR REPLACE FUNCTION exchange_do_batch4_reserves_insert( IN in3_credit_val INT8, IN in3_credit_frac INT4, IN in3_exchange_account_name VARCHAR, - IN in3_execute_date INT8, + IN in3_execution_date INT8, IN in3_wire_source_h_payto BYTEA, IN in3_payto_uri VARCHAR, IN in3_notify TEXT, @@ -472,7 +472,7 @@ BEGIN CLOSE curs_reserve_exist; OPEN curs_transaction_exist FOR - WITH reserve_changes AS ( + WITH reserve_transaction AS ( INSERT INTO reserves_in (reserve_pub ,wire_reference @@ -512,7 +512,7 @@ BEGIN ,in3_execution_date) ON CONFLICT DO NOTHING RETURNING reserve_pub) - SELECT reserve_uuid, reserve_pub FROM reserve_changes; + SELECT reserve_pub FROM reserve_transaction; k=0; <> LOOP @@ -526,7 +526,7 @@ BEGIN CASE k WHEN 0 THEN k = k + 1; - IF in0_reserve_pub = r.reserve_pub + IF in0_reserve_pub = i.reserve_pub THEN transaction_duplicate0 = FALSE; EXECUTE FORMAT ( @@ -537,7 +537,7 @@ BEGIN CONTINUE loop2_k; WHEN 1 THEN k = k + 1; - IF in1_reserve_pub = r.reserve_pub + IF in1_reserve_pub = i.reserve_pub THEN transaction_duplicate1 = FALSE; EXECUTE FORMAT ( @@ -548,7 +548,7 @@ BEGIN CONTINUE loop2_k; WHEN 2 THEN k = k + 1; - IF in2_reserve_pub = r.reserve_pub + IF in2_reserve_pub = i.reserve_pub THEN transaction_duplicate2 = FALSE; EXECUTE FORMAT ( @@ -558,7 +558,7 @@ BEGIN END IF; CONTINUE loop2_k; WHEN 3 THEN - IF in3_reserve_pub = r.reserve_pub + IF in3_reserve_pub = i.reserve_pub THEN transaction_duplicate3 = FALSE; EXECUTE FORMAT ( @@ -877,7 +877,7 @@ BEGIN CLOSE curs_reserve_exist; OPEN curs_transaction_exist FOR - WITH reserve_changes AS ( + WITH reserve_transaction AS ( INSERT INTO reserves_in (reserve_pub ,wire_reference @@ -945,7 +945,7 @@ BEGIN ,in7_execution_date) ON CONFLICT DO NOTHING RETURNING reserve_pub) - SELECT reserve_pub FROM reserve_changes; + SELECT reserve_pub FROM reserve_transaction; k=0; <> LOOP @@ -959,7 +959,7 @@ BEGIN CASE k WHEN 0 THEN k = k + 1; - IF in0_reserve_pub = r.reserve_pub + IF in0_reserve_pub = i.reserve_pub THEN transaction_duplicate0 = FALSE; EXECUTE FORMAT ( @@ -970,7 +970,7 @@ BEGIN CONTINUE loop2_k; WHEN 1 THEN k = k + 1; - IF in1_reserve_pub = r.reserve_pub + IF in1_reserve_pub = i.reserve_pub THEN transaction_duplicate1 = FALSE; EXECUTE FORMAT ( @@ -981,7 +981,7 @@ BEGIN CONTINUE loop2_k; WHEN 2 THEN k = k + 1; - IF in2_reserve_pub = r.reserve_pub + IF in2_reserve_pub = i.reserve_pub THEN transaction_duplicate2 = FALSE; EXECUTE FORMAT ( @@ -992,7 +992,7 @@ BEGIN CONTINUE loop2_k; WHEN 3 THEN k = k + 1; - IF in3_reserve_pub = r.reserve_pub + IF in3_reserve_pub = i.reserve_pub THEN transaction_duplicate3 = FALSE; EXECUTE FORMAT ( @@ -1003,7 +1003,7 @@ BEGIN CONTINUE loop2_k; WHEN 4 THEN k = k + 1; - IF in4_reserve_pub = r.reserve_pub + IF in4_reserve_pub = i.reserve_pub THEN transaction_duplicate4 = FALSE; EXECUTE FORMAT ( @@ -1014,7 +1014,7 @@ BEGIN CONTINUE loop2_k; WHEN 5 THEN k = k + 1; - IF in5_reserve_pub = r.reserve_pub + IF in5_reserve_pub = i.reserve_pub THEN transaction_duplicate2 = FALSE; EXECUTE FORMAT ( @@ -1025,7 +1025,7 @@ BEGIN CONTINUE loop2_k; WHEN 6 THEN k = k + 1; - IF in6_reserve_pub = r.reserve_pub + IF in6_reserve_pub = i.reserve_pub THEN transaction_duplicate6 = FALSE; EXECUTE FORMAT ( @@ -1035,7 +1035,7 @@ BEGIN END IF; CONTINUE loop2_k; WHEN 7 THEN - IF in7_reserve_pub = r.reserve_pub + IF in7_reserve_pub = i.reserve_pub THEN transaction_duplicate7 = FALSE; EXECUTE FORMAT ( From 89c5a3eca927deb57dff2a093e1f0e27b279eb87 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 22 Apr 2023 01:53:41 +0200 Subject: [PATCH 42/50] -misc bugs --- src/exchangedb/exchange_do_reserves_in_insert.sql | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql index 1c99f4fd1..77672f012 100644 --- a/src/exchangedb/exchange_do_reserves_in_insert.sql +++ b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -786,8 +786,13 @@ BEGIN ,in_reserve_expiration ,in_gc_date) ON CONFLICT DO NOTHING - RETURNING reserve_uuid,reserve_pub) - SELECT reserve_uuid, reserve_pub FROM reserve_changes; + RETURNING + reserve_uuid + ,reserve_pub) + SELECT + reserve_uuid + ,reserve_pub + FROM reserve_changes; k=0; <> LOOP @@ -1016,7 +1021,7 @@ BEGIN k = k + 1; IF in5_reserve_pub = i.reserve_pub THEN - transaction_duplicate2 = FALSE; + transaction_duplicate5 = FALSE; EXECUTE FORMAT ( 'NOTIFY %s' ,in5_notify); From 9e61579c8b8c42d49fc60744782dbd71efbbda8a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 22 Apr 2023 02:26:44 +0200 Subject: [PATCH 43/50] -misc fixes --- src/benchmark/bank-benchmark-cs.conf | 6 +++--- src/benchmark/taler-bank-benchmark.c | 2 ++ src/benchmark/taler-exchange-benchmark.c | 2 +- src/exchange/taler-exchange-wirewatch.c | 10 +++++++++- src/exchangedb/exchange_do_reserves_in_insert.sql | 6 +++--- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/benchmark/bank-benchmark-cs.conf b/src/benchmark/bank-benchmark-cs.conf index d012f0faa..e32370f89 100644 --- a/src/benchmark/bank-benchmark-cs.conf +++ b/src/benchmark/bank-benchmark-cs.conf @@ -28,7 +28,7 @@ DB = postgres # exchange (or the twister) is actually listening. base_url = "http://localhost:8081/" -WIREWATCH_IDLE_SLEEP_INTERVAL = 1500 ms +WIREWATCH_IDLE_SLEEP_INTERVAL = 500 ms [exchange-offline] MASTER_PRIV_FILE = ${TALER_DATA_HOME}/exchange/offline-keys/master.priv @@ -51,11 +51,11 @@ MAX_DEBT = EUR:100000000000.0 MAX_DEBT_BANK = EUR:1000000000000000.0 [benchmark] -USER_PAYTO_URI = payto://x-taler-bank/localhost:8082/42 +USER_PAYTO_URI = payto://x-taler-bank/localhost:8082/42?receiver-name=user42 [exchange-account-2] # What is the payto://-URL of the exchange (to generate wire response) -PAYTO_URI = "payto://x-taler-bank/localhost:8082/Exchange" +PAYTO_URI = "payto://x-taler-bank/localhost:8082/Exchange?receiver-name=Exchange" enable_debit = YES enable_credit = YES diff --git a/src/benchmark/taler-bank-benchmark.c b/src/benchmark/taler-bank-benchmark.c index b17bb9411..584df4896 100644 --- a/src/benchmark/taler-bank-benchmark.c +++ b/src/benchmark/taler-bank-benchmark.c @@ -689,6 +689,8 @@ parallel_benchmark (void) } /* But be extra sure we did finish all shards by doing one more */ + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Shard check phase\n"); wirewatch[0] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL, NULL, NULL, NULL, "taler-exchange-wirewatch", diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c index 77ef94ebc..fd7553813 100644 --- a/src/benchmark/taler-exchange-benchmark.c +++ b/src/benchmark/taler-exchange-benchmark.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2014-2020 Taler Systems SA + (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/exchange/taler-exchange-wirewatch.c b/src/exchange/taler-exchange-wirewatch.c index 9f954c27f..2bffc3b85 100644 --- a/src/exchange/taler-exchange-wirewatch.c +++ b/src/exchange/taler-exchange-wirewatch.c @@ -482,6 +482,10 @@ transaction_completed (void) latency = GNUNET_TIME_absolute_get_duration (hh_start_time); left = GNUNET_TIME_relative_subtract (longpoll_timeout, latency); +#if 1 + left = GNUNET_TIME_relative_min (left, + GNUNET_TIME_UNIT_SECONDS); +#endif delayed_until = GNUNET_TIME_relative_to_absolute (left); } if (test_mode) @@ -857,6 +861,10 @@ lock_shard (void *cls) job_name, GNUNET_STRINGS_relative_time_to_string (rdelay, true)); +#if 1 + rdelay = GNUNET_TIME_relative_min (rdelay, + GNUNET_TIME_UNIT_SECONDS); +#endif delayed_until = GNUNET_TIME_relative_to_absolute (rdelay); } GNUNET_assert (NULL == task); @@ -869,7 +877,7 @@ lock_shard (void *cls) job_name, GNUNET_STRINGS_relative_time_to_string ( wirewatch_idle_sleep_interval, - GNUNET_YES)); + true)); delayed_until = GNUNET_TIME_relative_to_absolute ( wirewatch_idle_sleep_interval); shard_open = false; diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql index 77672f012..07ce3ec28 100644 --- a/src/exchangedb/exchange_do_reserves_in_insert.sql +++ b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -286,8 +286,8 @@ BEGIN EXECUTE FORMAT ( 'NOTIFY %s' ,in1_notify); - EXIT loop_transaction; END IF; + EXIT loop_transaction; END CASE; END LOOP loop2_k; END LOOP loop_transaction; @@ -564,8 +564,8 @@ BEGIN EXECUTE FORMAT ( 'NOTIFY %s' ,in3_notify); - EXIT loop_transaction; END IF; + EXIT loop_transaction; END CASE; END LOOP loop2_k; END LOOP loop_transaction; @@ -1046,8 +1046,8 @@ BEGIN EXECUTE FORMAT ( 'NOTIFY %s' ,in7_notify); - EXIT loop_transaction; END IF; + EXIT loop_transaction; END CASE; END LOOP loop2_k; END LOOP loop_transaction; From 0236caf3546acfc25dabe8f8f5763c64a6f55561 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 22 Apr 2023 02:30:02 +0200 Subject: [PATCH 44/50] -misc fixes --- src/exchangedb/exchange_do_reserves_in_insert.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql index 07ce3ec28..d68541f22 100644 --- a/src/exchangedb/exchange_do_reserves_in_insert.sql +++ b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -280,7 +280,7 @@ BEGIN END IF; CONTINUE loop2_k; WHEN 1 THEN - IF in0_reserve_pub = i.reserve_pub + IF in1_reserve_pub = i.reserve_pub THEN transaction_duplicate1 = FALSE; EXECUTE FORMAT ( From be1d8afaec27d7cda6fb858930557e5a9be5df15 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 22 Apr 2023 02:33:18 +0200 Subject: [PATCH 45/50] -misc fixes --- src/exchangedb/exchange_do_reserves_in_insert.sql | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql index d68541f22..dd202a2ae 100644 --- a/src/exchangedb/exchange_do_reserves_in_insert.sql +++ b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -218,9 +218,8 @@ BEGIN THEN ruuid1 = i.reserve_uuid; out_reserve_found1 = FALSE; - EXIT loop_reserve; END IF; - EXIT loop_k; + EXIT loop_reserve; END CASE; END LOOP loop_k; END LOOP loop_reserve; @@ -462,9 +461,8 @@ BEGIN THEN ruuid3 = i.reserve_uuid; out_reserve_found3 = FALSE; - EXIT loop_reserve; END IF; - EXIT loop_k; + EXIT loop_reserve; END CASE; END LOOP loop_k; END LOOP loop_reserve; @@ -872,9 +870,8 @@ BEGIN THEN ruuid7 = i.reserve_uuid; out_reserve_found7 = FALSE; - EXIT loop_reserve; END IF; - EXIT loop_k; + EXIT loop_reserve; END CASE; END LOOP loop_k; END LOOP loop_reserve; From 76b934b219b6ec82f58a7e95cbc6fff4f4ed0ebf Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 22 Apr 2023 02:54:55 +0200 Subject: [PATCH 46/50] -misc fixes --- .../exchange_do_reserves_in_insert.sql | 54 +++++++++---------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql index dd202a2ae..6cd5847df 100644 --- a/src/exchangedb/exchange_do_reserves_in_insert.sql +++ b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -145,14 +145,12 @@ LANGUAGE plpgsql AS $$ DECLARE curs_reserve_exist REFCURSOR; +DECLARE + k INT8; DECLARE curs_transaction_exist REFCURSOR; DECLARE i RECORD; -DECLARE - r RECORD; -DECLARE - k INT8; BEGIN transaction_duplicate0 = TRUE; transaction_duplicate1 = TRUE; @@ -228,35 +226,33 @@ BEGIN OPEN curs_transaction_exist FOR WITH reserve_transaction AS ( - INSERT INTO reserves_in - (reserve_pub - ,wire_reference - ,credit_val - ,credit_frac - ,exchange_account_section - ,wire_source_h_payto - ,execution_date) - VALUES - (in0_reserve_pub - ,in0_wire_ref - ,in0_credit_val - ,in0_credit_frac - ,in0_exchange_account_name - ,in0_wire_source_h_payto - ,in0_execution_date), - (in1_reserve_pub - ,in1_wire_ref - ,in1_credit_val - ,in1_credit_frac - ,in1_exchange_account_name - ,in1_wire_source_h_payto - ,in1_execution_date) + INSERT INTO reserves_in + (reserve_pub + ,wire_reference + ,credit_val + ,credit_frac + ,exchange_account_section + ,wire_source_h_payto + ,execution_date) + VALUES + (in0_reserve_pub + ,in0_wire_ref + ,in0_credit_val + ,in0_credit_frac + ,in0_exchange_account_name + ,in0_wire_source_h_payto + ,in0_execution_date), + (in1_reserve_pub + ,in1_wire_ref + ,in1_credit_val + ,in1_credit_frac + ,in1_exchange_account_name + ,in1_wire_source_h_payto + ,in1_execution_date) ON CONFLICT DO NOTHING RETURNING reserve_pub) SELECT reserve_pub FROM reserve_transaction; - FETCH FROM curs_transaction_exist INTO r; - k=0; <> LOOP FETCH FROM curs_transaction_exist INTO i; From c3fc8c5e558d4bcba0492c8d0e2d563ce7fb0519 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 22 Apr 2023 14:43:26 +0200 Subject: [PATCH 47/50] fix fakebank long polling --- src/bank-lib/fakebank.c | 691 +++++++++++++++--------- src/exchange/taler-exchange-wirewatch.c | 34 +- 2 files changed, 474 insertions(+), 251 deletions(-) diff --git a/src/bank-lib/fakebank.c b/src/bank-lib/fakebank.c index 76e4db70a..60492e50f 100644 --- a/src/bank-lib/fakebank.c +++ b/src/bank-lib/fakebank.c @@ -400,6 +400,148 @@ struct Transaction }; +/** + * Function called to clean up context of a connection. + * + * @param ctx context to clean up + */ +typedef void +(*ConnectionCleaner)(void *ctx); + +/** + * Universal context we keep per connection. + */ +struct ConnectionContext +{ + /** + * Function we call upon completion to clean up. + */ + ConnectionCleaner ctx_cleaner; + + /** + * Request-handler specific context. + */ + void *ctx; +}; + + +/** + * This is the "base" structure for both the /history and the + * /history-range API calls. + */ +struct HistoryArgs +{ + + /** + * Bank account number of the requesting client. + */ + uint64_t account_number; + + /** + * Index of the starting transaction, exclusive (!). + */ + uint64_t start_idx; + + /** + * Requested number of results and order + * (positive: ascending, negative: descending) + */ + int64_t delta; + + /** + * Timeout for long polling. + */ + struct GNUNET_TIME_Relative lp_timeout; + + /** + * true if starting point was given. + */ + bool have_start; + +}; + + +/** + * Context we keep per history request. + */ +struct HistoryContext +{ + /** + * When does this request time out. + */ + struct GNUNET_TIME_Absolute timeout; + + /** + * Client arguments for this request. + */ + struct HistoryArgs ha; + + /** + * Account the request is about. + */ + struct Account *acc; + + /** + * Payto URI of the account. + */ + char *payto_uri; + + /** + * JSON object we are building to return. + */ + json_t *history; + +}; + + +/** + * Function called to clean up a history context. + * + * @param cls a `struct HistoryContext *` + */ +static void +history_cleanup (void *cls) +{ + struct HistoryContext *hc = cls; + + GNUNET_free (hc->payto_uri); + json_decref (hc->history); + GNUNET_free (hc); +} + + +/** + * Context we keep per get withdrawal operation request. + */ +struct WithdrawContext +{ + /** + * When does this request time out. + */ + struct GNUNET_TIME_Absolute timeout; + + /** + * The withdrawal operation this is about. + */ + struct WithdrawalOperation *wo; + +}; + + +/** + * Function called to clean up a withdraw context. + * + * @param cls a `struct WithdrawContext *` + */ +static void +withdraw_cleanup (void *cls) +{ + struct WithdrawContext *wc = cls; + + GNUNET_free (wc); +} + + /** * Handle for the fake bank. */ @@ -569,13 +711,6 @@ struct TALER_FAKEBANK_Handle }; -/** - * Special address "con_cls" can point to to indicate that the handler has - * been called more than once already (was previously suspended). - */ -static int special_ptr; - - /** * Task run whenever HTTP server operations are pending. * @@ -1583,15 +1718,14 @@ handle_mhd_completion_callback (void *cls, enum MHD_RequestTerminationCode toe) { /* struct TALER_FAKEBANK_Handle *h = cls; */ + struct ConnectionContext *cc = *con_cls; (void) cls; (void) connection; (void) toe; - if (NULL == *con_cls) + if (NULL == cc) return; - if (&special_ptr == *con_cls) - return; - GNUNET_JSON_post_parser_cleanup (*con_cls); - *con_cls = NULL; + cc->ctx_cleaner (cc->ctx); + GNUNET_free (cc); } @@ -1603,7 +1737,7 @@ handle_mhd_completion_callback (void *cls, * @param account account into which to deposit the funds (credit) * @param upload_data request data * @param upload_data_size size of @a upload_data in bytes - * @param con_cls closure for request (a `struct Buffer *`) + * @param con_cls closure for request (a `struct ConnectionContext *`) * @return MHD result code */ static MHD_RESULT @@ -1614,14 +1748,21 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h, size_t *upload_data_size, void **con_cls) { + struct ConnectionContext *cc = *con_cls; enum GNUNET_JSON_PostResult pr; json_t *json; uint64_t row_id; struct GNUNET_TIME_Timestamp timestamp; + if (NULL == cc) + { + cc = GNUNET_new (struct ConnectionContext); + cc->ctx_cleaner = &GNUNET_JSON_post_parser_cleanup; + *con_cls = cc; + } pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, connection, - con_cls, + &cc->ctx, upload_data, upload_data_size, &json); @@ -1736,7 +1877,7 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h, * @param account account making the transfer * @param upload_data request data * @param upload_data_size size of @a upload_data in bytes - * @param con_cls closure for request (a `struct Buffer *`) + * @param con_cls closure for request (a `struct ConnectionContext *`) * @return MHD result code */ static MHD_RESULT @@ -1747,14 +1888,21 @@ handle_transfer (struct TALER_FAKEBANK_Handle *h, size_t *upload_data_size, void **con_cls) { + struct ConnectionContext *cc = *con_cls; enum GNUNET_JSON_PostResult pr; json_t *json; uint64_t row_id; struct GNUNET_TIME_Timestamp ts; + if (NULL == cc) + { + cc = GNUNET_new (struct ConnectionContext); + cc->ctx_cleaner = &GNUNET_JSON_post_parser_cleanup; + *con_cls = cc; + } pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, connection, - con_cls, + &cc->ctx, upload_data, upload_data_size, &json); @@ -1895,42 +2043,6 @@ handle_home_page (struct TALER_FAKEBANK_Handle *h, } -/** - * This is the "base" structure for both the /history and the - * /history-range API calls. - */ -struct HistoryArgs -{ - - /** - * Bank account number of the requesting client. - */ - uint64_t account_number; - - /** - * Index of the starting transaction, exclusive (!). - */ - uint64_t start_idx; - - /** - * Requested number of results and order - * (positive: ascending, negative: descending) - */ - int64_t delta; - - /** - * Timeout for long polling. - */ - struct GNUNET_TIME_Relative lp_timeout; - - /** - * true if starting point was given. - */ - bool have_start; - -}; - - /** * Parse URL history arguments, of _both_ APIs: * /history/incoming and /history/outgoing. @@ -2176,7 +2288,7 @@ start_lp (struct TALER_FAKEBANK_Handle *h, * @param h the fakebank handle * @param connection the connection * @param account which account the request is about - * @param con_cls closure for request (NULL or &special_ptr) + * @param con_cls closure for request */ static MHD_RESULT handle_debit_history (struct TALER_FAKEBANK_Handle *h, @@ -2184,87 +2296,106 @@ handle_debit_history (struct TALER_FAKEBANK_Handle *h, const char *account, void **con_cls) { - struct HistoryArgs ha; - struct Account *acc; + struct ConnectionContext *cc = *con_cls; + struct HistoryContext *hc; struct Transaction *pos; - json_t *history; - char *debit_payto; enum GNUNET_GenericReturnValue ret; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Handling /history/outgoing connection %p\n", - connection); - if (GNUNET_OK != - (ret = parse_history_common_args (h, - connection, - &ha))) + if (NULL == cc) { - GNUNET_break_op (0); - return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES; - } - if (&special_ptr == *con_cls) - ha.lp_timeout = GNUNET_TIME_UNIT_ZERO; - acc = lookup_account (h, - account, - NULL); - if (NULL == acc) - { - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_BANK_UNKNOWN_ACCOUNT, - account); - } - GNUNET_asprintf (&debit_payto, - "payto://x-taler-bank/localhost/%s?receiver-name=%s", - account, - acc->receiver_name); - history = json_array (); - if (NULL == history) - { - GNUNET_break (0); - GNUNET_free (debit_payto); - return MHD_NO; - } - GNUNET_assert (0 == - pthread_mutex_lock (&h->big_lock)); - if (! ha.have_start) - { - pos = (0 > ha.delta) - ? acc->out_tail - : acc->out_head; + cc = GNUNET_new (struct ConnectionContext); + cc->ctx_cleaner = &history_cleanup; + *con_cls = cc; + hc = GNUNET_new (struct HistoryContext); + cc->ctx = hc; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Handling /history/outgoing connection %p\n", + connection); + if (GNUNET_OK != + (ret = parse_history_common_args (h, + connection, + &hc->ha))) + { + GNUNET_break_op (0); + return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES; + } + GNUNET_assert (0 == + pthread_mutex_lock (&h->big_lock)); + hc->acc = lookup_account (h, + account, + NULL); + if (NULL == hc->acc) + { + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_BANK_UNKNOWN_ACCOUNT, + account); + } + GNUNET_asprintf (&hc->payto_uri, + "payto://x-taler-bank/localhost/%s?receiver-name=%s", + account, + hc->acc->receiver_name); + /* New invariant: */ + GNUNET_assert (0 == strcmp (hc->payto_uri, + hc->acc->payto_uri)); + hc->history = json_array (); + if (NULL == hc->history) + { + GNUNET_break (0); + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + return MHD_NO; + } + hc->timeout = GNUNET_TIME_relative_to_absolute (hc->ha.lp_timeout); } else { - struct Transaction *t = h->transactions[ha.start_idx % h->ram_limit]; + hc = cc->ctx; + GNUNET_assert (0 == + pthread_mutex_lock (&h->big_lock)); + } + + if (! hc->ha.have_start) + { + pos = (0 > hc->ha.delta) + ? hc->acc->out_tail + : hc->acc->out_head; + } + else + { + struct Transaction *t = h->transactions[hc->ha.start_idx % h->ram_limit]; bool overflow; uint64_t dir; bool skip = true; - dir = (0 > ha.delta) ? (h->ram_limit - 1) : 1; - overflow = (t->row_id != ha.start_idx); + dir = (0 > hc->ha.delta) ? (h->ram_limit - 1) : 1; + overflow = (t->row_id != hc->ha.start_idx); /* If account does not match, linear scan for first matching account. */ while ( (! overflow) && - (NULL != t) && - (t->debit_account != acc) ) + (NULL != t) && + (t->debit_account != hc->acc) ) { skip = false; t = h->transactions[(t->row_id + dir) % h->ram_limit]; if ( (NULL != t) && - (t->row_id == ha.start_idx) ) + (t->row_id == hc->ha.start_idx) ) overflow = true; /* full circle, give up! */ } if ( (NULL == t) || overflow) { - if (GNUNET_TIME_relative_is_zero (ha.lp_timeout) && - (0 < ha.delta)) + /* FIXME: these conditions are unclear to me. */ + if ( (GNUNET_TIME_relative_is_zero (hc->ha.lp_timeout)) && + (0 < hc->ha.delta)) { GNUNET_assert (0 == pthread_mutex_unlock (&h->big_lock)); if (overflow) { - GNUNET_free (debit_payto); return TALER_MHD_reply_with_ec ( connection, TALER_EC_BANK_ANCIENT_TRANSACTION_GONE, @@ -2272,35 +2403,36 @@ handle_debit_history (struct TALER_FAKEBANK_Handle *h, } goto finish; } - *con_cls = &special_ptr; + if (h->in_shutdown) + { + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + goto finish; + } start_lp (h, connection, - acc, - ha.lp_timeout, + hc->acc, + GNUNET_TIME_absolute_get_remaining (hc->timeout), LP_DEBIT, NULL); GNUNET_assert (0 == pthread_mutex_unlock (&h->big_lock)); - json_decref (history); - GNUNET_free (debit_payto); return MHD_YES; } - if (t->debit_account != acc) + if (t->debit_account != hc->acc) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid start specified, transaction %llu not with account %s!\n", - (unsigned long long) ha.start_idx, + (unsigned long long) hc->ha.start_idx, account); GNUNET_assert (0 == pthread_mutex_unlock (&h->big_lock)); - GNUNET_free (debit_payto); - json_decref (history); return MHD_NO; } if (skip) { /* range is exclusive, skip the matching entry */ - if (0 > ha.delta) + if (0 > hc->ha.delta) pos = t->prev_out; else pos = t->next_out; @@ -2313,9 +2445,9 @@ handle_debit_history (struct TALER_FAKEBANK_Handle *h, if (NULL != pos) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Returning %lld debit transactions starting (inclusive) from %llu\n", - (long long) ha.delta, + (long long) hc->ha.delta, (unsigned long long) pos->row_id); - while ( (0 != ha.delta) && + while ( (0 != hc->ha.delta) && (NULL != pos) ) { json_t *trans; @@ -2327,9 +2459,9 @@ handle_debit_history (struct TALER_FAKEBANK_Handle *h, "Unexpected CREDIT transaction #%llu for account `%s'\n", (unsigned long long) pos->row_id, account); - if (0 > ha.delta) + if (0 > hc->ha.delta) pos = pos->prev_in; - if (0 < ha.delta) + if (0 < hc->ha.delta) pos = pos->next_in; continue; } @@ -2348,7 +2480,7 @@ handle_debit_history (struct TALER_FAKEBANK_Handle *h, GNUNET_JSON_pack_string ("credit_account", credit_payto), GNUNET_JSON_pack_string ("debit_account", - debit_payto), // FIXME #7275: inefficient to return this here always! + hc->payto_uri), // FIXME #7275: inefficient to return this here always! GNUNET_JSON_pack_string ("exchange_base_url", pos->subject.debit.exchange_base_url), GNUNET_JSON_pack_data_auto ("wtid", @@ -2356,51 +2488,55 @@ handle_debit_history (struct TALER_FAKEBANK_Handle *h, GNUNET_assert (NULL != trans); GNUNET_free (credit_payto); GNUNET_assert (0 == - json_array_append_new (history, + json_array_append_new (hc->history, trans)); - if (ha.delta > 0) - ha.delta--; + if (hc->ha.delta > 0) + hc->ha.delta--; else - ha.delta++; - if (0 > ha.delta) + hc->ha.delta++; + if (0 > hc->ha.delta) pos = pos->prev_out; - if (0 < ha.delta) + if (0 < hc->ha.delta) pos = pos->next_out; } - if ( (0 == json_array_size (history)) && - (! GNUNET_TIME_relative_is_zero (ha.lp_timeout)) && - (0 < ha.delta)) + if ( (0 == json_array_size (hc->history)) && + (! h->in_shutdown) && + (GNUNET_TIME_absolute_is_future (hc->timeout)) && + (0 < hc->ha.delta)) { - *con_cls = &special_ptr; start_lp (h, connection, - acc, - ha.lp_timeout, + hc->acc, + GNUNET_TIME_absolute_get_remaining (hc->timeout), LP_DEBIT, NULL); GNUNET_assert (0 == pthread_mutex_unlock (&h->big_lock)); - json_decref (history); return MHD_YES; } GNUNET_assert (0 == pthread_mutex_unlock (&h->big_lock)); finish: - if (0 == json_array_size (history)) + if (0 == json_array_size (hc->history)) { - json_decref (history); + GNUNET_break (h->in_shutdown || + (! GNUNET_TIME_absolute_is_future (hc->timeout))); return TALER_MHD_reply_static (connection, MHD_HTTP_NO_CONTENT, NULL, NULL, 0); } - GNUNET_free (debit_payto); - return TALER_MHD_REPLY_JSON_PACK (connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_array_steal ( - "outgoing_transactions", - history)); + { + json_t *h = hc->history; + + hc->history = NULL; + return TALER_MHD_REPLY_JSON_PACK (connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_array_steal ( + "outgoing_transactions", + h)); + } } @@ -2419,77 +2555,101 @@ handle_credit_history (struct TALER_FAKEBANK_Handle *h, const char *account, void **con_cls) { - struct HistoryArgs ha; - struct Account *acc; + struct ConnectionContext *cc = *con_cls; + struct HistoryContext *hc; const struct Transaction *pos; - json_t *history; - const char *credit_payto; enum GNUNET_GenericReturnValue ret; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Handling /history/incoming connection %p (%d)\n", - connection, - (*con_cls == &special_ptr)); - if (GNUNET_OK != - (ret = parse_history_common_args (h, - connection, - &ha))) + if (NULL == cc) { - GNUNET_break_op (0); - return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES; - } - if (&special_ptr == *con_cls) - ha.lp_timeout = GNUNET_TIME_UNIT_ZERO; - *con_cls = &special_ptr; - acc = lookup_account (h, - account, - NULL); - if (NULL == acc) - { - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_BANK_UNKNOWN_ACCOUNT, - account); - } - history = json_array (); - GNUNET_assert (NULL != history); - credit_payto = acc->payto_uri; - GNUNET_assert (0 == - pthread_mutex_lock (&h->big_lock)); - if (! ha.have_start) - { - pos = (0 > ha.delta) - ? acc->in_tail - : acc->in_head; + cc = GNUNET_new (struct ConnectionContext); + cc->ctx_cleaner = &history_cleanup; + *con_cls = cc; + hc = GNUNET_new (struct HistoryContext); + cc->ctx = hc; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Handling /history/incoming connection %p\n", + connection); + if (GNUNET_OK != + (ret = parse_history_common_args (h, + connection, + &hc->ha))) + { + GNUNET_break_op (0); + return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES; + } + GNUNET_assert (0 == + pthread_mutex_lock (&h->big_lock)); + hc->acc = lookup_account (h, + account, + NULL); + if (NULL == hc->acc) + { + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_BANK_UNKNOWN_ACCOUNT, + account); + } + /* FIXME: was simply: acc->payto_uri -- same!? */ + GNUNET_asprintf (&hc->payto_uri, + "payto://x-taler-bank/localhost/%s?receiver-name=%s", + account, + hc->acc->receiver_name); + GNUNET_assert (0 == strcmp (hc->payto_uri, + hc->acc->payto_uri)); + hc->history = json_array (); + if (NULL == hc->history) + { + GNUNET_break (0); + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + return MHD_NO; + } + hc->timeout = GNUNET_TIME_relative_to_absolute (hc->ha.lp_timeout); } else { - struct Transaction *t = h->transactions[ha.start_idx % h->ram_limit]; + hc = cc->ctx; + GNUNET_assert (0 == + pthread_mutex_lock (&h->big_lock)); + } + + if (! hc->ha.have_start) + { + pos = (0 > hc->ha.delta) + ? hc->acc->in_tail + : hc->acc->in_head; + } + else + { + struct Transaction *t = h->transactions[hc->ha.start_idx % h->ram_limit]; bool overflow; uint64_t dir; bool skip = true; - overflow = ( (NULL != t) && (t->row_id != ha.start_idx) ); - dir = (0 > ha.delta) ? (h->ram_limit - 1) : 1; + overflow = ( (NULL != t) && (t->row_id != hc->ha.start_idx) ); + dir = (0 > hc->ha.delta) ? (h->ram_limit - 1) : 1; /* If account does not match, linear scan for first matching account. */ while ( (! overflow) && (NULL != t) && - (t->credit_account != acc) ) + (t->credit_account != hc->acc) ) { skip = false; t = h->transactions[(t->row_id + dir) % h->ram_limit]; if ( (NULL != t) && - (t->row_id == ha.start_idx) ) + (t->row_id == hc->ha.start_idx) ) overflow = true; /* full circle, give up! */ } if ( (NULL == t) || overflow) { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "No transactions available, suspending request\n"); - if (GNUNET_TIME_relative_is_zero (ha.lp_timeout) && - (0 < ha.delta)) + /* FIXME: these conditions are unclear to me. */ + if (GNUNET_TIME_relative_is_zero (hc->ha.lp_timeout) && + (0 < hc->ha.delta)) { GNUNET_assert (0 == pthread_mutex_unlock (&h->big_lock)); @@ -2500,23 +2660,27 @@ handle_credit_history (struct TALER_FAKEBANK_Handle *h, NULL); goto finish; } - *con_cls = &special_ptr; + if (h->in_shutdown) + { + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + goto finish; + } start_lp (h, connection, - acc, - ha.lp_timeout, + hc->acc, + GNUNET_TIME_absolute_get_remaining (hc->timeout), LP_CREDIT, NULL); GNUNET_assert (0 == pthread_mutex_unlock (&h->big_lock)); - json_decref (history); return MHD_YES; } if (skip) { /* range from application is exclusive, skip the matching entry */ - if (0 > ha.delta) + if (0 > hc->ha.delta) pos = t->prev_in; else pos = t->next_in; @@ -2529,9 +2693,9 @@ handle_credit_history (struct TALER_FAKEBANK_Handle *h, if (NULL != pos) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Returning %lld credit transactions starting (inclusive) from %llu\n", - (long long) ha.delta, + (long long) hc->ha.delta, (unsigned long long) pos->row_id); - while ( (0 != ha.delta) && + while ( (0 != hc->ha.delta) && (NULL != pos) ) { json_t *trans; @@ -2542,9 +2706,9 @@ handle_credit_history (struct TALER_FAKEBANK_Handle *h, "Unexpected DEBIT transaction #%llu for account `%s'\n", (unsigned long long) pos->row_id, account); - if (0 > ha.delta) + if (0 > hc->ha.delta) pos = pos->prev_in; - if (0 < ha.delta) + if (0 < hc->ha.delta) pos = pos->next_in; continue; } @@ -2556,57 +2720,62 @@ handle_credit_history (struct TALER_FAKEBANK_Handle *h, TALER_JSON_pack_amount ("amount", &pos->amount), GNUNET_JSON_pack_string ("credit_account", - credit_payto), // FIXME #7275: inefficient to repeat this always here! + hc->payto_uri), // FIXME #7275: inefficient to repeat this always here! GNUNET_JSON_pack_string ("debit_account", pos->debit_account->payto_uri), GNUNET_JSON_pack_data_auto ("reserve_pub", &pos->subject.credit.reserve_pub)); GNUNET_assert (NULL != trans); GNUNET_assert (0 == - json_array_append_new (history, + json_array_append_new (hc->history, trans)); - if (ha.delta > 0) - ha.delta--; + if (hc->ha.delta > 0) + hc->ha.delta--; else - ha.delta++; - if (0 > ha.delta) + hc->ha.delta++; + if (0 > hc->ha.delta) pos = pos->prev_in; - if (0 < ha.delta) + if (0 < hc->ha.delta) pos = pos->next_in; } - if ( (0 == json_array_size (history)) && - (! GNUNET_TIME_relative_is_zero (ha.lp_timeout)) && - (0 < ha.delta)) + if ( (0 == json_array_size (hc->history)) && + (! h->in_shutdown) && + (GNUNET_TIME_absolute_is_future (hc->timeout)) && + (0 < hc->ha.delta)) { - *con_cls = &special_ptr; start_lp (h, connection, - acc, - ha.lp_timeout, + hc->acc, + GNUNET_TIME_absolute_get_remaining (hc->timeout), LP_CREDIT, NULL); GNUNET_assert (0 == pthread_mutex_unlock (&h->big_lock)); - json_decref (history); return MHD_YES; } GNUNET_assert (0 == pthread_mutex_unlock (&h->big_lock)); finish: - if (0 == json_array_size (history)) + if (0 == json_array_size (hc->history)) { - json_decref (history); + GNUNET_break (h->in_shutdown || + (! GNUNET_TIME_absolute_is_future (hc->timeout))); return TALER_MHD_reply_static (connection, MHD_HTTP_NO_CONTENT, NULL, NULL, 0); } - return TALER_MHD_REPLY_JSON_PACK (connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_array_steal ( - "incoming_transactions", - history)); + { + json_t *h = hc->history; + + hc->history = NULL; + return TALER_MHD_REPLY_JSON_PACK (connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_array_steal ( + "incoming_transactions", + h)); + } } @@ -2711,25 +2880,39 @@ get_withdrawal_operation (struct TALER_FAKEBANK_Handle *h, struct GNUNET_TIME_Relative lp, void **con_cls) { - struct WithdrawalOperation *wo; + struct ConnectionContext *cc = *con_cls; + struct WithdrawContext *wc; GNUNET_assert (0 == pthread_mutex_lock (&h->big_lock)); - wo = lookup_withdrawal_operation (h, - wopid); - if (NULL == wo) + if (NULL == cc) { - GNUNET_assert (0 == - pthread_mutex_unlock (&h->big_lock)); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_BANK_TRANSACTION_NOT_FOUND, - wopid); + cc = GNUNET_new (struct ConnectionContext); + cc->ctx_cleaner = &withdraw_cleanup; + *con_cls = cc; + wc = GNUNET_new (struct WithdrawContext); + cc->ctx = wc; + wc->wo = lookup_withdrawal_operation (h, + wopid); + if (NULL == wc->wo) + { + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_BANK_TRANSACTION_NOT_FOUND, + wopid); + } + wc->timeout = GNUNET_TIME_relative_to_absolute (lp); } - if ( (NULL != *con_cls) || - (GNUNET_TIME_relative_is_zero (lp)) || - wo->confirmation_done || - wo->aborted) + else + { + wc = cc->ctx; + } + if (GNUNET_TIME_absolute_is_past (wc->timeout) || + h->in_shutdown || + wc->wo->confirmation_done || + wc->wo->aborted) { json_t *wt; @@ -2744,27 +2927,26 @@ get_withdrawal_operation (struct TALER_FAKEBANK_Handle *h, connection, MHD_HTTP_OK, GNUNET_JSON_pack_bool ("aborted", - wo->aborted), + wc->wo->aborted), GNUNET_JSON_pack_bool ("selection_done", - wo->selection_done), + wc->wo->selection_done), GNUNET_JSON_pack_bool ("transfer_done", - wo->confirmation_done), + wc->wo->confirmation_done), GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("suggested_exchange", h->exchange_url)), TALER_JSON_pack_amount ("amount", - &wo->amount), + &wc->wo->amount), GNUNET_JSON_pack_array_steal ("wire_types", wt)); } - *con_cls = &special_ptr; start_lp (h, connection, - wo->debit_account, - lp, + wc->wo->debit_account, + GNUNET_TIME_absolute_get_remaining (wc->timeout), LP_WITHDRAW, - wo); + wc->wo); GNUNET_assert (0 == pthread_mutex_unlock (&h->big_lock)); return MHD_YES; @@ -2903,13 +3085,20 @@ post_withdrawal_operation (struct TALER_FAKEBANK_Handle *h, size_t *upload_data_size, void **con_cls) { + struct ConnectionContext *cc = *con_cls; enum GNUNET_JSON_PostResult pr; json_t *json; MHD_RESULT res; + if (NULL == cc) + { + cc = GNUNET_new (struct ConnectionContext); + cc->ctx_cleaner = &GNUNET_JSON_post_parser_cleanup; + *con_cls = cc; + } pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, connection, - con_cls, + &cc->ctx, upload_data, upload_data_size, &json); @@ -3294,13 +3483,20 @@ post_account_withdrawals_access (struct TALER_FAKEBANK_Handle *h, size_t *upload_data_size, void **con_cls) { + struct ConnectionContext *cc = *con_cls; enum GNUNET_JSON_PostResult pr; json_t *json; MHD_RESULT res; + if (NULL == cc) + { + cc = GNUNET_new (struct ConnectionContext); + cc->ctx_cleaner = &GNUNET_JSON_post_parser_cleanup; + *con_cls = cc; + } pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, connection, - con_cls, + &cc->ctx, upload_data, upload_data_size, &json); @@ -3367,13 +3563,20 @@ post_testing_register (struct TALER_FAKEBANK_Handle *h, size_t *upload_data_size, void **con_cls) { + struct ConnectionContext *cc = *con_cls; enum GNUNET_JSON_PostResult pr; json_t *json; MHD_RESULT res; + if (NULL == cc) + { + cc = GNUNET_new (struct ConnectionContext); + cc->ctx_cleaner = &GNUNET_JSON_post_parser_cleanup; + *con_cls = cc; + } pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, connection, - con_cls, + &cc->ctx, upload_data, upload_data_size, &json); diff --git a/src/exchange/taler-exchange-wirewatch.c b/src/exchange/taler-exchange-wirewatch.c index 2bffc3b85..235c0153f 100644 --- a/src/exchange/taler-exchange-wirewatch.c +++ b/src/exchange/taler-exchange-wirewatch.c @@ -57,6 +57,12 @@ static struct TALER_BANK_CreditHistoryHandle *hh; */ static bool hh_returned_data; +/** + * Set to true if the request for history did not + * succeed because the account was unknown. + */ +static bool hh_account_404; + /** * When did we start the last @e hh request? */ @@ -472,9 +478,9 @@ transaction_completed (void) GNUNET_SCHEDULER_shutdown (); return; } - if (! hh_returned_data) + if (! (hh_returned_data || hh_account_404) ) { - /* Enforce long polling delay even if the server ignored it + /* Enforce long-polling delay even if the server ignored it and returned earlier */ struct GNUNET_TIME_Relative latency; struct GNUNET_TIME_Relative left; @@ -482,12 +488,17 @@ transaction_completed (void) latency = GNUNET_TIME_absolute_get_duration (hh_start_time); left = GNUNET_TIME_relative_subtract (longpoll_timeout, latency); -#if 1 - left = GNUNET_TIME_relative_min (left, - GNUNET_TIME_UNIT_SECONDS); -#endif + if (! (test_mode || + GNUNET_TIME_relative_is_zero (left)) ) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, // WARNING, + "Server did not respect long-polling, enforcing client-side by sleeping for %s\n", + GNUNET_TIME_relative2s (left, + true)); delayed_until = GNUNET_TIME_relative_to_absolute (left); } + if (hh_account_404) + delayed_until = GNUNET_TIME_relative_to_absolute ( + GNUNET_TIME_UNIT_MILLISECONDS); if (test_mode) delayed_until = GNUNET_TIME_UNIT_ZERO_ABS; GNUNET_assert (NULL == task); @@ -713,7 +724,7 @@ history_cb (void *cls, } GNUNET_assert (NULL == task); hh = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "History request returned with HTTP status %u\n", reply->http_status); switch (reply->http_status) @@ -727,6 +738,7 @@ history_cb (void *cls, transaction_completed (); return; case MHD_HTTP_NOT_FOUND: + hh_account_404 = true; if (ignore_account_404) { transaction_completed (); @@ -765,6 +777,7 @@ continue_with_shard (void *cls) (unsigned long long) latest_row_off); hh_start_time = GNUNET_TIME_absolute_get (); hh_returned_data = false; + hh_account_404 = false; hh = TALER_BANK_credit_history (ctx, ai->auth, latest_row_off, @@ -862,6 +875,13 @@ lock_shard (void *cls) GNUNET_STRINGS_relative_time_to_string (rdelay, true)); #if 1 + if (GNUNET_TIME_relative_cmp (rdelay, + >, + GNUNET_TIME_UNIT_SECONDS)) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Delay would have been for %s\n", + GNUNET_TIME_relative2s (rdelay, + true)); rdelay = GNUNET_TIME_relative_min (rdelay, GNUNET_TIME_UNIT_SECONDS); #endif From acbee86745552a9b6361a8969d3c0a9d0399fc88 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 22 Apr 2023 15:02:47 +0200 Subject: [PATCH 48/50] simplify batch insert: no cursor where not required, replace out_reserve_found with ruuid being allowed to remain NULL --- .../exchange_do_reserves_in_insert.sql | 119 +++--------------- src/exchangedb/pg_reserves_in_insert.c | 31 ++--- 2 files changed, 25 insertions(+), 125 deletions(-) diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql index 6cd5847df..dffcd8b55 100644 --- a/src/exchangedb/exchange_do_reserves_in_insert.sql +++ b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -26,21 +26,11 @@ CREATE OR REPLACE FUNCTION exchange_do_batch_reserves_in_insert( IN in_wire_source_h_payto BYTEA, IN in_payto_uri VARCHAR, IN in_notify TEXT, - OUT out_reserve_found0 BOOLEAN, OUT transaction_duplicate0 BOOLEAN, OUT ruuid0 INT8) LANGUAGE plpgsql AS $$ -DECLARE - curs REFCURSOR; -DECLARE - i RECORD; -DECLARE - curs_trans REFCURSOR; BEGIN - ruuid0 = 0; - out_reserve_found0 = TRUE; - transaction_duplicate0 = TRUE; INSERT INTO wire_targets (wire_target_h_payto @@ -50,35 +40,22 @@ BEGIN ,in_payto_uri) ON CONFLICT DO NOTHING; - OPEN curs FOR - WITH reserve_changes AS ( - INSERT INTO reserves - (reserve_pub - ,current_balance_val - ,current_balance_frac - ,expiration_date - ,gc_date) - VALUES - (in_reserve_pub - ,in_credit_val - ,in_credit_frac - ,in_reserve_expiration - ,in_gc_date) - ON CONFLICT DO NOTHING - RETURNING reserve_uuid, reserve_pub) - SELECT reserve_uuid, reserve_pub FROM reserve_changes; + INSERT INTO reserves + (reserve_pub + ,current_balance_val + ,current_balance_frac + ,expiration_date + ,gc_date) + VALUES + (in_reserve_pub + ,in_credit_val + ,in_credit_frac + ,in_reserve_expiration + ,in_gc_date) + ON CONFLICT DO NOTHING + RETURNING reserve_uuid + INTO ruuid0; - FETCH FROM curs INTO i; - IF FOUND - THEN - -- We made a change, so the reserve did not previously exist. - out_reserve_found0 = FALSE; - ruuid0 = i.reserve_uuid; - END IF; - CLOSE curs; - - OPEN curs_trans FOR - WITH reserve_transaction AS( INSERT INTO reserves_in (reserve_pub ,wire_reference @@ -95,21 +72,15 @@ BEGIN ,in_exchange_account_name ,in_wire_source_h_payto ,in_execution_date) - ON CONFLICT DO NOTHING - RETURNING reserve_pub) - SELECT reserve_pub FROM reserve_transaction; + ON CONFLICT DO NOTHING; - FETCH FROM curs_trans INTO i; + transaction_duplicate0 = NOT FOUND; IF FOUND THEN - transaction_duplicate0 = FALSE; EXECUTE FORMAT ( 'NOTIFY %s' ,in_notify); END IF; - - CLOSE curs_trans; - RETURN; END $$; @@ -135,8 +106,6 @@ CREATE OR REPLACE FUNCTION exchange_do_batch2_reserves_insert( IN in1_wire_source_h_payto BYTEA, IN in1_payto_uri VARCHAR, IN in1_notify TEXT, - OUT out_reserve_found0 BOOLEAN, - OUT out_reserve_found1 BOOLEAN, OUT transaction_duplicate0 BOOLEAN, OUT transaction_duplicate1 BOOLEAN, OUT ruuid0 INT8, @@ -154,10 +123,6 @@ DECLARE BEGIN transaction_duplicate0 = TRUE; transaction_duplicate1 = TRUE; - out_reserve_found0 = TRUE; - out_reserve_found1 = TRUE; - ruuid0=0; - ruuid1=0; INSERT INTO wire_targets (wire_target_h_payto @@ -207,7 +172,6 @@ BEGIN IF in0_reserve_pub = i.reserve_pub THEN ruuid0 = i.reserve_uuid; - out_reserve_found0 = FALSE; CONTINUE loop_reserve; END IF; CONTINUE loop_k; @@ -215,7 +179,6 @@ BEGIN IF in1_reserve_pub = i.reserve_pub THEN ruuid1 = i.reserve_uuid; - out_reserve_found1 = FALSE; END IF; EXIT loop_reserve; END CASE; @@ -332,10 +295,6 @@ CREATE OR REPLACE FUNCTION exchange_do_batch4_reserves_insert( IN in3_wire_source_h_payto BYTEA, IN in3_payto_uri VARCHAR, IN in3_notify TEXT, - OUT out_reserve_found0 BOOLEAN, - OUT out_reserve_found1 BOOLEAN, - OUT out_reserve_found2 BOOLEAN, - OUT out_reserve_found3 BOOLEAN, OUT transaction_duplicate0 BOOLEAN, OUT transaction_duplicate1 BOOLEAN, OUT transaction_duplicate2 BOOLEAN, @@ -359,14 +318,6 @@ BEGIN transaction_duplicate1=TRUE; transaction_duplicate2=TRUE; transaction_duplicate3=TRUE; - out_reserve_found0 = TRUE; - out_reserve_found1 = TRUE; - out_reserve_found2 = TRUE; - out_reserve_found3 = TRUE; - ruuid0=0; - ruuid1=0; - ruuid2=0; - ruuid3=0; INSERT INTO wire_targets (wire_target_h_payto @@ -430,7 +381,6 @@ BEGIN IF in0_reserve_pub = i.reserve_pub THEN ruuid0 = i.reserve_uuid; - out_reserve_found0 = FALSE; CONTINUE loop_reserve; END IF; CONTINUE loop_k; @@ -439,7 +389,6 @@ BEGIN IF in1_reserve_pub = i.reserve_pub THEN ruuid1 = i.reserve_uuid; - out_reserve_found1 = FALSE; CONTINUE loop_reserve; END IF; CONTINUE loop_k; @@ -448,7 +397,6 @@ BEGIN IF in2_reserve_pub = i.reserve_pub THEN ruuid2 = i.reserve_uuid; - out_reserve_found2 = FALSE; CONTINUE loop_reserve; END IF; CONTINUE loop_k; @@ -456,7 +404,6 @@ BEGIN IF in3_reserve_pub = i.reserve_pub THEN ruuid3 = i.reserve_uuid; - out_reserve_found3 = FALSE; END IF; EXIT loop_reserve; END CASE; @@ -645,14 +592,6 @@ CREATE OR REPLACE FUNCTION exchange_do_batch8_reserves_insert( IN in7_wire_source_h_payto BYTEA, IN in7_payto_uri VARCHAR, IN in7_notify TEXT, - OUT out_reserve_found0 BOOLEAN, - OUT out_reserve_found1 BOOLEAN, - OUT out_reserve_found2 BOOLEAN, - OUT out_reserve_found3 BOOLEAN, - OUT out_reserve_found4 BOOLEAN, - OUT out_reserve_found5 BOOLEAN, - OUT out_reserve_found6 BOOLEAN, - OUT out_reserve_found7 BOOLEAN, OUT transaction_duplicate0 BOOLEAN, OUT transaction_duplicate1 BOOLEAN, OUT transaction_duplicate2 BOOLEAN, @@ -691,22 +630,6 @@ BEGIN transaction_duplicate5=TRUE; transaction_duplicate6=TRUE; transaction_duplicate7=TRUE; - out_reserve_found0 = TRUE; - out_reserve_found1 = TRUE; - out_reserve_found2 = TRUE; - out_reserve_found3 = TRUE; - out_reserve_found4 = TRUE; - out_reserve_found5 = TRUE; - out_reserve_found6 = TRUE; - out_reserve_found7 = TRUE; - ruuid0=0; - ruuid1=0; - ruuid2=0; - ruuid3=0; - ruuid4=0; - ruuid5=0; - ruuid6=0; - ruuid7=0; INSERT INTO wire_targets (wire_target_h_payto @@ -803,7 +726,6 @@ BEGIN IF in0_reserve_pub = i.reserve_pub THEN ruuid0 = i.reserve_uuid; - out_reserve_found0 = FALSE; CONTINUE loop_reserve; END IF; CONTINUE loop_k; @@ -812,7 +734,6 @@ BEGIN IF in1_reserve_pub = i.reserve_pub THEN ruuid1 = i.reserve_uuid; - out_reserve_found1 = FALSE; CONTINUE loop_reserve; END IF; CONTINUE loop_k; @@ -821,7 +742,6 @@ BEGIN IF in2_reserve_pub = i.reserve_pub THEN ruuid2 = i.reserve_uuid; - out_reserve_found2 = FALSE; CONTINUE loop_reserve; END IF; CONTINUE loop_k; @@ -830,7 +750,6 @@ BEGIN IF in3_reserve_pub = i.reserve_pub THEN ruuid3 = i.reserve_uuid; - out_reserve_found3 = FALSE; CONTINUE loop_reserve; END IF; CONTINUE loop_k; @@ -839,7 +758,6 @@ BEGIN IF in4_reserve_pub = i.reserve_pub THEN ruuid4 = i.reserve_uuid; - out_reserve_found4 = FALSE; CONTINUE loop_reserve; END IF; CONTINUE loop_k; @@ -848,7 +766,6 @@ BEGIN IF in5_reserve_pub = i.reserve_pub THEN ruuid5 = i.reserve_uuid; - out_reserve_found5 = FALSE; CONTINUE loop_reserve; END IF; CONTINUE loop_k; @@ -857,7 +774,6 @@ BEGIN IF in6_reserve_pub = i.reserve_pub THEN ruuid6 = i.reserve_uuid; - out_reserve_found6 = FALSE; CONTINUE loop_reserve; END IF; CONTINUE loop_k; @@ -865,7 +781,6 @@ BEGIN IF in7_reserve_pub = i.reserve_pub THEN ruuid7 = i.reserve_uuid; - out_reserve_found7 = FALSE; END IF; EXIT loop_reserve; END CASE; diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c index 2e29a1857..691c57d38 100644 --- a/src/exchangedb/pg_reserves_in_insert.c +++ b/src/exchangedb/pg_reserves_in_insert.c @@ -113,12 +113,12 @@ struct ReserveRecord * index @a index */ #define RR_RESULT_PARAM(rr,index) \ - GNUNET_PQ_result_spec_bool ("conflicted" TALER_S (index), \ - &rr[index].conflicts), \ GNUNET_PQ_result_spec_bool ("transaction_duplicate" TALER_S (index), \ &rr[index].transaction_duplicate), \ - GNUNET_PQ_result_spec_uint64 ("reserve_uuid" TALER_S (index), \ - &rr[index].reserve_uuid) + GNUNET_PQ_result_spec_allow_null ( \ + GNUNET_PQ_result_spec_uint64 ("reserve_uuid" TALER_S (index), \ + &rr[index].reserve_uuid), \ + &rr[index].conflicts) /** @@ -151,8 +151,7 @@ insert1 (struct PostgresClosure *pg, PREPARE (pg, "batch1_reserve_create", "SELECT " - " out_reserve_found0 AS conflicted0" - ",transaction_duplicate0 AS transaction_duplicate0" + " transaction_duplicate0 AS transaction_duplicate0" ",ruuid0 AS reserve_uuid0" " FROM exchange_do_batch_reserves_in_insert" " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);"); @@ -210,9 +209,7 @@ insert2 (struct PostgresClosure *pg, PREPARE (pg, "batch2_reserve_create", "SELECT" - " out_reserve_found0 AS conflicted0" - ",out_reserve_found1 AS conflicted1" - ",transaction_duplicate0" + " transaction_duplicate0" ",transaction_duplicate1" ",ruuid0 AS reserve_uuid0" ",ruuid1 AS reserve_uuid1" @@ -279,11 +276,7 @@ insert4 (struct PostgresClosure *pg, PREPARE (pg, "batch4_reserve_create", "SELECT" - " out_reserve_found0 AS conflicted0" - ",out_reserve_found1 AS conflicted1" - ",out_reserve_found2 AS conflicted2" - ",out_reserve_found3 AS conflicted3" - ",transaction_duplicate0" + " transaction_duplicate0" ",transaction_duplicate1" ",transaction_duplicate2" ",transaction_duplicate3" @@ -363,15 +356,7 @@ insert8 (struct PostgresClosure *pg, PREPARE (pg, "batch8_reserve_create", "SELECT" - " out_reserve_found0 AS conflicted0" - ",out_reserve_found1 AS conflicted1" - ",out_reserve_found2 AS conflicted2" - ",out_reserve_found3 AS conflicted3" - ",out_reserve_found4 AS conflicted4" - ",out_reserve_found5 AS conflicted5" - ",out_reserve_found6 AS conflicted6" - ",out_reserve_found7 AS conflicted7" - ",transaction_duplicate0" + " transaction_duplicate0" ",transaction_duplicate1" ",transaction_duplicate2" ",transaction_duplicate3" From 37dd5bed20f829a885c0f86437bf5afb2f30b1d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zg=C3=BCr=20Kesim?= Date: Sat, 22 Apr 2023 15:06:44 +0200 Subject: [PATCH 49/50] -added FIXME --- src/exchangedb/0002-refresh_revealed_coins.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/exchangedb/0002-refresh_revealed_coins.sql b/src/exchangedb/0002-refresh_revealed_coins.sql index 912e4bbbd..5fd315ba3 100644 --- a/src/exchangedb/0002-refresh_revealed_coins.sql +++ b/src/exchangedb/0002-refresh_revealed_coins.sql @@ -62,6 +62,9 @@ BEGIN ,table_name ,partition_suffix ); + -- + -- FIXME: Add comment for link_sig + -- PERFORM comment_partitioned_column( 'envelope of the new coin to be signed' ,'coin_ev' From 12681dfa1a4bd2f156a1d1402afa8c0e3250f163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zg=C3=BCr=20Kesim?= Date: Sat, 22 Apr 2023 15:39:02 +0200 Subject: [PATCH 50/50] WiP: age-withdraw, adjust schema and DB-handlers, cleanup FIXME's, 8/n --- .../taler-exchange-httpd_age-withdraw.c | 6 +- ...taler-exchange-httpd_age-withdraw_reveal.c | 64 +++++++++++++++---- .../0003-withdraw_age_commitments.sql | 9 +-- src/exchangedb/0003-withdraw_age_reveals.sql | 51 ++++++++++----- src/exchangedb/pg_get_age_withdraw_info.c | 8 +-- src/exchangedb/pg_insert_records_by_table.c | 54 ++++++++++------ src/exchangedb/pg_lookup_records_by_table.c | 54 +++++++++++----- src/exchangedb/pg_lookup_serial_by_table.c | 12 ++-- src/exchangedb/plugin_exchangedb_postgres.c | 1 + src/include/taler_exchangedb_plugin.h | 23 +++---- 10 files changed, 184 insertions(+), 98 deletions(-) diff --git a/src/exchange/taler-exchange-httpd_age-withdraw.c b/src/exchange/taler-exchange-httpd_age-withdraw.c index 170cd06a5..0978421a4 100644 --- a/src/exchange/taler-exchange-httpd_age-withdraw.c +++ b/src/exchange/taler-exchange-httpd_age-withdraw.c @@ -222,7 +222,6 @@ age_withdraw_transaction (void *cls, awc->kyc.ok = true; qs = TEH_plugin->do_age_withdraw (TEH_plugin->cls, &awc->commitment, - awc->now, &found, &balance_ok, &ruuid); @@ -312,7 +311,7 @@ TEH_handler_age_withdraw (struct TEH_RequestContext *rc, const json_t *root) { MHD_RESULT mhd_ret; - struct AgeWithdrawContext awc; + struct AgeWithdrawContext awc = {0}; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("reserve_sig", &awc.commitment.reserve_sig), @@ -321,12 +320,11 @@ TEH_handler_age_withdraw (struct TEH_RequestContext *rc, TALER_JSON_spec_amount ("amount", TEH_currency, &awc.commitment.amount_with_fee), - GNUNET_JSON_spec_uint32 ("max_age", + GNUNET_JSON_spec_uint16 ("max_age", &awc.commitment.max_age), GNUNET_JSON_spec_end () }; - memset (&awc, 0, sizeof (awc)); awc.commitment.reserve_pub = *reserve_pub; diff --git a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c index 50d524a2f..31ff57c6b 100644 --- a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c +++ b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c @@ -306,7 +306,7 @@ find_original_commitment ( break; case GNUNET_DB_STATUS_SOFT_ERROR: - /* FIXME:oec: Do we queue a result in this case or retry? */ + /* FIXME oec: Do we queue a result in this case or retry? */ default: GNUNET_break (0); /* should be impossible */ *result = TALER_MHD_reply_with_error (connection, @@ -564,7 +564,7 @@ verify_commitment_and_max_age ( { size_t k = 0; /* either 0 or 1, to index into coin_evs */ - for (size_t idx = 0; idx<3; idx++) + for (size_t idx = 0; idx j); + GNUNET_assert ((TALER_CNC_KAPPA - 1) * num_coins > j); secret = &disclosed_coin_secrets[j]; k++; @@ -614,7 +615,6 @@ verify_commitment_and_max_age ( { struct TALER_CoinPubHashP c_hash; struct TALER_PlanchetDetail detail; - struct TALER_BlindedCoinHashP bch; struct TALER_CoinSpendPrivateKeyP coin_priv; union TALER_DenominationBlindingKeyP bks; struct TALER_ExchangeWithdrawValues alg_values = { @@ -640,9 +640,7 @@ verify_commitment_and_max_age ( false, &alg_values.details. cs_values); - -#pragma message ("FIXME:oec: return value of needs handling!") - /* FIXME:oec: Handle error */ + /* FIXME Handle error? */ GNUNET_assert (TALER_EC_NONE == ec); } } @@ -692,10 +690,13 @@ verify_commitment_and_max_age ( return ret; } - GNUNET_CRYPTO_hash_context_read (hash_context, - &detail.blinded_planchet, - sizeof(detail.blinded_planchet)); } + + /* Continue the running hash of all coin hashes with the calculated + * hash-value of the current, disclosed coin */ + GNUNET_CRYPTO_hash_context_read (hash_context, + &bch, + sizeof(bch)); } } } @@ -722,6 +723,37 @@ verify_commitment_and_max_age ( } +/** + * @brief Signs and persists the undisclosed coins + * + * @param connection HTTP-connection to the client + * @param h_commitment_orig Original commitment + * @param num_coins Number of coins + * @param coin_evs The Hashes of the undisclosed, blinded coins, @a num_coins many + * @param denom_keys The array of denomination keys, @a num_coins. Needed to detect Clause-Schnorr-based denominations + * @param[out] result On error, a HTTP-response will be queued and result set accordingly + * @return GNUNET_OK on success, GNUNET_SYSERR otherwise + */ +static enum GNUNET_GenericReturnValue +sign_and_persist_blinded_coins ( + struct MHD_Connection *connection, + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment_orig, + const uint32_t num_coins, + const struct TALER_BlindedCoinHashP *coin_evs, + const struct TEH_DenominationKey *denom_keys, + MHD_RESULT *result) +{ + enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR; + + /* TODO[oec]: + * - sign the planchets + * - in a transaction: save the coins. + */ + #pragma message "FIXME[oec]: implement sign_and_persist_blinded_coins" + return ret; +} + + MHD_RESULT TEH_handler_age_withdraw_reveal ( struct TEH_RequestContext *rc, @@ -803,7 +835,15 @@ TEH_handler_age_withdraw_reveal ( &result)) break; - /* TODO:oec: sign the coins */ + /* Finally, sign and persist the coins */ + if (GNUNET_OK != sign_and_persist_blinded_coins ( + rc->connection, + &actx.commitment.h_commitment, + actx.num_coins, + actx.coin_evs, + actx.denom_keys, + &result)) + break; } while(0); diff --git a/src/exchangedb/0003-withdraw_age_commitments.sql b/src/exchangedb/0003-withdraw_age_commitments.sql index 6c153598d..b8451129a 100644 --- a/src/exchangedb/0003-withdraw_age_commitments.sql +++ b/src/exchangedb/0003-withdraw_age_commitments.sql @@ -33,7 +33,6 @@ BEGIN ',reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_pub)=32)' ',reserve_sig BYTEA CHECK (LENGTH(reserve_sig)=64)' ',noreveal_index INT4 NOT NULL' - ',timestamp INT8 NOT NULL' ') %s ;' ,table_name ,'PARTITION BY HASH (reserve_pub)' @@ -51,7 +50,7 @@ BEGIN ,partition_suffix ); PERFORM comment_partitioned_column( - 'The maximum age that the client commits to with this request' + 'The maximum age (in years) that the client commits to with this request' ,'max_age' ,table_name ,partition_suffix @@ -74,12 +73,6 @@ BEGIN ,table_name ,partition_suffix ); - PERFORM comment_partitioned_column( - 'Timestamp with the time when the withdraw-age request was received by the exchange' - ,'timestamp' - ,table_name - ,partition_suffix - ); END $$; diff --git a/src/exchangedb/0003-withdraw_age_reveals.sql b/src/exchangedb/0003-withdraw_age_reveals.sql index 3353d9367..af66eab75 100644 --- a/src/exchangedb/0003-withdraw_age_reveals.sql +++ b/src/exchangedb/0003-withdraw_age_reveals.sql @@ -14,22 +14,25 @@ -- TALER; see the file COPYING. If not, see -- -CREATE FUNCTION create_table_withdraw_age_reveals( +CREATE FUNCTION create_table_withdraw_age_revealed_coins( IN partition_suffix VARCHAR DEFAULT NULL ) RETURNS VOID LANGUAGE plpgsql AS $$ DECLARE - table_name VARCHAR DEFAULT 'withdraw_age_reveals'; + table_name VARCHAR DEFAULT 'withdraw_age_revealed_coins'; BEGIN PERFORM create_partitioned_table( 'CREATE TABLE %I' - '(withdraw_age_reveals_id BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE - ',h_commitment BYTEA NOT NULL CHECK (LENGTH(h_commitment)=32)' + '(withdraw_age_revealed_coins_id BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE + ',h_commitment BYTEA NOT NULL CHECK (LENGTH(h_commitment)=64)' ',freshcoin_index INT4 NOT NULL' ',denominations_serial INT8 NOT NULL' - ',h_coin_ev BYTEA CHECK (LENGTH(h_coin_ev)=32)' + ',coin_ev BYTEA NOT NULL' + ',h_coin_ev BYTEA CHECK (LENGTH(h_coin_ev)=64)' + ',ev_sig BYTEA NOT NULL' + ',ewv BYTEA NOT NULL' ') %s ;' ,table_name ,'PARTITION BY HASH (h_commitment)' @@ -59,29 +62,47 @@ BEGIN ,partition_suffix ); PERFORM comment_partitioned_column( - 'Hash of the blinded coins' + 'Envelope of the new coin to be signed' + ,'coin_ev' + ,table_name + ,partition_suffix + ); + PERFORM comment_partitioned_column( + 'Hash of the envelope of the new coin to be signed (for lookups)' ,'h_coin_ev' ,table_name ,partition_suffix ); + PERFORM comment_partitioned_column( + 'Exchange signature over the envelope' + ,'ev_sig' + ,table_name + ,partition_suffix + ); + PERFORM comment_partitioned_column( + 'Exchange contributed values in the creation of the fresh coin (see /csr)' + ,'ewv' + ,table_name + ,partition_suffix + ); END $$; -CREATE FUNCTION constrain_table_withdraw_age_reveals( +CREATE FUNCTION constrain_table_withdraw_age_revealed_coins( IN partition_suffix VARCHAR ) RETURNS void LANGUAGE plpgsql AS $$ DECLARE - table_name VARCHAR DEFAULT 'withdraw_age_reveals'; + table_name VARCHAR DEFAULT 'withdraw_age_revealed_coins'; BEGIN table_name = concat_ws('_', table_name, partition_suffix); EXECUTE FORMAT ( 'ALTER TABLE ' || table_name || - ' ADD CONSTRAINT ' || table_name || '_withdraw_age_reveals_id_key' - ' UNIQUE (withdraw_age_reveals_id);' + ' ADD CONSTRAINT ' || table_name || '_withdraw_age_revealed_coins_id_key' + ' UNIQUE (withdraw_age_revealed_coins_id);' ); EXECUTE FORMAT ( 'ALTER TABLE ' || table_name || @@ -91,12 +112,12 @@ BEGIN END $$; -CREATE FUNCTION foreign_table_withdraw_age_reveals() +CREATE FUNCTION foreign_table_withdraw_age_revealed_coins() RETURNS void LANGUAGE plpgsql AS $$ DECLARE - table_name VARCHAR DEFAULT 'withdraw_age_reveals'; + table_name VARCHAR DEFAULT 'withdraw_age_revealed_coins'; BEGIN EXECUTE FORMAT ( 'ALTER TABLE ' || table_name || @@ -121,17 +142,17 @@ INSERT INTO exchange_tables ,partitioned ,by_range) VALUES - ('withdraw_age_reveals' + ('withdraw_age_revealed_coins' ,'exchange-0003' ,'create' ,TRUE ,FALSE), - ('withdraw_age_reveals' + ('withdraw_age_revealed_coins' ,'exchange-0003' ,'constrain' ,TRUE ,FALSE), - ('withdraw_age_reveals' + ('withdraw_age_revealed_coins' ,'exchange-0003' ,'foreign' ,TRUE diff --git a/src/exchangedb/pg_get_age_withdraw_info.c b/src/exchangedb/pg_get_age_withdraw_info.c index 02ccc84ac..754b572c9 100644 --- a/src/exchangedb/pg_get_age_withdraw_info.c +++ b/src/exchangedb/pg_get_age_withdraw_info.c @@ -35,6 +35,7 @@ TEH_PG_get_age_withdraw_info ( { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), GNUNET_PQ_query_param_auto_from_type (ach), GNUNET_PQ_query_param_end }; @@ -45,14 +46,12 @@ TEH_PG_get_age_withdraw_info ( &awc->reserve_sig), GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", &awc->reserve_pub), - GNUNET_PQ_result_spec_uint32 ("max_age", + GNUNET_PQ_result_spec_uint16 ("max_age", &awc->max_age), TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", &awc->amount_with_fee), GNUNET_PQ_result_spec_uint32 ("noreveal_index", &awc->noreveal_index), - GNUNET_PQ_result_spec_timestamp ("timtestamp", - &awc->timestamp), GNUNET_PQ_result_spec_end }; @@ -70,9 +69,8 @@ TEH_PG_get_age_withdraw_info ( ",amount_with_fee_val" ",amount_with_fee_frac" ",noreveal_index" - ",timestamp" " FROM withdraw_age_commitments" - " WHERE h_commitment=$1;"); + " WHERE reserve_pub=$1 and h_commitment=$2;"); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "get_age_withdraw_info", params, diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c index 73e6ccda1..e790ec549 100644 --- a/src/exchangedb/pg_insert_records_by_table.c +++ b/src/exchangedb/pg_insert_records_by_table.c @@ -19,8 +19,9 @@ */ /** * @file exchangedb/pg_insert_records_by_table.c - * @brief insert_records_by_table implementation + * @brief replicate_records_by_table implementation * @author Christian Grothoff + * @author Özgür Kesim */ #include "platform.h" #include "taler_error_codes.h" @@ -28,6 +29,7 @@ #include "taler_pq_lib.h" #include "pg_insert_records_by_table.h" #include "pg_helper.h" +#include /** @@ -2110,40 +2112,56 @@ irbt_cb_table_withdraw_age_commitments (struct PostgresClosure *pg, /** - * Function called with withdraw_age_reveals records to insert into table. + * Function called with withdraw_age_revealed_coins records to insert into table. * * @param pg plugin context * @param td record to insert */ static enum GNUNET_DB_QueryStatus -irbt_cb_table_withdraw_age_reveals (struct PostgresClosure *pg, - const struct TALER_EXCHANGEDB_TableData *td) +irbt_cb_table_withdraw_age_revealed_coins (struct PostgresClosure *pg, + const struct + TALER_EXCHANGEDB_TableData *td) { + struct GNUNET_HashCode h_coin_ev; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&td->serial), -#if FIXME_OEC GNUNET_PQ_query_param_auto_from_type ( - &td->details.withdraw_age_reveals.h_commitment), -#endif + &td->details.withdraw_age_revealed_coins.h_commitment), GNUNET_PQ_query_param_uint32 ( - &td->details.withdraw_age_reveals.freshcoin_index), + &td->details.withdraw_age_revealed_coins.freshcoin_index), GNUNET_PQ_query_param_uint64 ( - &td->details.withdraw_age_reveals.denominations_serial), + &td->details.withdraw_age_revealed_coins.denominations_serial), + GNUNET_PQ_query_param_fixed_size ( + td->details.withdraw_age_revealed_coins.coin_ev, + td->details.withdraw_age_revealed_coins.coin_ev_size), + GNUNET_PQ_query_param_auto_from_type (&h_coin_ev), + TALER_PQ_query_param_blinded_denom_sig ( + &td->details.withdraw_age_revealed_coins.ev_sig), + TALER_PQ_query_param_exchange_withdraw_values ( + &td->details.withdraw_age_revealed_coins.ewv), GNUNET_PQ_query_param_end }; PREPARE (pg, - "insert_into_table_withdraw_age_reveals", - "INSERT INTO withdraw_age_reveals" - "(withdraw_age_reveals_id" - ",FIXME_OEC" + "insert_into_table_withdraw_age_revealed_coins", + "INSERT INTO withdraw_age_revealed_coins" + "(withdraw_age_revealed_coins_id" + ",h_commitment" ",freshcoin_index" ",denominations_serial" - ",FIXME_OEC" + ",coin_ev" + ",h_coin_ev" + ",ev_sig" + ",ewv" ") VALUES " - "($1, $2, $3, $4, $5);"); + "($1, $2, $3, $4, $5, $6, $7, $8);"); + + GNUNET_CRYPTO_hash (td->details.withdraw_age_revealed_coins.coin_ev, + td->details.withdraw_age_revealed_coins.coin_ev_size, + &h_coin_ev); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_withdraw_age_reveals", + "insert_into_table_withdraw_age_revealed_coins", params); } @@ -2298,8 +2316,8 @@ TEH_PG_insert_records_by_table (void *cls, case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS: rh = &irbt_cb_table_withdraw_age_commitments; break; - case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS: - rh = &irbt_cb_table_withdraw_age_reveals; + case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS: + rh = &irbt_cb_table_withdraw_age_revealed_coins; break; } if (NULL == rh) diff --git a/src/exchangedb/pg_lookup_records_by_table.c b/src/exchangedb/pg_lookup_records_by_table.c index 51894f23f..2e157360f 100644 --- a/src/exchangedb/pg_lookup_records_by_table.c +++ b/src/exchangedb/pg_lookup_records_by_table.c @@ -21,6 +21,7 @@ * @file exchangedb/pg_lookup_records_by_table.c * @brief implementation of lookup_records_by_table * @author Christian Grothoff + * @author Özgür Kesim */ #include "platform.h" #include "taler_error_codes.h" @@ -2807,9 +2808,6 @@ lrbt_cb_table_withdraw_age_commitments (void *cls, GNUNET_PQ_result_spec_uint32 ( "noreveal_index", &td.details.withdraw_age_commitments.noreveal_index), - GNUNET_PQ_result_spec_absolute_time ( - "timestamp", - &td.details.withdraw_age_commitments.timestamp), GNUNET_PQ_result_spec_end }; @@ -2830,40 +2828,48 @@ lrbt_cb_table_withdraw_age_commitments (void *cls, /** - * Function called with withdraw_age_reveals table entries. + * Function called with withdraw_age_revealed_coins 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_withdraw_age_reveals (void *cls, - PGresult *result, - unsigned int num_results) +lrbt_cb_table_withdraw_age_revealed_coins (void *cls, + PGresult *result, + unsigned int num_results) { struct LookupRecordsByTableContext *ctx = cls; struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS + .table = TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS }; for (unsigned int i = 0; i $1" " ORDER BY withdraw_age_commitment_id ASC;"); rh = &lrbt_cb_table_withdraw_age_commitments; break; - + case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS: + XPREPARE ("select_above_serial_by_table_withdraw_age_revealed_coins", + "SELECT" + " withdraw_age_revealed_coins_serial_id" + ",h_commitment" + ",freshcoin_index" + ",denominations_serial" + ",coin_ev" + ",h_coin_ev" + ",ev_sig" + ",ewv" + " FROM withdraw_age_revealed_coins" + " WHERE withdraw_age_revealed_coins_serial_id > $1" + " ORDER BY withdraw_age_revealed_coins_serial_id ASC;"); + rh = &lrbt_cb_table_withdraw_age_revealed_coins; + break; } if (NULL == rh) { diff --git a/src/exchangedb/pg_lookup_serial_by_table.c b/src/exchangedb/pg_lookup_serial_by_table.c index d2554af2e..c98b4539e 100644 --- a/src/exchangedb/pg_lookup_serial_by_table.c +++ b/src/exchangedb/pg_lookup_serial_by_table.c @@ -435,14 +435,14 @@ TEH_PG_lookup_serial_by_table (void *cls, " LIMIT 1;"); statement = "select_serial_by_table_withdraw_age_commitments"; break; - case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS: - XPREPARE ("select_serial_by_table_withdraw_age_reveals", + case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS: + XPREPARE ("select_serial_by_table_withdraw_age_revealed_coins", "SELECT" - " withdraw_age_reveals_id AS serial" - " FROM withdraw_age_reveals" - " ORDER BY withdraw_age_reveals_id DESC" + " withdraw_age_revealed_coins_id AS serial" + " FROM withdraw_age_revealed_coins" + " ORDER BY withdraw_age_revealed_coins_id DESC" " LIMIT 1;"); - statement = "select_serial_by_table_withdraw_age_reveals"; + statement = "select_serial_by_table_withdraw_age_revealed_coins"; break; } if (NULL == statement) diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 7e3aa2b1e..b3ebc7547 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -21,6 +21,7 @@ * @author Christian Grothoff * @author Sree Harsha Totakura * @author Marcello Stanisci + * @author Özgür Kesim */ #include "platform.h" #include diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index f60c3cf05..5b724953b 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -18,6 +18,7 @@ * @brief Low-level (statement-level) database access for the exchange * @author Florian Dold * @author Christian Grothoff + * @author Özgür Kesim */ #ifndef TALER_EXCHANGEDB_PLUGIN_H #define TALER_EXCHANGEDB_PLUGIN_H @@ -283,7 +284,7 @@ enum TALER_EXCHANGEDB_ReplicatedTable TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES, TALER_EXCHANGEDB_RT_PURSE_DELETION, TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS, - TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS, + TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS, }; @@ -764,11 +765,14 @@ struct TALER_EXCHANGEDB_TableData struct { struct TALER_AgeWithdrawCommitmentHashP h_commitment; - // FIXME-Oec: h_commitment --- schema says it is 32 byte, but it was 64 above??!? uint32_t freshcoin_index; uint64_t denominations_serial; - // FIXME-Oec: h_coin_ev --- schema says it is 32 byte!? - } withdraw_age_reveals; + void *coin_ev; + size_t coin_ev_size; + struct TALER_ExchangeWithdrawValues ewv; + // h_coin_ev omitted, to be recomputed! + struct TALER_BlindedDenominationSignature ev_sig; + } withdraw_age_revealed_coins; } details; @@ -1175,9 +1179,8 @@ struct TALER_EXCHANGEDB_AgeWithdrawCommitment /** * Maximum age that the coins are restricted to. - * FIXME-Oec: use 16-bit integer (see DB schema!) */ - uint32_t max_age; + uint16_t max_age; /** * The hash of the commitment of all n*kappa coins @@ -1206,11 +1209,6 @@ struct TALER_EXCHANGEDB_AgeWithdrawCommitment * The exchange's signature of the response. */ struct TALER_ExchangeSignatureP sig; - - /** - * Timestamp of the request being made - */ - struct GNUNET_TIME_Timestamp timestamp; }; @@ -3794,7 +3792,6 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param commitment corresponding commitment for the age-withdraw - * @param now current time (rounded) * @param[out] found set to true if the reserve was found * @param[out] balance_ok set to true if the balance was sufficient * @param[out] ruuid set to the reserve's UUID (reserves table row) @@ -3804,7 +3801,6 @@ struct TALER_EXCHANGEDB_Plugin (*do_age_withdraw)( void *cls, const struct TALER_EXCHANGEDB_AgeWithdrawCommitment *commitment, - struct GNUNET_TIME_Timestamp now, bool *found, bool *balance_ok, uint64_t *ruuid); @@ -5787,6 +5783,7 @@ struct TALER_EXCHANGEDB_Plugin * Insert record set into @a table. Used in exchange-auditor database * replication. * + memset (&awc, 0, sizeof (awc)); * @param cls closure * @param tb table data to insert * @return transaction status code, #GNUNET_DB_STATUS_HARD_ERROR if