aboutsummaryrefslogtreecommitdiff
path: root/src/exchangedb
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchangedb')
-rw-r--r--src/exchangedb/0002-reserves.sql4
-rw-r--r--src/exchangedb/0003-age_withdraw.sql (renamed from src/exchangedb/0003-age_withdraw_commitments.sql)46
-rw-r--r--src/exchangedb/0003-age_withdraw_reveals.sql125
-rw-r--r--src/exchangedb/Makefile.am3
-rw-r--r--src/exchangedb/exchange-0003.sql.in3
-rw-r--r--src/exchangedb/exchange_do_age_withdraw.sql181
-rw-r--r--src/exchangedb/exchange_do_batch_withdraw.sql48
-rw-r--r--src/exchangedb/exchange_do_batch_withdraw_insert.sql7
-rw-r--r--src/exchangedb/exchange_do_insert_kyc_attributes.sql2
-rw-r--r--src/exchangedb/pg_do_age_withdraw.c104
-rw-r--r--src/exchangedb/pg_do_age_withdraw.h55
-rw-r--r--src/exchangedb/pg_do_batch_withdraw.c13
-rw-r--r--src/exchangedb/pg_do_batch_withdraw.h6
-rw-r--r--src/exchangedb/pg_get_age_withdraw.c (renamed from src/exchangedb/pg_get_age_withdraw_info.c)66
-rw-r--r--src/exchangedb/pg_get_age_withdraw.h (renamed from src/exchangedb/pg_get_age_withdraw_info.h)14
-rw-r--r--src/exchangedb/pg_get_withdraw_info.c2
-rw-r--r--src/exchangedb/pg_insert_age_withdraw_reveal.c106
-rw-r--r--src/exchangedb/pg_insert_age_withdraw_reveal.h43
-rw-r--r--src/exchangedb/pg_insert_records_by_table.c90
-rw-r--r--src/exchangedb/pg_iterate_denominations.c5
-rw-r--r--src/exchangedb/pg_lookup_records_by_table.c118
-rw-r--r--src/exchangedb/pg_lookup_serial_by_table.c21
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c9
-rw-r--r--src/exchangedb/shard-0001.sql2
24 files changed, 537 insertions, 536 deletions
diff --git a/src/exchangedb/0002-reserves.sql b/src/exchangedb/0002-reserves.sql
index df5b6c3db..6ba7f604c 100644
--- a/src/exchangedb/0002-reserves.sql
+++ b/src/exchangedb/0002-reserves.sql
@@ -31,7 +31,7 @@ BEGIN
',current_balance_frac INT4 NOT NULL DEFAULT(0)'
',purses_active INT8 NOT NULL DEFAULT(0)'
',purses_allowed INT8 NOT NULL DEFAULT(0)'
- ',max_age INT4 NOT NULL DEFAULT(0)'
+ ',birthdate INT4 NOT NULL DEFAULT(0)'
',expiration_date INT8 NOT NULL'
',gc_date INT8 NOT NULL'
') %s ;'
@@ -82,7 +82,7 @@ BEGIN
);
PERFORM comment_partitioned_column(
'Birthday of the user in days after 1970, or 0 if user is an adult and is not subject to age restrictions'
- ,'max_age'
+ ,'birthdate'
,table_name
,partition_suffix
);
diff --git a/src/exchangedb/0003-age_withdraw_commitments.sql b/src/exchangedb/0003-age_withdraw.sql
index 3106a07ac..aed615da6 100644
--- a/src/exchangedb/0003-age_withdraw_commitments.sql
+++ b/src/exchangedb/0003-age_withdraw.sql
@@ -1,6 +1,6 @@
--
-- This file is part of TALER
--- Copyright (C) 2022 Taler Systems SA
+-- Copyright (C) 2023 Taler Systems SA
--
-- TALER is free software; you can redistribute it and/or modify it under the
-- terms of the GNU General Public License as published by the Free Software
@@ -13,26 +13,28 @@
-- You should have received a copy of the GNU General Public License along with
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
--
+-- @author Özgür Kesim
-CREATE FUNCTION create_table_age_withdraw_commitments(
+CREATE FUNCTION create_table_age_withdraw(
IN partition_suffix VARCHAR DEFAULT NULL
)
RETURNS VOID
LANGUAGE plpgsql
AS $$
DECLARE
- table_name VARCHAR DEFAULT 'age_withdraw_commitments';
+ table_name VARCHAR DEFAULT 'age_withdraw';
BEGIN
PERFORM create_partitioned_table(
'CREATE TABLE %I'
- '(age_withdraw_commitment_id BIGINT GENERATED BY DEFAULT AS IDENTITY'
+ '(age_withdraw_id BIGINT GENERATED BY DEFAULT AS IDENTITY'
',h_commitment BYTEA NOT NULL CONSTRAINT h_commitment_length CHECK(LENGTH(h_commitment)=64)'
',max_age SMALLINT NOT NULL CONSTRAINT max_age_positive CHECK(max_age>=0)'
',reserve_pub BYTEA NOT NULL CONSTRAINT reserve_pub_length CHECK(LENGTH(reserve_pub)=32)'
',reserve_sig BYTEA NOT NULL CONSTRAINT reserve_sig_length CHECK(LENGTH(reserve_sig)=64)'
',noreveal_index SMALLINT NOT NULL CONSTRAINT noreveal_index_positive CHECK(noreveal_index>=0)'
- ',denominations_serials INT8[] NOT NULL CONSTRAINT denominations_serial_array_length CHECK(cardinality(denominations_serials)=cardinality(denom_sigs))'
- ',denom_sigs BYTEA[] NOT NULL CONSTRAINT denom_sigs_array_length CHECK(cardinality(denom_sigs)=cardinality(denominations_serials))'
+ ',h_blind_evs BYTEA[] NOT NULL CONSTRAINT h_blind_evs_length CHECK(cardinality(h_blind_evs)=cardinality(denomination_serials))'
+ ',denom_serials INT8[] NOT NULL CONSTRAINT denominations_serial_array_length CHECK(cardinality(denom_serials)=cardinality(denom_sigs))'
+ ',denom_sigs BYTEA[] NOT NULL CONSTRAINT denom_sigs_array_length CHECK(cardinality(denom_sigs)=cardinality(denom_serials))'
') %s ;'
,table_name
,'PARTITION BY HASH (reserve_pub)'
@@ -40,7 +42,7 @@ BEGIN
);
PERFORM comment_partitioned_table(
'Commitments made when withdrawing coins with age restriction and the gamma value chosen by the exchange. '
- 'It also contains the blindly signed coins and related denominations.'
+ 'It also contains the blindly signed coins, their signatures and denominations.'
,table_name
,partition_suffix
);
@@ -76,12 +78,18 @@ BEGIN
);
PERFORM comment_partitioned_column(
'Array of references to the denominations'
- ,'denominations_serials'
+ ,'denom_serials'
,table_name
,partition_suffix
);
PERFORM comment_partitioned_column(
- 'Array of signatures over the blinded envelopes'
+ 'Array of the blinded envelopes of the chosen fresh coins, with value as given by the denomination in the corresponding slot in denom_serials'
+ ,'h_blind_evs'
+ ,table_name
+ ,partition_suffix
+ );
+ PERFORM comment_partitioned_column(
+ 'Array of signatures over each blinded envelope'
,'denom_sigs'
,table_name
,partition_suffix
@@ -90,14 +98,14 @@ END
$$;
-CREATE FUNCTION constrain_table_age_withdraw_commitments(
+CREATE FUNCTION constrain_table_age_withdraw(
IN partition_suffix VARCHAR
)
RETURNS void
LANGUAGE plpgsql
AS $$
DECLARE
- table_name VARCHAR DEFAULT 'age_withdraw_commitments';
+ table_name VARCHAR DEFAULT 'age_withdraw';
BEGIN
table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT (
@@ -111,25 +119,25 @@ BEGIN
);
EXECUTE FORMAT (
'ALTER TABLE ' || table_name ||
- ' ADD CONSTRAINT ' || table_name || '_age_withdraw_commitment_id_key'
- ' UNIQUE (age_withdraw_commitment_id);'
+ ' ADD CONSTRAINT ' || table_name || '_age_withdraw_id_key'
+ ' UNIQUE (age_withdraw_id);'
);
END
$$;
-CREATE FUNCTION foreign_table_age_withdraw_commitments()
+CREATE FUNCTION foreign_table_age_withdraw()
RETURNS void
LANGUAGE plpgsql
AS $$
DECLARE
- table_name VARCHAR DEFAULT 'age_withdraw_commitments';
+ table_name VARCHAR DEFAULT 'age_withdraw';
BEGIN
EXECUTE FORMAT (
'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub'
' FOREIGN KEY (reserve_pub)'
- ' REFERENCES reserves(reserve_pub) ON DELETE CASCADE;'
+ ' REFERENCES reserves(reserve_pub);' -- ON DELETE CASCADE;'
);
END
$$;
@@ -142,6 +150,6 @@ INSERT INTO exchange_tables
,partitioned
,by_range)
VALUES
- ('age_withdraw_commitments', 'exchange-0003', 'create', TRUE ,FALSE),
- ('age_withdraw_commitments', 'exchange-0003', 'constrain',TRUE ,FALSE),
- ('age_withdraw_commitments', 'exchange-0003', 'foreign', TRUE ,FALSE);
+ ('age_withdraw', 'exchange-0003', 'create', TRUE ,FALSE),
+ ('age_withdraw', 'exchange-0003', 'constrain',TRUE ,FALSE),
+ ('age_withdraw', 'exchange-0003', 'foreign', TRUE ,FALSE);
diff --git a/src/exchangedb/0003-age_withdraw_reveals.sql b/src/exchangedb/0003-age_withdraw_reveals.sql
deleted file mode 100644
index 2ab73f4b1..000000000
--- a/src/exchangedb/0003-age_withdraw_reveals.sql
+++ /dev/null
@@ -1,125 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2022 Taler Systems SA
---
--- TALER is free software; you can redistribute it and/or modify it under the
--- terms of the GNU General Public License as published by the Free Software
--- Foundation; either version 3, or (at your option) any later version.
---
--- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
--- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
--- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
---
--- You should have received a copy of the GNU General Public License along with
--- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
---
-
-CREATE FUNCTION create_table_age_withdraw_revealed_coins(
- IN partition_suffix VARCHAR DEFAULT NULL
-)
-RETURNS VOID
-LANGUAGE plpgsql
-AS $$
-DECLARE
- table_name VARCHAR DEFAULT 'age_withdraw_revealed_coins';
-BEGIN
- PERFORM create_partitioned_table(
- 'CREATE TABLE %I'
- '(age_withdraw_revealed_coins_id BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE
- ',h_commitment BYTEA NOT NULL CHECK (LENGTH(h_commitment)=64)'
- ',coin_index INT4 NOT NULL'
- ',h_coin_ev BYTEA CHECK (LENGTH(h_coin_ev)=64)'
- ') %s ;'
- ,table_name
- ,'PARTITION BY HASH (h_coin_ev)'
- ,partition_suffix
- );
- PERFORM comment_partitioned_table(
- 'Reveal of proofs of the correct age restriction after the commitment when withdrawing coins with age restriction'
- ,table_name
- ,partition_suffix
- );
- PERFORM comment_partitioned_column(
- 'Foreign key reference to the corresponding commitment'
- ,'h_commitment'
- ,table_name
- ,partition_suffix
- );
- PERFORM comment_partitioned_column(
- 'Index of the coin in the age-withdraw request, which is implicitly a batch request'
- ,'coin_index'
- ,table_name
- ,partition_suffix
- );
- PERFORM comment_partitioned_column(
- 'Hash of the envelope of the new coin to be signed (for lookups). The corresponding signatures are stores in age_withdraw_commitments.denom_sigs.'
- ,'h_coin_ev'
- ,table_name
- ,partition_suffix
- );
-END
-$$;
-
-CREATE FUNCTION constrain_table_age_withdraw_revealed_coins(
- IN partition_suffix VARCHAR
-)
-RETURNS void
-LANGUAGE plpgsql
-AS $$
-DECLARE
- table_name VARCHAR DEFAULT 'age_withdraw_revealed_coins';
-BEGIN
- table_name = concat_ws('_', table_name, partition_suffix);
-
- EXECUTE FORMAT (
- 'ALTER TABLE ' || table_name ||
- ' ADD CONSTRAINT ' || table_name || '_age_withdraw_revealed_coins_id_key'
- ' UNIQUE (age_withdraw_revealed_coins_id);'
- );
- EXECUTE FORMAT (
- 'ALTER TABLE ' || table_name ||
- ' ADD CONSTRAINT ' || table_name || '_freshcoin_index_and_h_commitment_uniqueness'
- ' UNIQUE (freshcoin_index, h_commitment);'
- );
-END
-$$;
-
-CREATE FUNCTION foreign_table_age_withdraw_revealed_coins()
-RETURNS void
-LANGUAGE plpgsql
-AS $$
-DECLARE
- table_name VARCHAR DEFAULT 'age_withdraw_revealed_coins';
-BEGIN
- EXECUTE FORMAT (
- 'ALTER TABLE ' || table_name ||
- ' ADD CONSTRAINT ' || table_name || '_foreign_h_commitment'
- ' FOREIGN KEY (h_commitment)'
- ' REFERENCES age_withdraw_commitments (h_commitment) ON DELETE CASCADE;'
- );
-END
-$$;
-
-
-INSERT INTO exchange_tables
- (name
- ,version
- ,action
- ,partitioned
- ,by_range)
- VALUES
- ('age_withdraw_revealed_coins'
- ,'exchange-0003'
- ,'create'
- ,TRUE
- ,FALSE),
- ('age_withdraw_revealed_coins'
- ,'exchange-0003'
- ,'constrain'
- ,TRUE
- ,FALSE),
- ('age_withdraw_revealed_coins'
- ,'exchange-0003'
- ,'foreign'
- ,TRUE
- ,FALSE);
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
index c2e87e5da..526f40b0d 100644
--- a/src/exchangedb/Makefile.am
+++ b/src/exchangedb/Makefile.am
@@ -128,7 +128,8 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
pg_drain_kyc_alert.h pg_drain_kyc_alert.c \
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_get_age_withdraw.c pg_get_age_withdraw.h \
+ pg_do_age_withdraw.h pg_do_age_withdraw.c \
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 \
diff --git a/src/exchangedb/exchange-0003.sql.in b/src/exchangedb/exchange-0003.sql.in
index 01733ea24..cd16bfbd4 100644
--- a/src/exchangedb/exchange-0003.sql.in
+++ b/src/exchangedb/exchange-0003.sql.in
@@ -25,8 +25,7 @@ SET search_path TO exchange;
#include "0003-aml_status.sql"
#include "0003-aml_staff.sql"
#include "0003-aml_history.sql"
-#include "0003-age_withdraw_commitments.sql"
-#include "0003-age_withdraw_reveals.sql"
+#include "0003-age_withdraw.sql"
COMMIT;
diff --git a/src/exchangedb/exchange_do_age_withdraw.sql b/src/exchangedb/exchange_do_age_withdraw.sql
new file mode 100644
index 000000000..3f1d682a4
--- /dev/null
+++ b/src/exchangedb/exchange_do_age_withdraw.sql
@@ -0,0 +1,181 @@
+--
+-- This file is part of TALER
+-- Copyright (C) 2023 Taler Systems SA
+--
+-- TALER is free software; you can redistribute it and/or modify it under the
+-- terms of the GNU General Public License as published by the Free Software
+-- Foundation; either version 3, or (at your option) any later version.
+--
+-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+-- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License along with
+-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+--
+-- @author Özgür Kesim
+
+CREATE OR REPLACE FUNCTION exchange_do_age_withdraw(
+ IN amount_val INT8,
+ IN amount_frac INT4,
+ IN rpub BYTEA,
+ IN rsig BYTEA,
+ IN now INT8,
+ IN min_reserve_gc INT8,
+ IN h_commitment BYTEA,
+ IN maximum_age_committed INT2, -- in years ϵ [0,1..)
+ IN noreveal_index INT2,
+ IN blinded_evs BYTEA[],
+ IN denom_serials INT8[],
+ IN denom_sigs BYTEA[],
+ OUT reserve_found BOOLEAN,
+ OUT balance_ok BOOLEAN,
+ OUT age_ok BOOLEAN,
+ OUT required_age INT2, -- in years ϵ [0,1..)
+ OUT conflict BOOLEAN,
+ OUT ruuid INT8)
+LANGUAGE plpgsql
+AS $$
+DECLARE
+ reserve_gc INT8;
+ reserve_val INT8;
+ reserve_frac INT4;
+ reserve_birthday INT4;
+ not_before date;
+ earliest_date date;
+BEGIN
+-- Shards: reserves by reserve_pub (SELECT)
+-- reserves_out (INSERT, with CONFLICT detection) by wih
+-- reserves by reserve_pub (UPDATE)
+-- reserves_in by reserve_pub (SELECT)
+-- wire_targets by wire_target_h_payto
+
+SELECT
+ current_balance_val
+ ,current_balance_frac
+ ,gc_date
+ ,birthday
+ ,reserve_uuid
+ INTO
+ reserve_val
+ ,reserve_frac
+ ,reserve_gc
+ ,reserve_birthday
+ ,ruuid
+ FROM exchange.reserves
+ WHERE reserves.reserve_pub=rpub;
+
+IF NOT FOUND
+THEN
+ -- reserve unknown
+ reserve_found=FALSE;
+ balance_ok=FALSE;
+ age_ok=FALSE;
+ required_age=0;
+ conflict=FALSE;
+ ruuid=2;
+ RETURN;
+END IF;
+
+
+-- Check age requirements
+IF ((maximum_age_committed = 0) OR (reserve_birthday = 0))
+THEN
+ -- No commitment to a non-zero age was provided or the reserve is marked as
+ -- having no age restriction. We can simply pass.
+ age_ok = OK;
+ELSE
+ not_before=date '1970-01-01' + reserve_birthday;
+ earliest_date = current_date - make_interval(maximum_age_committed);
+ --
+ -- 1970-01-01 + birthday == not_before now
+ -- | | |
+ -- <.......not allowed......>[<.....allowed range......>]
+ -- | | |
+ -- ____*_____________________*_________*________________* timeline
+ -- |
+ -- earliest_date ==
+ -- now - maximum_age_committed*year
+ --
+ IF (earliest_date < not_before)
+ THEN
+ reserve_found = TRUE;
+ balance_ok = FALSE;
+ age_ok = FALSE;
+ required_age = extract(year from age(not_before, current_date)) + 1;
+ RETURN;
+ END IF;
+END IF;
+
+-- Check reserve balance is sufficient.
+IF (reserve_val > amount_val)
+THEN
+ IF (reserve_frac >= amount_frac)
+ THEN
+ reserve_val=reserve_val - amount_val;
+ reserve_frac=reserve_frac - amount_frac;
+ ELSE
+ reserve_val=reserve_val - amount_val - 1;
+ reserve_frac=reserve_frac + 100000000 - amount_frac;
+ END IF;
+ELSE
+ IF (reserve_val = amount_val) AND (reserve_frac >= amount_frac)
+ THEN
+ reserve_val=0;
+ reserve_frac=reserve_frac - amount_frac;
+ ELSE
+ balance_ok=FALSE;
+ RETURN;
+ END IF;
+END IF;
+
+-- Calculate new expiration dates.
+min_reserve_gc=GREATEST(min_reserve_gc,reserve_gc);
+
+-- Update reserve balance.
+UPDATE reserves SET
+ gc_date=min_reserve_gc
+ ,current_balance_val=reserve_val
+ ,current_balance_frac=reserve_frac
+WHERE
+ reserves.reserve_pub=rpub;
+
+reserve_found=TRUE;
+balance_ok=TRUE;
+
+-- Write the commitment into the age-withdraw table
+INSERT INTO exchange.age_withdraw
+ (h_commitment
+ ,max_age
+ ,reserve_pub
+ ,reserve_sig
+ ,noreveal_index
+ ,denomination_serials
+ ,h_blind_evs
+ ,denom_sigs)
+VALUES
+ (h_commitment
+ ,maximum_age_committed
+ ,rpub
+ ,rsig
+ ,noreveal_index
+ ,denom_serials
+ ,blinded_evs
+ ,denom_sigs)
+ON CONFLICT DO NOTHING;
+
+IF NOT FOUND
+THEN
+ -- Signal a conflict so that the caller
+ -- can fetch the actual data from the DB.
+ conflict=TRUE;
+ RETURN;
+ELSE
+ conflict=FALSE;
+END IF;
+
+END $$;
+
+COMMENT ON FUNCTION exchange_do_age_withdraw(INT8, INT4, BYTEA, BYTEA, INT8, INT8, BYTEA, INT2, INT2, BYTEA[], INT8[], BYTEA[])
+ IS 'Checks whether the reserve has sufficient balance for an age-withdraw operation (or the request is repeated and was previously approved) and that age requirements are met. If so updates the database with the result. Includes storing the blinded planchets and denomination signatures, or signaling conflict';
+
diff --git a/src/exchangedb/exchange_do_batch_withdraw.sql b/src/exchangedb/exchange_do_batch_withdraw.sql
index 64777bb38..6d3b9a11d 100644
--- a/src/exchangedb/exchange_do_batch_withdraw.sql
+++ b/src/exchangedb/exchange_do_batch_withdraw.sql
@@ -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
@@ -13,6 +13,8 @@
-- You should have received a copy of the GNU General Public License along with
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
--
+-- @author Christian Grothoff
+-- @author Özgür Kesim
CREATE OR REPLACE FUNCTION exchange_do_batch_withdraw(
IN amount_val INT8,
@@ -20,18 +22,20 @@ CREATE OR REPLACE FUNCTION exchange_do_batch_withdraw(
IN rpub BYTEA,
IN now INT8,
IN min_reserve_gc INT8,
--- TODO[oec]: add [IN] parameter for maximum age and [OUT] parameter for required age
+ IN do_age_check BOOLEAN,
OUT reserve_found BOOLEAN,
OUT balance_ok BOOLEAN,
- OUT ruuid INT8)
+ OUT age_ok BOOLEAN,
+ OUT allowed_maximum_age INT4, -- in years
+ OUT ruuid INT8
LANGUAGE plpgsql
AS $$
DECLARE
reserve_gc INT8;
-DECLARE
reserve_val INT8;
-DECLARE
reserve_frac INT4;
+ reserve_birthday INT4;
+ not_before date;
BEGIN
-- Shards: reserves by reserve_pub (SELECT)
-- reserves_out (INSERT, with CONFLICT detection) by wih
@@ -44,12 +48,13 @@ SELECT
current_balance_val
,current_balance_frac
,gc_date
+ ,birthday
,reserve_uuid
--- TODO[oec]: get age requirements
INTO
reserve_val
,reserve_frac
,reserve_gc
+ ,reserve_birthday
,ruuid
FROM exchange.reserves
WHERE reserves.reserve_pub=rpub;
@@ -59,11 +64,32 @@ THEN
-- reserve unknown
reserve_found=FALSE;
balance_ok=FALSE;
+ age_ok=FALSE;
+ allowed_maximum_age=0;
ruuid=2;
RETURN;
END IF;
--- TODO[oec]: check age requirements
+
+-- Check if age requirements are present
+IF ((NOT do_age_check) OR (reserve_birthday = 0))
+THEN
+ age_ok = OK;
+ required_age = 0;
+ELSE
+ -- Age requirements are formally not met: The exchange is setup to support
+ -- age restrictions (do_age_check == TRUE) and the reserve has a
+ -- birthday set (reserve_birthday != 0), but the client called the
+ -- batch-withdraw endpoint instead of the age-withdraw endpoint, which it
+ -- should have.
+ not_before=date '1970-01-01' + reserve_birthday;
+ allowed_maximum_age = extract(year from age(current_date, not_before));
+
+ reserve_found=TRUE;
+ balance_ok=FALSE;
+ age_ok = FALSE;
+ RETURN;
+END IF;
-- Check reserve balance is sufficient.
IF (reserve_val > amount_val)
@@ -82,7 +108,6 @@ ELSE
reserve_val=0;
reserve_frac=reserve_frac - amount_frac;
ELSE
- reserve_found=TRUE;
balance_ok=FALSE;
RETURN;
END IF;
@@ -104,9 +129,6 @@ balance_ok=TRUE;
END $$;
--- TODO[oec]: Update comment re: age requirements are implemented
-COMMENT ON FUNCTION exchange_do_batch_withdraw(INT8, INT4, BYTEA, INT8, INT8)
- IS 'Checks whether the reserve has sufficient balance for a withdraw operation (or the request is repeated and was previously approved) and if so updates the database with the result. Excludes storing the planchets.';
-
-
+COMMENT ON FUNCTION exchange_do_batch_withdraw(INT8, INT4, BYTEA, INT8, INT8, BOOLEAN)
+ IS 'Checks whether the reserve has sufficient balance for a withdraw operation (or the request is repeated and was previously approved) and that age requirements are formally met. If so updates the database with the result. Excludes storing the planchets.';
diff --git a/src/exchangedb/exchange_do_batch_withdraw_insert.sql b/src/exchangedb/exchange_do_batch_withdraw_insert.sql
index 27378674f..b580f6fb7 100644
--- a/src/exchangedb/exchange_do_batch_withdraw_insert.sql
+++ b/src/exchangedb/exchange_do_batch_withdraw_insert.sql
@@ -14,14 +14,11 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
--
-
--- TODO[oec]: add min. age requirements handling
-
CREATE OR REPLACE FUNCTION exchange_do_batch_withdraw_insert(
IN cs_nonce BYTEA,
IN amount_val INT8,
IN amount_frac INT4,
- IN h_denom_pub BYTEA,
+ IN h_denom_pub BYTEA, -- FIXME: denom_serials should really be a parameter to this FUNCTION.
IN ruuid INT8,
IN reserve_sig BYTEA,
IN h_coin_envelope BYTEA,
@@ -45,6 +42,8 @@ out_denom_unknown=TRUE;
out_conflict=TRUE;
out_nonce_reuse=TRUE;
+-- FIXME: denom_serials should really be a parameter to this FUNCTION.
+
SELECT denominations_serial
INTO denom_serial
FROM exchange.denominations
diff --git a/src/exchangedb/exchange_do_insert_kyc_attributes.sql b/src/exchangedb/exchange_do_insert_kyc_attributes.sql
index f1959a66e..949181399 100644
--- a/src/exchangedb/exchange_do_insert_kyc_attributes.sql
+++ b/src/exchangedb/exchange_do_insert_kyc_attributes.sql
@@ -61,7 +61,7 @@ UPDATE exchange.legitimization_processes
out_ok = FOUND;
-- FIXME-Oec: update exchange reserve table to store in_birthday here!
--- UPDATE exchange.reserves SET max_age=in_birthday WHERE reserve_pub=X;
+-- UPDATE exchange.reserves SET birthday=in_birthday WHERE reserve_pub=X;
IF in_require_aml
THEN
diff --git a/src/exchangedb/pg_do_age_withdraw.c b/src/exchangedb/pg_do_age_withdraw.c
new file mode 100644
index 000000000..8a93ef8df
--- /dev/null
+++ b/src/exchangedb/pg_do_age_withdraw.c
@@ -0,0 +1,104 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/pg_do_batch_withdraw.c
+ * @brief Implementation of the do_batch_withdraw function for Postgres
+ * @author Özgür Kesim
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_exchangedb_plugin.h"
+#include "taler_pq_lib.h"
+#include "taler_pq_lib.h"
+#include "pg_do_batch_withdraw.h"
+#include "pg_helper.h"
+#include <gnunet/gnunet_time_lib.h>
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_age_withdraw (
+ void *cls,
+ const struct TALER_EXCHANGEDB_AgeWithdraw *commitment,
+ struct GNUNET_TIME_Timestamp now,
+ bool *found,
+ bool *balance_ok,
+ bool *age_ok,
+ uint16_t *required_age,
+ bool *conflict,
+ uint64_t *ruuid)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_TIME_Timestamp gc;
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (&commitment->amount_with_fee),
+ GNUNET_PQ_query_param_auto_from_type (&commitment->reserve_pub),
+ GNUNET_PQ_query_param_auto_from_type (&commitment->reserve_sig),
+ GNUNET_PQ_query_param_timestamp (&now),
+ GNUNET_PQ_query_param_timestamp (&gc),
+ GNUNET_PQ_query_param_auto_from_type (&commitment->h_commitment),
+ GNUNET_PQ_query_param_uint16 (&commitment->max_age),
+ GNUNET_PQ_query_param_uint16 (&commitment->noreveal_index),
+ GNUNET_PQ_query_param_array_auto_from_type (commitment->num_coins,
+ commitment->h_coin_evs,
+ pg->conn),
+ GNUNET_PQ_query_param_array_uint64 (commitment->num_coins,
+ commitment->denom_serials,
+ pg->conn),
+ GNUNET_PQ_query_param_array_auto_from_type (commitment->num_coins,
+ commitment->denom_sigs,
+ pg->conn),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("reserve_found",
+ found),
+ GNUNET_PQ_result_spec_bool ("balance_ok",
+ balance_ok),
+ GNUNET_PQ_result_spec_bool ("age_ok",
+ age_ok),
+ GNUNET_PQ_result_spec_uint16 ("required_age",
+ required_age),
+ GNUNET_PQ_result_spec_bool ("conflict",
+ conflict),
+ GNUNET_PQ_result_spec_uint64 ("ruuid",
+ ruuid),
+ GNUNET_PQ_result_spec_end
+ };
+
+ gc = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_add (now.abs_time,
+ pg->legal_reserve_expiration_time));
+
+
+ /* Used in #postgres_do_age_withdraw() to
+ update the reserve balance and check its status */
+ PREPARE (pg,
+ "call_age_withdraw",
+ "SELECT "
+ " reserve_found"
+ ",balance_ok"
+ ",age_ok"
+ ",required_age"
+ ",conflict"
+ ",ruuid"
+ " FROM exchange_do_batch_withdraw"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_age_withdraw",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/pg_do_age_withdraw.h b/src/exchangedb/pg_do_age_withdraw.h
new file mode 100644
index 000000000..5beb3133c
--- /dev/null
+++ b/src/exchangedb/pg_do_age_withdraw.h
@@ -0,0 +1,55 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/pg_do_age_withdraw.h
+ * @brief implementation of the do_age_withdraw function for Postgres
+ * @author Özgür Kesim
+ */
+#ifndef PG_DO_AGE_WITHDRAW_H
+#define PG_DO_AGE_WITHDRAW_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Perform reserve update as part of an age-withdraw operation, checking for
+ * sufficient balance and fulfillment of age requirements. Finally persisting
+ * the withdrawal details.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param commitment the commitment with all parameters
+ * @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] age_ok set to true if no age requirements are present on the reserve
+ * @param[out] required_age if @e age_ok is false, set to the maximum allowed age when withdrawing from this reserve
+ * @param[out] conflict set to true if there already is an entry in the database for the given pair (h_commitment, reserve_pub)
+ * @param[out] ruuid set to the reserve's UUID (reserves table row)
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_age_withdraw (
+ void *cls,
+ const struct TALER_EXCHANGEDB_AgeWithdraw *commitment,
+ const struct GNUNET_TIME_Timestamp now,
+ bool *found,
+ bool *balance_ok,
+ bool *age_ok,
+ uint16_t *required_age,
+ bool *conflict,
+ uint64_t *ruuid);
+
+#endif
diff --git a/src/exchangedb/pg_do_batch_withdraw.c b/src/exchangedb/pg_do_batch_withdraw.c
index d93caa15e..6b5816733 100644
--- a/src/exchangedb/pg_do_batch_withdraw.c
+++ b/src/exchangedb/pg_do_batch_withdraw.c
@@ -17,6 +17,7 @@
* @file exchangedb/pg_do_batch_withdraw.c
* @brief Implementation of the do_batch_withdraw function for Postgres
* @author Christian Grothoff
+ * @author Özgür Kesim
*/
#include "platform.h"
#include "taler_error_codes.h"
@@ -31,10 +32,12 @@ TEH_PG_do_batch_withdraw (
void *cls,
struct GNUNET_TIME_Timestamp now,
const struct TALER_ReservePublicKeyP *reserve_pub,
- /* TODO[oec]: add parameter for maximum age and [out]parameter for required age */
const struct TALER_Amount *amount,
+ bool do_age_check,
bool *found,
bool *balance_ok,
+ bool *age_ok,
+ uint16_t *allowed_maximum_age,
uint64_t *ruuid)
{
struct PostgresClosure *pg = cls;
@@ -42,6 +45,7 @@ TEH_PG_do_batch_withdraw (
struct GNUNET_PQ_QueryParam params[] = {
TALER_PQ_query_param_amount (amount),
GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_bool (do_age_check),
GNUNET_PQ_query_param_timestamp (&now),
GNUNET_PQ_query_param_timestamp (&gc),
GNUNET_PQ_query_param_end
@@ -51,6 +55,10 @@ TEH_PG_do_batch_withdraw (
found),
GNUNET_PQ_result_spec_bool ("balance_ok",
balance_ok),
+ GNUNET_PQ_result_spec_bool ("age_ok",
+ age_ok),
+ GNUNET_PQ_result_spec_uint16 ("allowed_maximum_age",
+ allowed_maximum_age),
GNUNET_PQ_result_spec_uint64 ("ruuid",
ruuid),
GNUNET_PQ_result_spec_end
@@ -68,8 +76,9 @@ TEH_PG_do_batch_withdraw (
"SELECT "
" reserve_found"
",balance_ok"
+ ",age_ok"
+ ",required_age"
",ruuid"
- /* TODO[oec]: add parameter for maximum age and [out] parameter for required age */
" FROM exchange_do_batch_withdraw"
" ($1,$2,$3,$4,$5);");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
diff --git a/src/exchangedb/pg_do_batch_withdraw.h b/src/exchangedb/pg_do_batch_withdraw.h
index ee4bf2937..d0b865746 100644
--- a/src/exchangedb/pg_do_batch_withdraw.h
+++ b/src/exchangedb/pg_do_batch_withdraw.h
@@ -33,8 +33,11 @@
* @param now current time (rounded)
* @param reserve_pub public key of the reserve to debit
* @param amount total amount to withdraw
+ * @param age_check_required if true, fail if age requirements are set on the reserve
* @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] age_ok set to true if no age requirements are present on the reserve
+ * @param[out] allowed_maximum_age if @e age_ok is false, set to the maximum allowed age when withdrawing from this reserve (client needs to call age-withdraw)
* @param[out] ruuid set to the reserve's UUID (reserves table row)
* @return query execution status
*/
@@ -44,8 +47,11 @@ TEH_PG_do_batch_withdraw (
struct GNUNET_TIME_Timestamp now,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *amount,
+ bool age_check_required,
bool *found,
bool *balance_ok,
+ bool *age_ok,
+ uint16_t *allowed_maximum_age,
uint64_t *ruuid);
#endif
diff --git a/src/exchangedb/pg_get_age_withdraw_info.c b/src/exchangedb/pg_get_age_withdraw.c
index f4a68b377..5e123ca9a 100644
--- a/src/exchangedb/pg_get_age_withdraw_info.c
+++ b/src/exchangedb/pg_get_age_withdraw.c
@@ -14,24 +14,24 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
- * @file exchangedb/pg_get_age_withdraw_info.c
- * @brief Implementation of the get_age_withdraw_info function for Postgres
+ * @file exchangedb/pg_get_age_withdraw.c
+ * @brief Implementation of the get_age_withdraw function for Postgres
* @author Özgür Kesim
*/
#include "platform.h"
#include "taler_error_codes.h"
#include "taler_dbevents.h"
#include "taler_pq_lib.h"
-#include "pg_get_age_withdraw_info.h"
+#include "pg_get_age_withdraw.h"
#include "pg_helper.h"
enum GNUNET_DB_QueryStatus
-TEH_PG_get_age_withdraw_info (
+TEH_PG_get_age_withdraw (
void *cls,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_AgeWithdrawCommitmentHashP *ach,
- struct TALER_EXCHANGEDB_AgeWithdrawCommitment *awc)
+ struct TALER_EXCHANGEDB_AgeWithdraw *aw)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
@@ -41,26 +41,44 @@ TEH_PG_get_age_withdraw_info (
};
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("h_commitment",
- &awc->h_commitment),
+ &aw->h_commitment),
GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
- &awc->reserve_sig),
+ &aw->reserve_sig),
GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &awc->reserve_pub),
+ &aw->reserve_pub),
GNUNET_PQ_result_spec_uint16 ("max_age",
- &awc->max_age),
+ &aw->max_age),
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &awc->amount_with_fee),
- GNUNET_PQ_result_spec_uint32 ("noreveal_index",
- &awc->noreveal_index),
+ &aw->amount_with_fee),
+ GNUNET_PQ_result_spec_uint16 ("noreveal_index",
+ &aw->noreveal_index),
+ GNUNET_PQ_result_spec_array_fixed_size (
+ pg->conn,
+ "h_coin_evs",
+ sizeof(struct TALER_BlindedPlanchet),
+ &aw->num_coins,
+ (void **) &aw->h_coin_evs),
+ GNUNET_PQ_result_spec_array_fixed_size (
+ pg->conn,
+ "denom_sigs",
+ sizeof(struct TALER_DenominationSignature),
+ NULL,
+ (void **) &aw->denom_sigs),
+ GNUNET_PQ_result_spec_array_fixed_size (
+ pg->conn,
+ "denom_pub_hashes",
+ sizeof(struct TALER_DenominationHashP),
+ NULL,
+ (void **) &aw->denom_pub_hashes),
GNUNET_PQ_result_spec_end
};
- /* Used in #postgres_get_age_withdraw_info() to
- locate the response for a /reserve/$RESERVE_PUB/age-withdraw request using
- the hash of the blinded message. Used to make sure
- /reserve/$RESERVE_PUB/age-withdraw requests are idempotent. */
+ /* Used in #postgres_get_age_withdraw() to
+ locate the response for a /reserve/$RESERVE_PUB/age-withdraw request
+ using the hash of the blinded message. Also needed to ensure
+ idempotency of /reserve/$RESERVE_PUB/age-withdraw requests. */
PREPARE (pg,
- "get_age_withdraw_info",
+ "get_age_withdraw",
"SELECT"
" h_commitment"
",reserve_sig"
@@ -69,10 +87,20 @@ TEH_PG_get_age_withdraw_info (
",amount_with_fee_val"
",amount_with_fee_frac"
",noreveal_index"
- " FROM age_withdraw_commitments"
+ ",h_coin_evs"
+ ",denom_sigs"
+ ",ARRAY("
+ " SELECT denominations.denom_pub_hash FROM ("
+ " SELECT UNNEST(denomination_serials) AS id,"
+ " generate_subscripts(denominations_serials, 1) AS nr" /* for order */
+ " ) AS denoms"
+ " LEFT JOIN denominations ON denominations.denominations_serial=denoms.id"
+ ") AS denom_pub_hashes"
+ " FROM age_withdraw"
" WHERE reserve_pub=$1 and h_commitment=$2;");
+
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_age_withdraw_info",
+ "get_age_withdraw",
params,
rs);
}
diff --git a/src/exchangedb/pg_get_age_withdraw_info.h b/src/exchangedb/pg_get_age_withdraw.h
index 0844b1a19..2257aa43c 100644
--- a/src/exchangedb/pg_get_age_withdraw_info.h
+++ b/src/exchangedb/pg_get_age_withdraw.h
@@ -14,12 +14,12 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
- * @file exchangedb/pg_get_age_withdraw_info.h
- * @brief implementation of the get_age_withdraw_info function for Postgres
+ * @file exchangedb/pg_get_age_withdraw.h
+ * @brief implementation of the get_age_withdraw function for Postgres
* @author Özgür KESIM
*/
-#ifndef PG_GET_AGE_WITHDRAW_INFO_H
-#define PG_GET_AGE_WITHDRAW_INFO_H
+#ifndef PG_GET_AGE_WITHDRAW_H
+#define PG_GET_AGE_WITHDRAW_H
#include "taler_util.h"
#include "taler_json_lib.h"
@@ -33,13 +33,13 @@
* @param cls the @e cls of this struct with the plugin-specific state
* @param reserve_pub public key of the reserve for which the age-withdraw request is made
* @param ach hash that uniquely identifies the age-withdraw operation
- * @param[out] awc corresponding details of the previous age-withdraw request if an entry was found
+ * @param[out] aw corresponding details of the previous age-withdraw request if an entry was found
* @return statement execution status
*/
enum GNUNET_DB_QueryStatus
-TEH_PG_get_age_withdraw_info (
+TEH_PG_get_age_withdraw (
void *cls,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_AgeWithdrawCommitmentHashP *ach,
- struct TALER_EXCHANGEDB_AgeWithdrawCommitment *awc);
+ struct TALER_EXCHANGEDB_AgeWithdraw *aw);
#endif
diff --git a/src/exchangedb/pg_get_withdraw_info.c b/src/exchangedb/pg_get_withdraw_info.c
index d6a180b00..08f950596 100644
--- a/src/exchangedb/pg_get_withdraw_info.c
+++ b/src/exchangedb/pg_get_withdraw_info.c
@@ -27,7 +27,7 @@
enum GNUNET_DB_QueryStatus
-TEH_PG_get_withdraw_info (
+TEH_PG_get_withdraw (
void *cls,
const struct TALER_BlindedCoinHashP *bch,
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
diff --git a/src/exchangedb/pg_insert_age_withdraw_reveal.c b/src/exchangedb/pg_insert_age_withdraw_reveal.c
deleted file mode 100644
index ebba7ebbc..000000000
--- a/src/exchangedb/pg_insert_age_withdraw_reveal.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2023 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_age_withdraw_reveal.c
- * @brief Implementation of the insert_age_withdraw_reveal function for Postgres
- * @author Özgür Kesim
- */
-#include "platform.h"
-#include "taler_error_codes.h"
-#include "taler_dbevents.h"
-#include "taler_pq_lib.h"
-#include "pg_insert_refresh_reveal.h"
-#include "pg_helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TEH_PG_insert_age_withdraw_reveal (
- void *cls,
- /*TODO:oec*/
- )
-{
- struct PostgresClosure *pg = cls;
-
- if (TALER_CNC_KAPPA != num_tprivs + 1)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- /* TODO */
-#if 0
- PREPARE (pg,
- "insert_age_withdraw_revealed_coin",
- "INSERT INTO age_withdraw_reveals "
- "(h_commitment "
- ",freshcoin_index "
- ",denominations_serial "
- ",h_coin_ev "
- ",ev_sig"
- ") SELECT $1, $2, $3, "
- " denominations_serial, $5, $6, $7, $8"
- " FROM denominations"
- " WHERE denom_pub_hash=$4"
-
- " ON CONFLICT DO NOTHING;");
- for (uint32_t i = 0; i<num_rrcs; i++)
- {
- const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&melt_serial_id),
- GNUNET_PQ_query_param_uint32 (&i),
- GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig),
- GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub),
- TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet),
- TALER_PQ_query_param_exchange_withdraw_values (&rrc->exchange_vals),
- GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash),
- TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_refresh_revealed_coin",
- params);
- if (0 > qs)
- return qs;
- }
-
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&melt_serial_id),
- GNUNET_PQ_query_param_auto_from_type (tp),
- GNUNET_PQ_query_param_fixed_size (
- tprivs,
- num_tprivs * sizeof (struct TALER_TransferPrivateKeyP)),
- GNUNET_PQ_query_param_end
- };
-
- /* Used in #postgres_insert_refresh_reveal() to store the transfer
- keys we learned */
- PREPARE (pg,
- "insert_refresh_transfer_keys",
- "INSERT INTO refresh_transfer_keys "
- "(melt_serial_id"
- ",transfer_pub"
- ",transfer_privs"
- ") VALUES ($1, $2, $3)"
- " ON CONFLICT DO NOTHING;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_refresh_transfer_keys",
- params);
- }
-#endif
-}
diff --git a/src/exchangedb/pg_insert_age_withdraw_reveal.h b/src/exchangedb/pg_insert_age_withdraw_reveal.h
deleted file mode 100644
index 1ce05d597..000000000
--- a/src/exchangedb/pg_insert_age_withdraw_reveal.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2023 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_age_withdraw_reveal.h
- * @brief implementation of the insert_age_withdraw_reveal function for Postgres
- * @author Özgür Kesim
- */
-#ifndef PG_INSERT_AGE_WITHDRAW_REVEAL_H
-#define PG_INSERT_AGE_WITHDRAW_REVEAL_H
-
-#include "taler_util.h"
-#include "taler_json_lib.h"
-#include "taler_exchangedb_plugin.h"
-
-/**
- * @brief Store in the database which coin(s) the wallet wanted to create in a
- * given age-withdraw operation and all of the other information we learned or
- * created in the /age-withdraw/reveal step.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * TODO:oec
- * @return query status for the transaction
- */
-enum GNUNET_DB_QueryStatus
-TEH_PG_insert_refresh_reveal (
- void *cls,
- /* TODO: oec */
- );
-
-#endif
diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c
index 9baaf3b1a..a8b71759c 100644
--- a/src/exchangedb/pg_insert_records_by_table.c
+++ b/src/exchangedb/pg_insert_records_by_table.c
@@ -2057,38 +2057,37 @@ irbt_cb_table_purse_deletion (struct PostgresClosure *pg,
/**
- * Function called with age_withdraw_commitments records to insert into table.
+ * Function called with age_withdraw records to insert into table.
*
* @param pg plugin context
* @param td record to insert
*/
static enum GNUNET_DB_QueryStatus
-irbt_cb_table_age_withdraw_commitments (struct PostgresClosure *pg,
- const struct
- TALER_EXCHANGEDB_TableData *td)
+irbt_cb_table_age_withdraw (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.age_withdraw_commitments.h_commitment),
+ &td->details.age_withdraw.h_commitment),
TALER_PQ_query_param_amount (
- &td->details.age_withdraw_commitments.amount_with_fee),
+ &td->details.age_withdraw.amount_with_fee),
GNUNET_PQ_query_param_uint16 (
- &td->details.age_withdraw_commitments.max_age),
+ &td->details.age_withdraw.max_age),
GNUNET_PQ_query_param_auto_from_type (
- &td->details.age_withdraw_commitments.reserve_pub),
+ &td->details.age_withdraw.reserve_pub),
GNUNET_PQ_query_param_auto_from_type (
- &td->details.age_withdraw_commitments.reserve_sig),
+ &td->details.age_withdraw.reserve_sig),
GNUNET_PQ_query_param_uint32 (
- &td->details.age_withdraw_commitments.noreveal_index),
- GNUNET_PQ_query_param_absolute_time (
- &td->details.age_withdraw_commitments.timestamp),
+ &td->details.age_withdraw.noreveal_index),
+ /* TODO: other fields, too! */
GNUNET_PQ_query_param_end
};
PREPARE (pg,
- "insert_into_table_age_withdraw_commitments",
- "INSERT INTO age_withdraw_commitments"
+ "insert_into_table_age_withdraw",
+ "INSERT INTO age_withdraw"
"(age_withdraw_commitment_id"
",h_commitment"
",amount_with_fee_val"
@@ -2097,64 +2096,10 @@ irbt_cb_table_age_withdraw_commitments (struct PostgresClosure *pg,
",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_age_withdraw_commitments",
- params);
-}
-
-
-/**
- * Function called with age_withdraw_revealed_coins records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_age_withdraw_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),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.age_withdraw_revealed_coins.h_commitment),
- GNUNET_PQ_query_param_uint32 (
- &td->details.age_withdraw_revealed_coins.freshcoin_index),
- GNUNET_PQ_query_param_uint64 (
- &td->details.age_withdraw_revealed_coins.denominations_serial),
- GNUNET_PQ_query_param_fixed_size (
- td->details.age_withdraw_revealed_coins.coin_ev,
- td->details.age_withdraw_revealed_coins.coin_ev_size),
- GNUNET_PQ_query_param_auto_from_type (&h_coin_ev),
- TALER_PQ_query_param_blinded_denom_sig (
- &td->details.age_withdraw_revealed_coins.ev_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_age_withdraw_revealed_coins",
- "INSERT INTO age_withdraw_revealed_coins"
- "(age_withdraw_revealed_coins_id"
- ",h_commitment"
- ",freshcoin_index"
- ",denominations_serial"
- ",coin_ev"
- ",h_coin_ev"
- ",ev_sig"
- ",ewv"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8);");
-
- GNUNET_CRYPTO_hash (td->details.age_withdraw_revealed_coins.coin_ev,
- td->details.age_withdraw_revealed_coins.coin_ev_size,
- &h_coin_ev);
-
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_age_withdraw_revealed_coins",
+ "insert_into_table_age_withdraw",
params);
}
@@ -2306,11 +2251,8 @@ TEH_PG_insert_records_by_table (void *cls,
case TALER_EXCHANGEDB_RT_PURSE_DELETION:
rh = &irbt_cb_table_purse_deletion;
break;
- case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS:
- rh = &irbt_cb_table_age_withdraw_commitments;
- break;
- case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS:
- rh = &irbt_cb_table_age_withdraw_revealed_coins;
+ case TALER_EXCHANGEDB_RT_AGE_WITHDRAW:
+ rh = &irbt_cb_table_age_withdraw;
break;
}
if (NULL == rh)
diff --git a/src/exchangedb/pg_iterate_denominations.c b/src/exchangedb/pg_iterate_denominations.c
index a38257689..1549ed77a 100644
--- a/src/exchangedb/pg_iterate_denominations.c
+++ b/src/exchangedb/pg_iterate_denominations.c
@@ -72,6 +72,8 @@ dominations_cb_helper (void *cls,
struct TALER_DenominationHashP h_denom_pub = {0};
bool revoked;
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("denominations_serial",
+ &meta.serial),
GNUNET_PQ_result_spec_auto_from_type ("master_sig",
&master_sig),
GNUNET_PQ_result_spec_bool ("revoked",
@@ -145,7 +147,8 @@ TEH_PG_iterate_denominations (void *cls,
PREPARE (pg,
"select_denominations",
"SELECT"
- " denominations.master_sig"
+ " denominations_serial"
+ ",denominations.master_sig"
",denom_revocations_serial_id IS NOT NULL AS revoked"
",valid_from"
",expire_withdraw"
diff --git a/src/exchangedb/pg_lookup_records_by_table.c b/src/exchangedb/pg_lookup_records_by_table.c
index 3fcad58c0..7862335ac 100644
--- a/src/exchangedb/pg_lookup_records_by_table.c
+++ b/src/exchangedb/pg_lookup_records_by_table.c
@@ -2762,109 +2762,48 @@ lrbt_cb_table_purse_deletion (void *cls,
/**
- * Function called with age_withdraw_commitments table entries.
+ * Function called with age_withdraw 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_age_withdraw_commitments (void *cls,
- PGresult *result,
- unsigned int num_results)
+lrbt_cb_table_age_withdraw (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
+ .table = TALER_EXCHANGEDB_RT_AGE_WITHDRAW
};
for (unsigned int i = 0; i<num_results; i++)
{
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint64 (
- "age_withdraw_commitment_id",
+ "age_withdraw_id",
&td.serial),
GNUNET_PQ_result_spec_auto_from_type (
"h_commitment",
- &td.details.age_withdraw_commitments.h_commitment),
+ &td.details.age_withdraw.h_commitment),
GNUNET_PQ_result_spec_uint16 (
"max_age",
- &td.details.age_withdraw_commitments.max_age),
+ &td.details.age_withdraw.max_age),
TALER_PQ_RESULT_SPEC_AMOUNT (
"amount_with_fee",
- &td.details.age_withdraw_commitments.amount_with_fee),
+ &td.details.age_withdraw.amount_with_fee),
GNUNET_PQ_result_spec_auto_from_type (
"reserve_pub",
- &td.details.age_withdraw_commitments.reserve_pub),
+ &td.details.age_withdraw.reserve_pub),
GNUNET_PQ_result_spec_auto_from_type (
"reserve_sig",
- &td.details.age_withdraw_commitments.reserve_sig),
+ &td.details.age_withdraw.reserve_sig),
GNUNET_PQ_result_spec_uint32 (
"noreveal_index",
- &td.details.age_withdraw_commitments.noreveal_index),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with age_withdraw_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_age_withdraw_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_REVEALED_COINS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "age_withdraw_revealed_coins_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_commitment",
- &td.details.age_withdraw_revealed_coins.h_commitment),
- GNUNET_PQ_result_spec_uint32 (
- "freshcoin_index",
- &td.details.age_withdraw_revealed_coins.freshcoin_index),
- GNUNET_PQ_result_spec_uint64 (
- "denominations_serial",
- &td.details.age_withdraw_revealed_coins.denominations_serial),
- /* Note: h_coin_ev is recalculated */
- GNUNET_PQ_result_spec_variable_size (
- "coin_ev",
- (void **) &td.details.age_withdraw_revealed_coins.coin_ev,
- &td.details.age_withdraw_revealed_coins.coin_ev_size),
- TALER_PQ_result_spec_blinded_denom_sig (
- "ev_sig",
- &td.details.refresh_revealed_coins.ev_sig),
- TALER_PQ_result_spec_exchange_withdraw_values (
- "ewv",
- &td.details.refresh_revealed_coins.ewv),
+ &td.details.age_withdraw.noreveal_index),
+ /* TODO[oec]: more fields! */
GNUNET_PQ_result_spec_end
};
@@ -3591,10 +3530,10 @@ TEH_PG_lookup_records_by_table (void *cls,
" 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_age_withdraw_commitments",
+ case TALER_EXCHANGEDB_RT_AGE_WITHDRAW:
+ XPREPARE ("select_above_serial_by_table_age_withdraw",
"SELECT"
- " age_withdraw_commitment_id"
+ " age_withdraw_id"
",h_commitment"
",amount_with_fee_val"
",amount_with_fee_frac"
@@ -3602,26 +3541,11 @@ TEH_PG_lookup_records_by_table (void *cls,
",reserve_pub"
",reserve_sig"
",noreveal_index"
- " FROM age_withdraw_commitments"
- " WHERE age_withdraw_commitment_id > $1"
- " ORDER BY age_withdraw_commitment_id ASC;");
- rh = &lrbt_cb_table_age_withdraw_commitments;
- break;
- case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS:
- XPREPARE ("select_above_serial_by_table_age_withdraw_revealed_coins",
- "SELECT"
- " age_withdraw_revealed_coins_serial_id"
- ",h_commitment"
- ",freshcoin_index"
- ",denominations_serial"
- ",coin_ev"
- ",h_coin_ev"
- ",ev_sig"
- ",ewv"
- " FROM age_withdraw_revealed_coins"
- " WHERE age_withdraw_revealed_coins_serial_id > $1"
- " ORDER BY age_withdraw_revealed_coins_serial_id ASC;");
- rh = &lrbt_cb_table_age_withdraw_revealed_coins;
+ " FROM age_withdraw"
+ " WHERE age_withdraw_id > $1"
+ " ORDER BY age_withdraw_id ASC;");
+ /* TODO[oec]: MORE FIELDS! */
+ rh = &lrbt_cb_table_age_withdraw;
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 2e3b41304..0bf0b9718 100644
--- a/src/exchangedb/pg_lookup_serial_by_table.c
+++ b/src/exchangedb/pg_lookup_serial_by_table.c
@@ -426,23 +426,14 @@ TEH_PG_lookup_serial_by_table (void *cls,
" LIMIT 1;");
statement = "select_serial_by_table_purse_deletion";
break;
- case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS:
- XPREPARE ("select_serial_by_table_age_withdraw_commitments",
+ case TALER_EXCHANGEDB_RT_AGE_WITHDRAW:
+ XPREPARE ("select_serial_by_table_age_withdraw",
"SELECT"
- " age_withdraw_commitment_id AS serial"
- " FROM age_withdraw_commitments"
- " ORDER BY age_withdraw_commitment_id DESC"
+ " age_withdraw_id AS serial"
+ " FROM age_withdraw"
+ " ORDER BY age_withdraw_id DESC"
" LIMIT 1;");
- statement = "select_serial_by_table_age_withdraw_commitments";
- break;
- case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS:
- XPREPARE ("select_serial_by_table_age_withdraw_revealed_coins",
- "SELECT"
- " age_withdraw_revealed_coins_id AS serial"
- " FROM age_withdraw_revealed_coins"
- " ORDER BY age_withdraw_revealed_coins_id DESC"
- " LIMIT 1;");
- statement = "select_serial_by_table_age_withdraw_revealed_coins";
+ statement = "select_serial_by_table_age_withdraw";
break;
}
if (NULL == statement)
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index 006484198..6938ee0ab 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -117,8 +117,9 @@
#include "pg_drain_kyc_alert.h"
#include "pg_reserves_in_insert.h"
#include "pg_get_withdraw_info.h"
-#include "pg_get_age_withdraw_info.h"
+#include "pg_get_age_withdraw.h"
#include "pg_do_batch_withdraw.h"
+#include "pg_do_age_withdraw.h"
#include "pg_get_policy_details.h"
#include "pg_persist_policy_details.h"
#include "pg_do_deposit.h"
@@ -581,8 +582,10 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &TEH_PG_get_withdraw_info;
plugin->do_batch_withdraw
= &TEH_PG_do_batch_withdraw;
- plugin->get_age_withdraw_info
- = &TEH_PG_get_age_withdraw_info;
+ plugin->do_age_withdraw
+ = &TEH_PG_do_age_withdraw;
+ plugin->get_age_withdraw
+ = &TEH_PG_get_age_withdraw;
plugin->get_policy_details
= &TEH_PG_get_policy_details;
plugin->persist_policy_details
diff --git a/src/exchangedb/shard-0001.sql b/src/exchangedb/shard-0001.sql
index 89c79f175..030664435 100644
--- a/src/exchangedb/shard-0001.sql
+++ b/src/exchangedb/shard-0001.sql
@@ -160,7 +160,7 @@ BEGIN
',current_balance_frac INT4 NOT NULL DEFAULT(0)'
',purses_active INT8 NOT NULL DEFAULT(0)'
',purses_allowed INT8 NOT NULL DEFAULT(0)'
- ',max_age INT4 NOT NULL DEFAULT(120)'
+ ',birthdate INT4 NOT NULL DEFAULT(0)' -- 0 means: no age restriction.
',expiration_date INT8 NOT NULL'
',gc_date INT8 NOT NULL'
') %s ;'