diff options
Diffstat (limited to 'src/exchangedb/exchange_do_reserve_purse.sql')
-rw-r--r-- | src/exchangedb/exchange_do_reserve_purse.sql | 162 |
1 files changed, 162 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..8ae652e69 --- /dev/null +++ b/src/exchangedb/exchange_do_reserve_purse.sql @@ -0,0 +1,162 @@ +-- +-- 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_expiration INT8, + IN in_reserve_gc INT8, + IN in_reserve_sig BYTEA, + IN in_reserve_quota BOOLEAN, + IN in_purse_fee taler_amount, + 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 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 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; + INSERT INTO exchange.reserves + (reserve_pub + ,expiration_date + ,gc_date) + VALUES + (in_reserve_pub + ,in_reserve_expiration + ,in_reserve_gc); + 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 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, INT8, INT8, BYTEA, BOOLEAN, taler_amount, BYTEA, BYTEA) + IS 'Create a purse for a reserve.'; |