diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-12-06 13:29:23 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-12-06 13:29:23 +0100 |
commit | 87198f124c989d014adc9a2bae5098cf80555d62 (patch) | |
tree | 666ea877e53cebbe2ff9260f3efcdfff4a0b7c08 /src/exchangedb/exchange_do_reserve_purse.sql | |
parent | 21959eebd2256a3fb72173488cf366868179ee13 (diff) | |
download | exchange-87198f124c989d014adc9a2bae5098cf80555d62.tar.xz |
refactor procedures.sql
Diffstat (limited to 'src/exchangedb/exchange_do_reserve_purse.sql')
-rw-r--r-- | src/exchangedb/exchange_do_reserve_purse.sql | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/src/exchangedb/exchange_do_reserve_purse.sql b/src/exchangedb/exchange_do_reserve_purse.sql new file mode 100644 index 000000000..a110c85a3 --- /dev/null +++ b/src/exchangedb/exchange_do_reserve_purse.sql @@ -0,0 +1,157 @@ +-- +-- 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/> +-- + +CREATE OR REPLACE FUNCTION exchange_do_reserve_purse( + IN in_purse_pub BYTEA, + IN in_merge_sig BYTEA, + IN in_merge_timestamp INT8, + IN in_reserve_sig BYTEA, + IN in_reserve_quota BOOLEAN, + IN in_purse_fee_val INT8, + IN in_purse_fee_frac INT4, + IN in_reserve_pub BYTEA, + IN in_wallet_h_payto BYTEA, + OUT out_no_funds BOOLEAN, + OUT out_no_reserve BOOLEAN, + OUT out_conflict BOOLEAN) +LANGUAGE plpgsql +AS $$ +BEGIN + +-- Store purse merge signature, checks for purse_pub uniqueness +INSERT INTO exchange.purse_merges + (partner_serial_id + ,reserve_pub + ,purse_pub + ,merge_sig + ,merge_timestamp) + VALUES + (NULL + ,in_reserve_pub + ,in_purse_pub + ,in_merge_sig + ,in_merge_timestamp) + ON CONFLICT DO NOTHING; + +IF NOT FOUND +THEN + -- Idempotency check: see if an identical record exists. + -- Note that by checking 'merge_sig', we implicitly check + -- identity over everything that the signature covers. + PERFORM + FROM exchange.purse_merges + WHERE purse_pub=in_purse_pub + AND merge_sig=in_merge_sig; + IF NOT FOUND + THEN + -- Purse was merged, but to some other reserve. Not allowed. + out_conflict=TRUE; + out_no_reserve=FALSE; + out_no_funds=FALSE; + RETURN; + END IF; + + -- "success" + out_conflict=FALSE; + out_no_funds=FALSE; + out_no_reserve=FALSE; + RETURN; +END IF; +out_conflict=FALSE; + +PERFORM + FROM exchange.reserves + WHERE reserve_pub=in_reserve_pub; + +out_no_reserve = NOT FOUND; + +IF (in_reserve_quota) +THEN + -- Increment active purses per reserve (and check this is allowed) + IF (out_no_reserve) + THEN + out_no_funds=TRUE; + RETURN; + END IF; + UPDATE exchange.reserves + SET purses_active=purses_active+1 + WHERE reserve_pub=in_reserve_pub + AND purses_active < purses_allowed; + IF NOT FOUND + THEN + out_no_funds=TRUE; + RETURN; + END IF; +ELSE + -- UPDATE reserves balance (and check if balance is enough to pay the fee) + IF (out_no_reserve) + THEN + IF ( (0 != in_purse_fee_val) OR + (0 != in_purse_fee_frac) ) + THEN + out_no_funds=TRUE; + RETURN; + END IF; + ELSE + UPDATE exchange.reserves + SET + current_balance_frac=current_balance_frac-in_purse_fee_frac + + CASE + WHEN current_balance_frac < in_purse_fee_frac + THEN 100000000 + ELSE 0 + END, + current_balance_val=current_balance_val-in_purse_fee_val + - CASE + WHEN current_balance_frac < in_purse_fee_frac + THEN 1 + ELSE 0 + END + WHERE reserve_pub=in_reserve_pub + AND ( (current_balance_val > in_purse_fee_val) OR + ( (current_balance_frac >= in_purse_fee_frac) AND + (current_balance_val >= in_purse_fee_val) ) ); + IF NOT FOUND + THEN + out_no_funds=TRUE; + RETURN; + END IF; + END IF; +END IF; + +out_no_funds=FALSE; + + +-- Store account merge signature. +INSERT INTO exchange.account_merges + (reserve_pub + ,reserve_sig + ,purse_pub + ,wallet_h_payto) + VALUES + (in_reserve_pub + ,in_reserve_sig + ,in_purse_pub + ,in_wallet_h_payto); + +END $$; + +COMMENT ON FUNCTION exchange_do_reserve_purse(BYTEA, BYTEA, INT8, BYTEA, BOOLEAN, INT8, INT4, BYTEA, BYTEA) + IS 'Create a purse for a reserve.'; + + + + |