Merge branch 'master' into ar
This commit is contained in:
commit
fe457bb7ba
130
src/exchangedb/withdraw.sql
Normal file
130
src/exchangedb/withdraw.sql
Normal 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';
|
||||
|
Loading…
Reference in New Issue
Block a user