aboutsummaryrefslogtreecommitdiff
path: root/src/exchangedb/exchange-0001.sql
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchangedb/exchange-0001.sql')
-rw-r--r--src/exchangedb/exchange-0001.sql220
1 files changed, 157 insertions, 63 deletions
diff --git a/src/exchangedb/exchange-0001.sql b/src/exchangedb/exchange-0001.sql
index df07e0252..3f9979c06 100644
--- a/src/exchangedb/exchange-0001.sql
+++ b/src/exchangedb/exchange-0001.sql
@@ -1,6 +1,6 @@
--
-- This file is part of TALER
--- Copyright (C) 2014--2021 Taler Systems SA
+-- 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
@@ -22,7 +22,7 @@ SELECT _v.register_patch('exchange-0001', NULL, NULL);
CREATE TABLE IF NOT EXISTS denominations
- (denominations_serial BIGSERIAL UNIQUE
+ (denominations_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)
,denom_type INT4 NOT NULL DEFAULT (1) -- 1 == RSA (for now, remove default later!)
,age_mask INT4 NOT NULL DEFAULT (0)
@@ -58,7 +58,7 @@ CREATE INDEX IF NOT EXISTS denominations_by_expire_legal_index
CREATE TABLE IF NOT EXISTS denomination_revocations
- (denom_revocations_serial_id BIGSERIAL UNIQUE
+ (denom_revocations_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,denominations_serial INT8 PRIMARY KEY REFERENCES denominations (denominations_serial) ON DELETE CASCADE
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
);
@@ -67,7 +67,7 @@ COMMENT ON TABLE denomination_revocations
CREATE TABLE IF NOT EXISTS wire_targets
- (wire_target_serial_id BIGSERIAL -- UNIQUE
+ (wire_target_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,h_payto BYTEA PRIMARY KEY CHECK (LENGTH(h_payto)=64)
,payto_uri VARCHAR NOT NULL
,kyc_ok BOOLEAN NOT NULL DEFAULT (FALSE)
@@ -89,7 +89,7 @@ CREATE TABLE IF NOT EXISTS wire_targets_default
FOR VALUES WITH (MODULUS 1, REMAINDER 0);
CREATE TABLE IF NOT EXISTS reserves
- (reserve_uuid BIGSERIAL
+ (reserve_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY
,reserve_pub BYTEA PRIMARY KEY CHECK(LENGTH(reserve_pub)=32)
,current_balance_val INT8 NOT NULL
,current_balance_frac INT4 NOT NULL
@@ -130,7 +130,7 @@ COMMENT ON INDEX reserves_by_gc_date_index
CREATE TABLE IF NOT EXISTS reserves_in
- (reserve_in_serial_id BIGSERIAL -- UNIQUE
+ (reserve_in_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,reserve_pub BYTEA PRIMARY KEY REFERENCES reserves (reserve_pub) ON DELETE CASCADE
,wire_reference INT8 NOT NULL
,credit_val INT8 NOT NULL
@@ -168,7 +168,7 @@ CREATE INDEX IF NOT EXISTS reserves_in_by_exchange_account_reserve_in_serial_id_
CREATE TABLE IF NOT EXISTS reserves_close
- (close_uuid BIGSERIAL -- UNIQUE / PRIMARY KEY
+ (close_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE / PRIMARY KEY
,reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE CASCADE
,execution_date INT8 NOT NULL
,wtid BYTEA NOT NULL CHECK (LENGTH(wtid)=32)
@@ -195,8 +195,7 @@ CREATE INDEX IF NOT EXISTS reserves_close_by_reserve_pub_index
CREATE TABLE IF NOT EXISTS reserves_out
- (reserve_out_serial_id BIGSERIAL -- UNIQUE
- ,wih BYTEA PRIMARY KEY CHECK (LENGTH(wih)=64)
+ (reserve_out_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,h_blind_ev BYTEA CHECK (LENGTH(h_blind_ev)=64) -- UNIQUE
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial)
,denom_sig BYTEA NOT NULL
@@ -206,11 +205,9 @@ CREATE TABLE IF NOT EXISTS reserves_out
,amount_with_fee_val INT8 NOT NULL
,amount_with_fee_frac INT4 NOT NULL
)
- PARTITION BY HASH (wih);
+ PARTITION BY HASH (h_blind_ev);
COMMENT ON TABLE reserves_out
IS 'Withdraw operations performed on reserves.';
-COMMENT ON COLUMN reserves_out.wih
- IS 'Hash that uniquely identifies the withdraw request. Used to detect request replays (crucial for CS) and to check the withdraw existed during recoup.';
COMMENT ON COLUMN reserves_out.h_blind_ev
IS 'Hash of the blinded coin, used as primary key here so that broken clients that use a non-random coin or blinding factor fail to withdraw (otherwise they would fail on deposit when the coin is not unique there).';
COMMENT ON COLUMN reserves_out.denominations_serial
@@ -230,7 +227,7 @@ COMMENT ON INDEX reserves_out_by_reserve_uuid_and_execution_date_index
CREATE TABLE IF NOT EXISTS auditors
- (auditor_uuid BIGSERIAL UNIQUE
+ (auditor_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,auditor_pub BYTEA PRIMARY KEY CHECK (LENGTH(auditor_pub)=32)
,auditor_name VARCHAR NOT NULL
,auditor_url VARCHAR NOT NULL
@@ -250,7 +247,7 @@ COMMENT ON COLUMN auditors.last_change
CREATE TABLE IF NOT EXISTS auditor_denom_sigs
- (auditor_denom_serial BIGSERIAL UNIQUE
+ (auditor_denom_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,auditor_uuid INT8 NOT NULL REFERENCES auditors (auditor_uuid) ON DELETE CASCADE
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ON DELETE CASCADE
,auditor_sig BYTEA CHECK (LENGTH(auditor_sig)=64)
@@ -267,7 +264,7 @@ COMMENT ON COLUMN auditor_denom_sigs.auditor_sig
CREATE TABLE IF NOT EXISTS exchange_sign_keys
- (esk_serial BIGSERIAL UNIQUE
+ (esk_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,exchange_pub BYTEA PRIMARY KEY CHECK (LENGTH(exchange_pub)=32)
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
,valid_from INT8 NOT NULL
@@ -289,7 +286,7 @@ COMMENT ON COLUMN exchange_sign_keys.expire_legal
CREATE TABLE IF NOT EXISTS signkey_revocations
- (signkey_revocations_serial_id BIGSERIAL UNIQUE
+ (signkey_revocations_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,esk_serial INT8 PRIMARY KEY REFERENCES exchange_sign_keys (esk_serial) ON DELETE CASCADE
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
);
@@ -298,7 +295,7 @@ COMMENT ON TABLE signkey_revocations
CREATE TABLE IF NOT EXISTS extensions
- (extension_id BIGSERIAL UNIQUE
+ (extension_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,name VARCHAR NOT NULL UNIQUE
,config BYTEA
);
@@ -311,7 +308,7 @@ COMMENT ON COLUMN extensions.config
CREATE TABLE IF NOT EXISTS known_coins
- (known_coin_id BIGSERIAL -- UNIQUE
+ (known_coin_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ON DELETE CASCADE
,coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (LENGTH(coin_pub)=32)
,age_hash BYTEA CHECK (LENGTH(age_hash)=32)
@@ -342,7 +339,7 @@ CREATE INDEX IF NOT EXISTS known_coins_by_known_coin_id_index
CREATE TABLE IF NOT EXISTS refresh_commitments
- (melt_serial_id BIGSERIAL -- UNIQUE
+ (melt_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,rc BYTEA PRIMARY KEY CHECK (LENGTH(rc)=64)
,old_coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE
,h_age_commitment BYTEA CHECK(LENGTH(h_age_commitment)=32)
@@ -375,7 +372,7 @@ CREATE INDEX IF NOT EXISTS refresh_commitments_by_old_coin_pub_index
CREATE TABLE IF NOT EXISTS refresh_revealed_coins
- (rrc_serial BIGSERIAL -- UNIQUE
+ (rrc_serial BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,melt_serial_id INT8 NOT NULL -- REFERENCES refresh_commitments (melt_serial_id) ON DELETE CASCADE
,freshcoin_index INT4 NOT NULL
,link_sig BYTEA NOT NULL CHECK(LENGTH(link_sig)=64)
@@ -419,7 +416,7 @@ CREATE INDEX IF NOT EXISTS refresh_revealed_coins_by_melt_serial_id_index
CREATE TABLE IF NOT EXISTS refresh_transfer_keys
- (rtc_serial BIGSERIAL -- UNIQUE
+ (rtc_serial BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,melt_serial_id INT8 PRIMARY KEY -- REFERENCES refresh_commitments (melt_serial_id) ON DELETE CASCADE
,transfer_pub BYTEA NOT NULL CHECK(LENGTH(transfer_pub)=32)
,transfer_privs BYTEA NOT NULL
@@ -445,7 +442,7 @@ CREATE INDEX IF NOT EXISTS refresh_transfer_keys_by_rtc_serial_index
CREATE TABLE IF NOT EXISTS extension_details
- (extension_details_serial_id BIGSERIAL PRIMARY KEY
+ (extension_details_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
,extension_options VARCHAR);
COMMENT ON TABLE extension_details
IS 'Extensions that were provided with deposits (not yet used).';
@@ -454,7 +451,7 @@ COMMENT ON COLUMN extension_details.extension_options
CREATE TABLE IF NOT EXISTS deposits
- (deposit_serial_id BIGSERIAL -- PRIMARY KEY
+ (deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- PRIMARY KEY
,shard INT8 NOT NULL
,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id) ON DELETE CASCADE
,amount_with_fee_val INT8 NOT NULL
@@ -526,7 +523,7 @@ COMMENT ON INDEX deposits_for_iterate_matching_index
CREATE TABLE IF NOT EXISTS refunds
- (refund_serial_id BIGSERIAL -- UNIQUE
+ (refund_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,deposit_serial_id INT8 NOT NULL -- REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE
,merchant_sig BYTEA NOT NULL CHECK(LENGTH(merchant_sig)=64)
,rtransaction_id INT8 NOT NULL
@@ -553,7 +550,7 @@ CREATE INDEX IF NOT EXISTS refunds_by_refund_serial_id_index
CREATE TABLE IF NOT EXISTS wire_out
- (wireout_uuid BIGSERIAL -- PRIMARY KEY
+ (wireout_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- PRIMARY KEY
,execution_date INT8 NOT NULL
,wtid_raw BYTEA UNIQUE NOT NULL CHECK (LENGTH(wtid_raw)=32)
,wire_target_serial_id INT8 NOT NULL -- REFERENCES wire_targets (wire_target_serial_id)
@@ -582,7 +579,7 @@ CREATE INDEX IF NOT EXISTS wire_out_by_wire_target_serial_id_index
CREATE TABLE IF NOT EXISTS aggregation_tracking
- (aggregation_serial_id BIGSERIAL -- UNIQUE
+ (aggregation_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,deposit_serial_id INT8 PRIMARY KEY -- REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE
,wtid_raw BYTEA CONSTRAINT wire_out_ref REFERENCES wire_out(wtid_raw) ON DELETE CASCADE DEFERRABLE
)
@@ -606,7 +603,7 @@ COMMENT ON INDEX aggregation_tracking_by_wtid_raw_index
CREATE TABLE IF NOT EXISTS wire_fee
- (wire_fee_serial BIGSERIAL UNIQUE
+ (wire_fee_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,wire_method VARCHAR NOT NULL
,start_date INT8 NOT NULL
,end_date INT8 NOT NULL
@@ -628,7 +625,7 @@ CREATE INDEX IF NOT EXISTS wire_fee_by_end_date_index
CREATE TABLE IF NOT EXISTS recoup
- (recoup_uuid BIGSERIAL -- UNIQUE
+ (recoup_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id)
,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)
,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)
@@ -643,7 +640,7 @@ COMMENT ON TABLE recoup
COMMENT ON COLUMN recoup.known_coin_id
IS 'Coin that is being debited in the recoup. Do not CASCADE ON DROP on the coin_pub, as we may keep the coin alive!';
COMMENT ON COLUMN recoup.reserve_out_serial_id
- IS 'Identifies the wih of the recouped coin and provides the link to the credited reserve.';
+ IS 'Identifies the h_blind_ev of the recouped coin and provides the link to the credited reserve.';
COMMENT ON COLUMN recoup.coin_sig
IS 'Signature by the coin affirming the recoup, of type TALER_SIGNATURE_WALLET_COIN_RECOUP';
COMMENT ON COLUMN recoup.coin_blind
@@ -664,7 +661,7 @@ CREATE INDEX IF NOT EXISTS recoup_by_known_coin_id_index
CREATE TABLE IF NOT EXISTS recoup_refresh
- (recoup_refresh_uuid BIGSERIAL -- UNIQUE
+ (recoup_refresh_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id)
,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)
,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)
@@ -698,7 +695,7 @@ CREATE INDEX IF NOT EXISTS recoup_refresh_by_known_coin_id_index
CREATE TABLE IF NOT EXISTS prewire
- (prewire_uuid BIGSERIAL PRIMARY KEY
+ (prewire_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
,wire_method TEXT NOT NULL
,finished BOOLEAN NOT NULL DEFAULT false
,failed BOOLEAN NOT NULL DEFAULT false
@@ -746,12 +743,29 @@ 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.';
--- "wire_accounts" has no BIGSERIAL because it is a 'mutable' table
+-- "wire_accounts" has no sequence because it is a 'mutable' table
-- and is of no concern to the auditor
+CREATE TABLE IF NOT EXISTS cs_nonce_locks
+ (cs_nonce_lock_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
+ ,nonce BYTEA PRIMARY KEY CHECK (LENGTH(nonce)=32)
+ ,op_hash BYTEA NOT NULL CHECK (LENGTH(op_hash)=64)
+ ,max_denomination_serial INT8 NOT NULL
+ )
+ PARTITION BY HASH (nonce);
+COMMENT ON TABLE cs_nonce_locks
+ IS 'ensures a Clause Schnorr client nonce is locked for use with an operation identified by a hash';
+COMMENT ON COLUMN cs_nonce_locks.nonce
+ IS 'actual nonce submitted by the client';
+COMMENT ON COLUMN cs_nonce_locks.op_hash
+ IS 'hash (RC for refresh, blind coin hash for withdraw) the nonce may be used with';
+COMMENT ON COLUMN cs_nonce_locks.max_denomination_serial
+ IS 'Maximum number of a CS denomination serial the nonce could be used with, for GC';
+
+
CREATE TABLE IF NOT EXISTS work_shards
- (shard_serial_id BIGSERIAL UNIQUE
+ (shard_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,last_attempt INT8 NOT NULL
,start_row INT8 NOT NULL
,end_row INT8 NOT NULL
@@ -783,7 +797,7 @@ CREATE INDEX IF NOT EXISTS work_shards_by_job_name_completed_last_attempt_index
CREATE UNLOGGED TABLE IF NOT EXISTS revolving_work_shards
- (shard_serial_id BIGSERIAL UNIQUE
+ (shard_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,last_attempt INT8 NOT NULL
,start_row INT4 NOT NULL
,end_row INT4 NOT NULL
@@ -818,7 +832,7 @@ CREATE INDEX IF NOT EXISTS revolving_work_shards_by_job_name_active_last_attempt
CREATE OR REPLACE FUNCTION exchange_do_withdraw(
- IN in_wih BYTEA,
+ IN cs_nonce BYTEA,
IN amount_val INT8,
IN amount_frac INT4,
IN h_denom_pub BYTEA,
@@ -832,8 +846,7 @@ CREATE OR REPLACE FUNCTION exchange_do_withdraw(
OUT balance_ok BOOLEAN,
OUT kycok BOOLEAN,
OUT account_uuid INT8,
- OUT ruuid INT8,
- OUT out_denom_sig BYTEA)
+ OUT ruuid INT8)
LANGUAGE plpgsql
AS $$
DECLARE
@@ -851,7 +864,8 @@ BEGIN
-- reserves_in by reserve_pub (SELECT)
-- wire_targets by wire_target_serial_id
-SELECT denominations_serial INTO denom_serial
+SELECT denominations_serial
+ INTO denom_serial
FROM denominations
WHERE denom_pub_hash=h_denom_pub;
@@ -867,6 +881,7 @@ THEN
RETURN;
END IF;
+
SELECT
current_balance_val
,current_balance_frac
@@ -887,7 +902,7 @@ THEN
balance_ok=FALSE;
kycok=FALSE;
account_uuid=0;
- ruuid=0;
+ ruuid=2;
RETURN;
END IF;
@@ -895,7 +910,6 @@ END IF;
-- the query successful due to idempotency.
INSERT INTO reserves_out
(h_blind_ev
- ,wih
,denominations_serial
,denom_sig
,reserve_uuid
@@ -905,7 +919,6 @@ INSERT INTO reserves_out
,amount_with_fee_frac)
VALUES
(h_coin_envelope
- ,in_wih
,denom_serial
,denom_sig
,ruuid
@@ -918,25 +931,6 @@ ON CONFLICT DO NOTHING;
IF NOT FOUND
THEN
-- idempotent query, all constraints must be satisfied
-
- SELECT
- denom_sig
- INTO
- out_denom_sig
- FROM reserves_in
- WHERE wih=in_wih
- LIMIT 1; -- limit 1 should not be required (without p2p transfers)
-
- IF NOT FOUND
- THEN
- reserve_found=FALSE;
- balance_ok=FALSE;
- kycok=FALSE;
- account_uuid=0;
- ruuid=0;
- ASSERT false, 'internal logic error';
- END IF;
-
reserve_found=TRUE;
balance_ok=TRUE;
kycok=TRUE;
@@ -983,6 +977,44 @@ WHERE
reserve_found=TRUE;
balance_ok=TRUE;
+
+
+-- Special actions needed for a CS withdraw?
+IF NOT NULL cs_nonce
+THEN
+ -- Cache CS signature to prevent replays in the future
+ -- (and check if cached signature exists at the same time).
+ INSERT INTO cs_nonce_locks
+ (nonce
+ ,max_denomination_serial
+ ,op_hash)
+ VALUES
+ (cs_nonce
+ ,denom_serial
+ ,h_coin_envelope)
+ ON CONFLICT DO NOTHING;
+
+ IF NOT FOUND
+ THEN
+ -- See if the existing entry is identical.
+ SELECT 1
+ FROM cs_nonce_locks
+ WHERE nonce=cs_nonce
+ AND op_hash=h_coin_envelope;
+ IF NOT FOUND
+ THEN
+ reserve_found=FALSE;
+ balance_ok=FALSE;
+ kycok=FALSE;
+ account_uuid=0;
+ ruuid=1; -- FIXME: return error message more nicely!
+ ASSERT false, 'nonce reuse attempted by client';
+ END IF;
+ END IF;
+END IF;
+
+
+
-- Obtain KYC status based on the last wire transfer into
-- this reserve. FIXME: likely not adequate for reserves that got P2P transfers!
SELECT
@@ -996,9 +1028,6 @@ SELECT
WHERE reserve_pub=rpub
LIMIT 1; -- limit 1 should not be required (without p2p transfers)
--- Return denomination signature as result that
--- was given as the argument.
-out_denom_sig=denom_sig;
END $$;
@@ -1223,6 +1252,7 @@ END $$;
CREATE OR REPLACE FUNCTION exchange_do_melt(
+ IN in_cs_rms BYTEA,
IN in_amount_with_fee_val INT8,
IN in_amount_with_fee_frac INT4,
IN in_rc BYTEA,
@@ -1236,6 +1266,8 @@ CREATE OR REPLACE FUNCTION exchange_do_melt(
OUT out_noreveal_index INT4)
LANGUAGE plpgsql
AS $$
+DECLARE
+ denom_max INT8;
BEGIN
-- Shards: INSERT refresh_commitments (by rc)
-- (rare:) SELECT refresh_commitments (by old_coin_pub) -- crosses shards!
@@ -1333,6 +1365,56 @@ THEN
RETURN;
END IF;
+
+
+-- Special actions needed for a CS melt?
+IF NOT NULL in_cs_rms
+THEN
+ -- Get maximum denominations serial value in
+ -- existence, this will determine how long the
+ -- nonce will be locked.
+ SELECT
+ denominations_serial
+ INTO
+ denom_max
+ FROM denominations
+ ORDER BY denominations_serial DESC
+ LIMIT 1;
+
+ -- Cache CS signature to prevent replays in the future
+ -- (and check if cached signature exists at the same time).
+ INSERT INTO cs_nonce_locks
+ (nonce
+ ,max_denomination_serial
+ ,op_hash)
+ VALUES
+ (cs_rms
+ ,denom_serial
+ ,in_rc)
+ ON CONFLICT DO NOTHING;
+
+ IF NOT FOUND
+ THEN
+ -- Record exists, make sure it is the same
+ SELECT 1
+ FROM cs_nonce_locks
+ WHERE nonce=cs_rms
+ AND op_hash=in_rc;
+
+ IF NOT FOUND
+ THEN
+ -- Nonce reuse detected
+ out_balance_ok=FALSE;
+ out_zombie_bad=FALSE;
+ out_noreveal_index=42; -- FIXME: return error message more nicely!
+ ASSERT false, 'nonce reuse attempted by client';
+ END IF;
+ END IF;
+END IF;
+
+
+
+
-- Everything fine, return success!
out_balance_ok=TRUE;
out_noreveal_index=in_noreveal_index;
@@ -1806,6 +1888,8 @@ DECLARE
deposit_min INT8; -- minimum deposit still alive
DECLARE
reserve_out_min INT8; -- minimum reserve_out still alive
+DECLARE
+ denom_min INT8; -- minimum denomination still alive
BEGIN
DELETE FROM prewire
@@ -1901,6 +1985,16 @@ DELETE FROM refunds
DELETE FROM aggregation_tracking
WHERE deposit_serial_id < deposit_min;
+SELECT
+ denominations_serial
+ INTO
+ denom_min
+ FROM denominations
+ ORDER BY denominations_serial ASC
+ LIMIT 1;
+
+DELETE FROM cs_nonce_locks
+ WHERE max_denomination_serial <= denom_min;
END $$;