Compare commits
7 Commits
571d43cef3
...
94e5193bff
Author | SHA1 | Date | |
---|---|---|---|
94e5193bff | |||
1c923855a3 | |||
0d0494ee91 | |||
85020a9204 | |||
963e84aad2 | |||
|
d083536786 | ||
|
c93ce9ea2e |
@ -29,7 +29,7 @@ BEGIN
|
||||
'(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)'
|
||||
',amount_with_fee TALER_AMOUNT NOT NULL'
|
||||
',amount_with_fee taler_amount NOT NULL'
|
||||
',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)'
|
||||
@ -138,7 +138,7 @@ BEGIN
|
||||
'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
|
||||
$$;
|
||||
@ -151,6 +151,7 @@ INSERT INTO exchange_tables
|
||||
,partitioned
|
||||
,by_range)
|
||||
VALUES
|
||||
('age_withdraw', 'exchange-0003', 'create', TRUE ,FALSE),
|
||||
('age_withdraw', 'exchange-0003', 'constrain',TRUE ,FALSE),
|
||||
('age_withdraw', 'exchange-0003', 'foreign', TRUE ,FALSE);
|
||||
('age_withdraw', 'exchange-0002', 'create', TRUE ,FALSE),
|
||||
('age_withdraw', 'exchange-0002', 'constrain',TRUE ,FALSE),
|
||||
('age_withdraw', 'exchange-0002', 'foreign', TRUE ,FALSE);
|
||||
|
@ -137,12 +137,12 @@ INSERT INTO exchange_tables
|
||||
,by_range)
|
||||
VALUES
|
||||
('aml_history'
|
||||
,'exchange-0003'
|
||||
,'exchange-0002'
|
||||
,'create'
|
||||
,TRUE
|
||||
,FALSE),
|
||||
('aml_history'
|
||||
,'exchange-0003'
|
||||
,'exchange-0002'
|
||||
,'constrain'
|
||||
,TRUE
|
||||
,FALSE);
|
@ -91,12 +91,12 @@ INSERT INTO exchange_tables
|
||||
,by_range)
|
||||
VALUES
|
||||
('aml_status'
|
||||
,'exchange-0003'
|
||||
,'exchange-0002'
|
||||
,'create'
|
||||
,TRUE
|
||||
,FALSE),
|
||||
('aml_status'
|
||||
,'exchange-0003'
|
||||
,'exchange-0002'
|
||||
,'constrain'
|
||||
,TRUE
|
||||
,FALSE);
|
@ -29,7 +29,6 @@ BEGIN
|
||||
',h_payto BYTEA PRIMARY KEY CHECK (LENGTH(h_payto)=32)'
|
||||
',kyc_prox BYTEA NOT NULL CHECK (LENGTH(kyc_prox)=32)'
|
||||
',provider VARCHAR NOT NULL'
|
||||
',birthdate VARCHAR'
|
||||
',collection_time INT8 NOT NULL'
|
||||
',expiration_time INT8 NOT NULL'
|
||||
',encrypted_attributes BYTEA NOT NULL'
|
||||
@ -56,12 +55,6 @@ BEGIN
|
||||
,table_name
|
||||
,partition_suffix
|
||||
);
|
||||
PERFORM comment_partitioned_column(
|
||||
'birth date of the user, in format YYYY-MM-DD where a value of 0 is used to indicate unknown (in official documents); NULL if the birth date was not collected by the provider; used for KYC-driven age restrictions'
|
||||
,'birthdate'
|
||||
,table_name
|
||||
,partition_suffix
|
||||
);
|
||||
PERFORM comment_partitioned_column(
|
||||
'time when the attributes were collected by the provider'
|
||||
,'collection_time'
|
||||
@ -145,12 +138,12 @@ INSERT INTO exchange_tables
|
||||
,by_range)
|
||||
VALUES
|
||||
('kyc_attributes'
|
||||
,'exchange-0003'
|
||||
,'exchange-0002'
|
||||
,'create'
|
||||
,TRUE
|
||||
,FALSE),
|
||||
('kyc_attributes'
|
||||
,'exchange-0003'
|
||||
,'exchange-0002'
|
||||
,'constrain'
|
||||
,TRUE
|
||||
,FALSE);
|
@ -110,12 +110,12 @@ INSERT INTO exchange_tables
|
||||
,by_range)
|
||||
VALUES
|
||||
('purse_actions'
|
||||
,'exchange-0003'
|
||||
,'exchange-0002'
|
||||
,'create'
|
||||
,TRUE
|
||||
,FALSE),
|
||||
('purse_actions'
|
||||
,'exchange-0003'
|
||||
,'exchange-0002'
|
||||
,'master'
|
||||
,TRUE
|
||||
,FALSE);
|
@ -94,17 +94,17 @@ INSERT INTO exchange_tables
|
||||
,by_range)
|
||||
VALUES
|
||||
('purse_deletion'
|
||||
,'exchange-0003'
|
||||
,'exchange-0002'
|
||||
,'create'
|
||||
,TRUE
|
||||
,FALSE),
|
||||
('purse_deletion'
|
||||
,'exchange-0003'
|
||||
,'exchange-0002'
|
||||
,'constrain'
|
||||
,TRUE
|
||||
,FALSE),
|
||||
('purse_requests_was_deleted'
|
||||
,'exchange-0003'
|
||||
,'exchange-0002'
|
||||
,'master'
|
||||
,TRUE
|
||||
,FALSE);
|
@ -19,6 +19,9 @@ CREATE TABLE wire_accounts
|
||||
,master_sig BYTEA CHECK (LENGTH(master_sig)=64)
|
||||
,is_active BOOLEAN NOT NULL
|
||||
,last_change INT8 NOT NULL
|
||||
,conversion_url VARCHAR DEFAULT (NULL)
|
||||
,debit_restrictions VARCHAR DEFAULT (NULL)
|
||||
,credit_restrictions VARCHAR DEFAULT (NULL)
|
||||
);
|
||||
COMMENT ON TABLE wire_accounts
|
||||
IS 'Table with current and historic bank accounts of the exchange. Entries never expire as we need to remember the last_change column indefinitely.';
|
||||
@ -30,5 +33,13 @@ COMMENT ON COLUMN wire_accounts.is_active
|
||||
IS 'true if we are currently supporting the use of this account.';
|
||||
COMMENT ON COLUMN wire_accounts.last_change
|
||||
IS 'Latest time when active status changed. Used to detect replays of old messages.';
|
||||
COMMENT ON COLUMN wire_accounts.conversion_url
|
||||
IS 'URL of a currency conversion service if conversion is needed when this account is used; NULL if there is no conversion.';
|
||||
COMMENT ON COLUMN wire_accounts.debit_restrictions
|
||||
IS 'JSON array describing restrictions imposed when debiting this account. Empty for no restrictions, NULL if account was migrated from previous database revision or account is disabled.';
|
||||
COMMENT ON COLUMN wire_accounts.credit_restrictions
|
||||
IS 'JSON array describing restrictions imposed when crediting this account. Empty for no restrictions, NULL if account was migrated from previous database revision or account is disabled.';
|
||||
|
||||
|
||||
-- "wire_accounts" has no sequence because it is a 'mutable' table
|
||||
-- and is of no concern to the auditor
|
||||
|
@ -1,44 +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/>
|
||||
--
|
||||
|
||||
CREATE OR REPLACE FUNCTION master_table_kyc_attributes_V2()
|
||||
RETURNS VOID
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
table_name VARCHAR DEFAULT 'kyc_attributes';
|
||||
BEGIN
|
||||
EXECUTE FORMAT (
|
||||
'ALTER TABLE ' || table_name ||
|
||||
' DROP COLUMN birthdate;'
|
||||
);
|
||||
END $$;
|
||||
|
||||
COMMENT ON FUNCTION master_table_kyc_attributes_V2
|
||||
IS 'Removes birthdate column from the kyc_attributes table';
|
||||
|
||||
INSERT INTO exchange_tables
|
||||
(name
|
||||
,version
|
||||
,action
|
||||
,partitioned
|
||||
,by_range)
|
||||
VALUES
|
||||
('kyc_attributes_V2'
|
||||
,'exchange-0004'
|
||||
,'master'
|
||||
,TRUE
|
||||
,FALSE);
|
@ -1,26 +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/>
|
||||
--
|
||||
|
||||
ALTER TABLE wire_accounts
|
||||
ADD COLUMN conversion_url VARCHAR DEFAULT (NULL),
|
||||
ADD COLUMN debit_restrictions VARCHAR DEFAULT (NULL),
|
||||
ADD COLUMN credit_restrictions VARCHAR DEFAULT (NULL);
|
||||
COMMENT ON COLUMN wire_accounts.conversion_url
|
||||
IS 'URL of a currency conversion service if conversion is needed when this account is used; NULL if there is no conversion.';
|
||||
COMMENT ON COLUMN wire_accounts.debit_restrictions
|
||||
IS 'JSON array describing restrictions imposed when debiting this account. Empty for no restrictions, NULL if account was migrated from previous database revision or account is disabled.';
|
||||
COMMENT ON COLUMN wire_accounts.credit_restrictions
|
||||
IS 'JSON array describing restrictions imposed when crediting this account. Empty for no restrictions, NULL if account was migrated from previous database revision or account is disabled.';
|
@ -18,19 +18,13 @@ sqlinputs = \
|
||||
exchange_do_*.sql \
|
||||
procedures.sql.in \
|
||||
0002-*.sql \
|
||||
exchange-0002.sql.in \
|
||||
0003-*.sql \
|
||||
exchange-0003.sql.in \
|
||||
0004-*.sql \
|
||||
exchange-0004.sql.in
|
||||
exchange-0002.sql.in
|
||||
|
||||
sql_DATA = \
|
||||
benchmark-0001.sql \
|
||||
versioning.sql \
|
||||
exchange-0001.sql \
|
||||
exchange-0002.sql \
|
||||
exchange-0003.sql \
|
||||
exchange-0004.sql \
|
||||
drop.sql \
|
||||
procedures.sql
|
||||
|
||||
@ -41,9 +35,7 @@ BUILT_SOURCES = \
|
||||
procedures.sql
|
||||
|
||||
CLEANFILES = \
|
||||
exchange-0002.sql \
|
||||
exchange-0003.sql \
|
||||
exchange-0004.sql
|
||||
exchange-0002.sql
|
||||
|
||||
procedures.sql: procedures.sql.in exchange_do_*.sql
|
||||
chmod +w $@ || true
|
||||
@ -55,16 +47,6 @@ exchange-0002.sql: exchange-0002.sql.in 0002-*.sql
|
||||
gcc -E -P -undef - < exchange-0002.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@
|
||||
chmod ugo-w $@
|
||||
|
||||
exchange-0003.sql: exchange-0003.sql.in 0003-*.sql
|
||||
chmod +w $@ || true
|
||||
gcc -E -P -undef - < exchange-0003.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@
|
||||
chmod ugo-w $@
|
||||
|
||||
exchange-0004.sql: exchange-0004.sql.in 0004-*.sql
|
||||
chmod +w $@ || true
|
||||
gcc -E -P -undef - < exchange-0004.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@
|
||||
chmod ugo-w $@
|
||||
|
||||
check_SCRIPTS = \
|
||||
test_idempotency.sh
|
||||
|
||||
|
@ -20,8 +20,6 @@ BEGIN;
|
||||
|
||||
SELECT _v.unregister_patch('exchange-0001');
|
||||
SELECT _v.unregister_patch('exchange-0002');
|
||||
SELECT _v.unregister_patch('exchange-0003');
|
||||
SELECT _v.unregister_patch('exchange-0004');
|
||||
|
||||
DROP SCHEMA exchange CASCADE;
|
||||
|
||||
|
@ -137,102 +137,10 @@ COMMENT ON FUNCTION comment_partitioned_column
|
||||
IS 'Generic function to create a comment on column of a table that is partitioned.';
|
||||
|
||||
|
||||
--------------------------------------------------------------
|
||||
-- Taler amounts and helper functiosn
|
||||
-------------------------------------------------------------
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
CREATE TYPE TALER_AMOUNT
|
||||
AS (val INT8
|
||||
,frac INT4);
|
||||
|
||||
COMMENT ON TYPE TALER_AMOUNT
|
||||
IS 'Type to store a TALER-amount as (val, frac) pair.';
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE PROCEDURE amount_normalize(
|
||||
IN amount TALER_AMOUNT
|
||||
,OUT normalized TALER_AMOUNT
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
normalized.val = amount.val + amount.frac / 100000000;
|
||||
normalized.frac = amount.frac % 100000000;
|
||||
END $$;
|
||||
|
||||
COMMENT ON PROCEDURE amount_normalize
|
||||
IS 'Returns the normalized amount by adding to the .val the value of (.frac / 100000000) and removing the modulus 100000000 from .frac.';
|
||||
|
||||
CREATE PROCEDURE amount_add(
|
||||
IN a TALER_AMOUNT
|
||||
,IN b TALER_AMOUNT
|
||||
,OUT sum TALER_AMOUNT
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
sum = (a.val + b.val, a.frac + b.frac);
|
||||
CALL amount_normalize(sum ,sum);
|
||||
|
||||
IF (sum.val > (1<<52))
|
||||
THEN
|
||||
RAISE EXCEPTION 'addition overflow';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
COMMENT ON PROCEDURE amount_add
|
||||
IS 'Returns the normalized sum of two amounts. It raises an exception when the resulting .val is larger than 2^52';
|
||||
|
||||
CREATE FUNCTION amount_left_minus_right(
|
||||
IN l TALER_AMOUNT
|
||||
,IN r TALER_AMOUNT
|
||||
,OUT diff TALER_AMOUNT
|
||||
,OUT ok BOOLEAN
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
|
||||
IF (l.val > r.val)
|
||||
THEN
|
||||
ok = TRUE;
|
||||
IF (l.frac >= r.frac)
|
||||
THEN
|
||||
diff.val = l.val - r.val;
|
||||
diff.frac = l.frac - r.frac;
|
||||
ELSE
|
||||
diff.val = l.val - r.val - 1;
|
||||
diff.frac = l.frac + 100000000 - r.frac;
|
||||
END IF;
|
||||
ELSE
|
||||
IF (l.val = r.val) AND (l.frac >= r.frac)
|
||||
THEN
|
||||
diff.val = 0;
|
||||
diff.frac = l.frac - r.frac;
|
||||
ok = TRUE;
|
||||
ELSE
|
||||
diff = (-1, -1);
|
||||
ok = FALSE;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
RETURN;
|
||||
END $$;
|
||||
|
||||
COMMENT ON FUNCTION amount_left_minus_right
|
||||
IS 'Subtracts the right amount from the left and returns the difference and TRUE, if the left amount is larger than the right, or an invalid amount and FALSE otherwise.';
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- Main DB setup loop
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
|
||||
CREATE FUNCTION do_create_tables(
|
||||
num_partitions INTEGER
|
||||
-- NULL: no partitions, add foreign constraints
|
||||
|
@ -19,6 +19,22 @@ BEGIN;
|
||||
SELECT _v.register_patch('exchange-0002', NULL, NULL);
|
||||
SET search_path TO exchange;
|
||||
|
||||
CREATE TYPE taler_amount
|
||||
AS
|
||||
(val INT8
|
||||
,frac INT4
|
||||
);
|
||||
COMMENT ON TYPE taler_amount
|
||||
IS 'Stores an amount, fraction is in units of 1/100000000 of the base value';
|
||||
|
||||
CREATE TYPE exchange_do_array_reserve_insert_return_type
|
||||
AS
|
||||
(transaction_duplicate BOOLEAN
|
||||
,ruuid INT8
|
||||
);
|
||||
COMMENT ON TYPE exchange_do_array_reserve_insert_return_type
|
||||
IS 'Return type for exchange_do_array_reserves_insert() stored procedure';
|
||||
|
||||
#include "0002-denominations.sql"
|
||||
#include "0002-denomination_revocations.sql"
|
||||
#include "0002-wire_targets.sql"
|
||||
@ -71,5 +87,13 @@ SET search_path TO exchange;
|
||||
#include "0002-revolving_work_shards.sql"
|
||||
#include "0002-partners.sql"
|
||||
#include "0002-partner_accounts.sql"
|
||||
#include "0002-purse_actions.sql"
|
||||
#include "0002-purse_deletion.sql"
|
||||
#include "0002-kyc_attributes.sql"
|
||||
#include "0002-aml_status.sql"
|
||||
#include "0002-aml_staff.sql"
|
||||
#include "0002-aml_history.sql"
|
||||
#include "0002-age_withdraw.sql"
|
||||
|
||||
|
||||
COMMIT;
|
||||
|
@ -1,31 +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 <http://www.gnu.org/licenses/>
|
||||
--
|
||||
|
||||
BEGIN;
|
||||
|
||||
SELECT _v.register_patch('exchange-0003', NULL, NULL);
|
||||
SET search_path TO exchange;
|
||||
|
||||
#include "0003-purse_actions.sql"
|
||||
#include "0003-purse_deletion.sql"
|
||||
#include "0003-kyc_attributes.sql"
|
||||
#include "0003-aml_status.sql"
|
||||
#include "0003-aml_staff.sql"
|
||||
#include "0003-aml_history.sql"
|
||||
#include "0003-age_withdraw.sql"
|
||||
|
||||
|
||||
COMMIT;
|
@ -1,25 +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/>
|
||||
--
|
||||
|
||||
BEGIN;
|
||||
|
||||
SELECT _v.register_patch('exchange-0004', NULL, NULL);
|
||||
SET search_path TO exchange;
|
||||
|
||||
#include "0004-kyc_attributes.sql"
|
||||
#include "0004-wire_accounts.sql"
|
||||
|
||||
COMMIT;
|
@ -16,7 +16,7 @@
|
||||
-- @author Özgür Kesim
|
||||
|
||||
CREATE OR REPLACE FUNCTION exchange_do_age_withdraw(
|
||||
IN amount_with_fee TALER_AMOUNT,
|
||||
IN amount_with_fee taler_amount,
|
||||
IN rpub BYTEA,
|
||||
IN rsig BYTEA,
|
||||
IN now INT8,
|
||||
@ -38,8 +38,8 @@ AS $$
|
||||
DECLARE
|
||||
reserve_gc INT8;
|
||||
difference RECORD;
|
||||
balance TALER_AMOUNT;
|
||||
new_balance TALER_AMOUNT;
|
||||
balance taler_amount;
|
||||
new_balance taler_amount;
|
||||
not_before date;
|
||||
earliest_date date;
|
||||
BEGIN
|
||||
@ -166,6 +166,5 @@ END IF;
|
||||
|
||||
END $$;
|
||||
|
||||
COMMENT ON FUNCTION exchange_do_age_withdraw(TALER_AMOUNT, BYTEA, BYTEA, INT8, INT8, BYTEA, INT2, INT2, BYTEA[], INT8[], BYTEA[])
|
||||
COMMENT ON FUNCTION exchange_do_age_withdraw(taler_amount, 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';
|
||||
|
||||
|
78
src/exchangedb/exchange_do_amount_specific.sql
Normal file
78
src/exchangedb/exchange_do_amount_specific.sql
Normal file
@ -0,0 +1,78 @@
|
||||
--------------------------------------------------------------
|
||||
-- Taler amounts and helper functiosn
|
||||
-------------------------------------------------------------
|
||||
|
||||
CREATE OR REPLACE PROCEDURE amount_normalize(
|
||||
IN amount taler_amount
|
||||
,OUT normalized taler_amount
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
normalized.val = amount.val + amount.frac / 100000000;
|
||||
normalized.frac = amount.frac % 100000000;
|
||||
END $$;
|
||||
|
||||
COMMENT ON PROCEDURE amount_normalize
|
||||
IS 'Returns the normalized amount by adding to the .val the value of (.frac / 100000000) and removing the modulus 100000000 from .frac.';
|
||||
|
||||
CREATE OR REPLACE PROCEDURE amount_add(
|
||||
IN a taler_amount
|
||||
,IN b taler_amount
|
||||
,OUT sum taler_amount
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
sum = (a.val + b.val, a.frac + b.frac);
|
||||
CALL amount_normalize(sum ,sum);
|
||||
|
||||
IF (sum.val > (1<<52))
|
||||
THEN
|
||||
RAISE EXCEPTION 'addition overflow';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
COMMENT ON PROCEDURE amount_add
|
||||
IS 'Returns the normalized sum of two amounts. It raises an exception when the resulting .val is larger than 2^52';
|
||||
|
||||
CREATE OR REPLACE FUNCTION amount_left_minus_right(
|
||||
IN l taler_amount
|
||||
,IN r taler_amount
|
||||
,OUT diff taler_amount
|
||||
,OUT ok BOOLEAN
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
|
||||
IF (l.val > r.val)
|
||||
THEN
|
||||
ok = TRUE;
|
||||
IF (l.frac >= r.frac)
|
||||
THEN
|
||||
diff.val = l.val - r.val;
|
||||
diff.frac = l.frac - r.frac;
|
||||
ELSE
|
||||
diff.val = l.val - r.val - 1;
|
||||
diff.frac = l.frac + 100000000 - r.frac;
|
||||
END IF;
|
||||
ELSE
|
||||
IF (l.val = r.val) AND (l.frac >= r.frac)
|
||||
THEN
|
||||
diff.val = 0;
|
||||
diff.frac = l.frac - r.frac;
|
||||
ok = TRUE;
|
||||
ELSE
|
||||
diff = (-1, -1);
|
||||
ok = FALSE;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
RETURN;
|
||||
END $$;
|
||||
|
||||
COMMENT ON FUNCTION amount_left_minus_right
|
||||
IS 'Subtracts the right amount from the left and returns the difference and TRUE, if the left amount is larger than the right, or an invalid amount and FALSE otherwise.';
|
||||
|
||||
|
@ -966,21 +966,6 @@ END $$;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
CREATE TYPE exchange_do_array_reserve_insert_return_type
|
||||
AS
|
||||
(transaction_duplicate BOOLEAN
|
||||
,ruuid INT8);
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION exchange_do_array_reserves_insert(
|
||||
IN in_gc_date INT8,
|
||||
IN in_reserve_expiration INT8,
|
||||
|
@ -293,6 +293,15 @@ TEH_PG_internal_setup (struct PostgresClosure *pg)
|
||||
NULL);
|
||||
if (NULL == db_conn)
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
if (GNUNET_OK != TALER_PQ_load_oids_for_composite_types (db_conn))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to load OIDs for composite types\n");
|
||||
GNUNET_PQ_disconnect (db_conn);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
pg->prep_gen++;
|
||||
pg->conn = db_conn;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ BEGIN;
|
||||
|
||||
SET search_path TO exchange;
|
||||
|
||||
#include "exchange_do_amount_specific.sql"
|
||||
#include "exchange_do_withdraw.sql"
|
||||
#include "exchange_do_batch_withdraw.sql"
|
||||
#include "exchange_do_batch_withdraw_insert.sql"
|
||||
|
@ -46,7 +46,6 @@ TALER_EXCHANGEDB_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg);
|
||||
void
|
||||
TALER_EXCHANGEDB_plugin_unload (struct TALER_EXCHANGEDB_Plugin *plugin);
|
||||
|
||||
|
||||
/**
|
||||
* Information about an account from the configuration.
|
||||
*/
|
||||
|
@ -19,15 +19,42 @@
|
||||
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
|
||||
* @author Florian Dold
|
||||
* @author Christian Grothoff
|
||||
* @author Özgür Kesim
|
||||
*/
|
||||
#ifndef TALER_PQ_LIB_H_
|
||||
#define TALER_PQ_LIB_H_
|
||||
|
||||
#include <libpq-fe.h>
|
||||
#include <jansson.h>
|
||||
#include <gnunet/gnunet_common.h>
|
||||
#include <gnunet/gnunet_pq_lib.h>
|
||||
#include "taler_util.h"
|
||||
|
||||
/**
|
||||
* Enumerates the composite types that Taler defines in Postgres.
|
||||
* The corresponding OIDs (which are assigned by postgres at time of
|
||||
* declaration) are stored in TALER_PQ_CompositeOIDs.
|
||||
*/
|
||||
enum TALER_PQ_CompositeType
|
||||
{
|
||||
TALER_PQ_CompositeAmount,
|
||||
TALER_PQ_CompositeMAX /* MUST be last */
|
||||
};
|
||||
|
||||
/**
|
||||
* The correspondence of the Composite types and their OID in Postgres
|
||||
*/
|
||||
extern Oid TALER_PQ_CompositeOIDs[TALER_PQ_CompositeMAX];
|
||||
|
||||
/**
|
||||
* Initialize the list of OIDs in TALER_PQ_CompositeOIDs. MUST be called
|
||||
* before any composite type is used in arrays-specs/-params.
|
||||
*
|
||||
* @return GNUNET_SYSERR on failure
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_PQ_load_oids_for_composite_types (struct GNUNET_PQ_Context *db);
|
||||
|
||||
/**
|
||||
* Generate query parameter for a currency, consisting of the three
|
||||
* components "value", "fraction" and "currency" in this order. The
|
||||
|
@ -10,6 +10,8 @@ lib_LTLIBRARIES = \
|
||||
libtalerpq.la
|
||||
|
||||
libtalerpq_la_SOURCES = \
|
||||
pq_common.h \
|
||||
pq_composite_types.c \
|
||||
pq_query_helper.c \
|
||||
pq_result_helper.c
|
||||
libtalerpq_la_LIBADD = \
|
||||
|
83
src/pq/pq_common.h
Normal file
83
src/pq/pq_common.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
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 pq/pq_common.h
|
||||
* @brief common defines for the pq functions
|
||||
* @author Özgür Kesim
|
||||
*/
|
||||
#ifndef TALER_PQ_COMMON_H_
|
||||
#define TALER_PQ_COMMON_H_
|
||||
|
||||
#include "platform.h"
|
||||
/**
|
||||
* Internal types that are supported as TALER-exchange-specific array types.
|
||||
*
|
||||
* To support a new type,
|
||||
* 1. add a new entry into this list,
|
||||
* 2. for query-support, implement the size calculation and memory copying in
|
||||
* qconv_array() accordingly, in pq_query_helper.c
|
||||
* 3. provide a query-API for arrays of the type, by calling
|
||||
* query_param_array_generic with the appropriate parameters,
|
||||
* in pq_query_helper.c
|
||||
* 4. for result-support, implement memory copying by adding another case
|
||||
* to extract_array_generic, in pq_result_helper.c
|
||||
* 5. provide a result-spec-API for arrays of the type,
|
||||
* in pq_result_helper.c
|
||||
* 6. expose the API's in taler_pq_lib.h
|
||||
*/
|
||||
enum TALER_PQ_ArrayType
|
||||
{
|
||||
TALER_PQ_array_of_blinded_denom_sig,
|
||||
TALER_PQ_array_of_blinded_coin_hash,
|
||||
TALER_PQ_array_of_denom_hash,
|
||||
/* TODO[oec]: Next up: TALER_PQ_array_of_amount, */
|
||||
TALER_PQ_array_of_MAX, /* must be last */
|
||||
};
|
||||
|
||||
/**
|
||||
* Memory representation of an taler amount record for Postgres.
|
||||
*
|
||||
* All values need to be in network-byte-order.
|
||||
*/
|
||||
struct TALER_PQ_Amount_P
|
||||
{
|
||||
uint32_t oid_v; /* oid of .v */
|
||||
uint32_t sz_v; /* size of .v */
|
||||
uint64_t v; /* value */
|
||||
uint32_t oid_f; /* oid of .f */
|
||||
uint32_t sz_f; /* size of .f */
|
||||
uint32_t f; /* fraction */
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* Create a `struct TALER_PQ_Amount_P` for initialization
|
||||
*
|
||||
* @param db postgres-context of type `struct GNUNET_PQ_Context *`
|
||||
* @param amount amount of type `struct TALER_Amount *`
|
||||
*/
|
||||
#define MAKE_TALER_PQ_AMOUNT_P(db,amount) \
|
||||
{ \
|
||||
.oid_v = htonl (GNUNET_PQ_get_oid ((db), GNUNET_PQ_DATATYPE_INT8)), \
|
||||
.oid_f = htonl (GNUNET_PQ_get_oid ((db), GNUNET_PQ_DATATYPE_INT4)), \
|
||||
.sz_v = htonl (sizeof((amount)->value)), \
|
||||
.sz_f = htonl (sizeof((amount)->fraction)), \
|
||||
.v = GNUNET_htonll ((amount)->value), \
|
||||
.f = htonl ((amount)->fraction) \
|
||||
}
|
||||
|
||||
|
||||
#endif /* TALER_PQ_COMMON_H_ */
|
||||
/* end of pg/pq_common.h */
|
57
src/pq/pq_composite_types.c
Normal file
57
src/pq/pq_composite_types.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
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 pq/pq_composite_types.c
|
||||
* @brief helper functions for Taler-specific libpq (PostGres) interactions with composite types
|
||||
* @author Özgür Kesim
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include <gnunet/gnunet_common.h>
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <gnunet/gnunet_pq_lib.h>
|
||||
#include "taler_pq_lib.h"
|
||||
#include "pq_common.h"
|
||||
|
||||
Oid TALER_PQ_CompositeOIDs[TALER_PQ_CompositeMAX] = {0};
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_PQ_load_oids_for_composite_types (
|
||||
struct GNUNET_PQ_Context *db)
|
||||
{
|
||||
static char *names[] = {
|
||||
[TALER_PQ_CompositeAmount] = "taler_amount"
|
||||
};
|
||||
size_t num = sizeof(names) / sizeof(names[0]);
|
||||
|
||||
GNUNET_static_assert (num == TALER_PQ_CompositeMAX);
|
||||
|
||||
for (size_t i = 0; i < num; i++)
|
||||
{
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
enum TALER_PQ_CompositeType typ = i;
|
||||
ret = GNUNET_PQ_get_oid_by_name (db,
|
||||
names[i],
|
||||
&TALER_PQ_CompositeOIDs[typ]);
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to load OID for type %s\n",
|
||||
names[i]);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
@ -872,7 +872,7 @@ qconv_array (
|
||||
RETURN_UNLESS ((0 == num) || (y / num == x));
|
||||
|
||||
/* size of header */
|
||||
total_size = x = sizeof(struct TALER_PQ_ArrayHeader_P);
|
||||
total_size = x = sizeof(struct GNUNET_PQ_ArrayHeader_P);
|
||||
total_size += y;
|
||||
RETURN_UNLESS (total_size >= x);
|
||||
|
||||
@ -941,7 +941,7 @@ qconv_array (
|
||||
/* Write data */
|
||||
{
|
||||
char *out = elements;
|
||||
struct TALER_PQ_ArrayHeader_P h = {
|
||||
struct GNUNET_PQ_ArrayHeader_P h = {
|
||||
.ndim = htonl (1), /* We only support one-dimensional arrays */
|
||||
.has_null = htonl (0), /* We do not support NULL entries in arrays */
|
||||
.lbound = htonl (1), /* Default start index value */
|
||||
|
@ -1166,7 +1166,7 @@ extract_array_generic (
|
||||
int data_sz;
|
||||
char *data;
|
||||
void *out = NULL;
|
||||
struct TALER_PQ_ArrayHeader_P header;
|
||||
struct GNUNET_PQ_ArrayHeader_P header;
|
||||
int col_num;
|
||||
|
||||
GNUNET_assert (NULL != dst);
|
||||
@ -1192,8 +1192,8 @@ extract_array_generic (
|
||||
FAIL_IF (NULL == data);
|
||||
|
||||
{
|
||||
struct TALER_PQ_ArrayHeader_P *h =
|
||||
(struct TALER_PQ_ArrayHeader_P *) data;
|
||||
struct GNUNET_PQ_ArrayHeader_P *h =
|
||||
(struct GNUNET_PQ_ArrayHeader_P *) data;
|
||||
|
||||
header.ndim = ntohl (h->ndim);
|
||||
header.has_null = ntohl (h->has_null);
|
||||
|
@ -194,6 +194,16 @@ main (int argc,
|
||||
GNUNET_PQ_disconnect (conn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = TALER_PQ_load_oids_for_composite_types (conn);
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to load oids for composites\n");
|
||||
GNUNET_PQ_disconnect (conn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = run_queries (conn);
|
||||
{
|
||||
struct GNUNET_PQ_ExecuteStatement ds[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user