Merge branch 'master' into ar

This commit is contained in:
Özgür Kesim 2021-12-14 14:21:45 +01:00
commit fe457bb7ba
Signed by: oec
GPG Key ID: 3D76A56D79EDD9D7

130
src/exchangedb/withdraw.sql Normal file
View File

@ -0,0 +1,130 @@
CREATE OR REPLACE FUNCTION exchange_do_withdraw(
IN amount_val INT8,
IN amount_frac INT4,
IN h_denom_pub BYTEA,
IN rpub BYTEA,
IN reserve_sig BYTEA,
IN h_coin_envelope BYTEA,
IN denom_sig BYTEA,
IN now INT8,
IN min_reserve_gc INT8,
OUT reserve_found BOOLEAN,
OUT balance_ok BOOLEAN,
OUT kycok BOOLEAN,
OUT ruuid INT8,
OUT account_uuid INT8)
LANGUAGE plpgsql
AS $$
DECLARE
reserve_gc INT8;
DECLARE
denom_serial INT8;
DECLARE
reserve_val INT8;
DECLARE
reserve_frac INT4;
BEGIN
SELECT denominations_serial INTO denom_serial
FROM denominations
WHERE denom_pub_hash=h_denom_pub;
IF NOT FOUND
THEN
-- denomination unknown, should be impossible!
reserve_found=FALSE;
balance_ok=FALSE;
kycok=FALSE;
ruuid=0;
account_uuid=0;
ASSERT false, 'denomination unknown';
RETURN;
END IF;
UPDATE reserves SET
gc_date=GREATEST(gc_date, min_reserve_gc)
,current_balance_val=current_balance_val - amount_val
- CASE WHEN (current_balance_frac < amount_frac)
THEN 1
ELSE 0
END
,current_balance_frac=current_balance_frac - amount_frac
+ CASE WHEN (current_balance_frac < amount_frac)
THEN 100000000
ELSE 0
END
WHERE reserves.reserve_pub=rpub
AND ( (current_balance_val > amount_val) OR
( (current_balance_val = amount_val) AND
(current_balance_frac >= amount_frac) ) );
balance_ok=FOUND;
-- Obtain KYC status based on the last wire transfer into
-- this reserve. FIXME: likely not adequate for reserves that got P2P transfers!
SELECT
kyc_ok
,wire_source_serial_id
,reserve_uuid
INTO
kycok
,account_uuid
,ruuid
FROM reserves
JOIN reserves_in USING (reserve_uuid)
JOIN wire_targets ON (wire_source_serial_id = wire_target_serial_id)
WHERE reserves.reserve_pub=rpub
LIMIT 1; -- limit 1 should not be required (without p2p transfers)
IF NOT FOUND
THEN
-- reserve unknown
reserve_found=FALSE;
balance_ok=FALSE;
kycok=FALSE;
account_uuid=0;
RETURN;
END IF;
reserve_found=TRUE;
-- We optimistically insert, and then on conflict declare
-- the query successful due to idempotency.
INSERT INTO reserves_out
(h_blind_ev
,denominations_serial
,denom_sig
,reserve_uuid
,reserve_sig
,execution_date
,amount_with_fee_val
,amount_with_fee_frac)
VALUES
(h_coin_envelope
,denom_serial
,denom_sig
,ruuid
,reserve_sig
,now
,amount_val
,amount_frac)
ON CONFLICT DO NOTHING;
IF NOT FOUND
THEN
-- idempotent query, all constraints must be satisfied
balance_ok=TRUE;
-- rollback any potential balance update we may have made
ROLLBACK;
START TRANSACTION ISOLATION LEVEL SERIALIZABLE;
RETURN;
END IF;
END $$;
COMMENT ON FUNCTION exchange_do_withdraw(INT8, INT4, BYTEA, BYTEA, BYTEA, BYTEA, 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';