rework deposits sharding, towards making aggregator faster (not necessarily done)

This commit is contained in:
Christian Grothoff 2022-03-24 17:33:29 +01:00
parent c782dfe2aa
commit b856d56d95
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
6 changed files with 325 additions and 177 deletions

View File

@ -28,6 +28,18 @@
#include "taler_json_lib.h" #include "taler_json_lib.h"
#include "taler_bank_service.h" #include "taler_bank_service.h"
struct AdditionalDeposit
{
/**
* Public key of the coin.
*/
struct TALER_CoinSpendPublicKeyP coin_pub;
/**
* Row of the deposit.
*/
uint64_t row;
};
/** /**
* Information about one aggregation process to be executed. There is * Information about one aggregation process to be executed. There is
@ -42,6 +54,11 @@ struct AggregationUnit
*/ */
struct TALER_MerchantPublicKeyP merchant_pub; struct TALER_MerchantPublicKeyP merchant_pub;
/**
* Public key of the coin.
*/
struct TALER_CoinSpendPublicKeyP coin_pub;
/** /**
* Total amount to be transferred, before subtraction of @e fees.wire and rounding down. * Total amount to be transferred, before subtraction of @e fees.wire and rounding down.
*/ */
@ -97,7 +114,8 @@ struct AggregationUnit
/** /**
* Array of row_ids from the aggregation. * Array of row_ids from the aggregation.
*/ */
uint64_t additional_rows[TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT]; struct AdditionalDeposit
additional_rows[TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT];
/** /**
* Offset specifying how many @e additional_rows are in use. * Offset specifying how many @e additional_rows are in use.
@ -383,7 +401,8 @@ deposit_cb (void *cls,
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
au->merchant_pub = *merchant_pub; au->merchant_pub = *merchant_pub;
GNUNET_log (GNUNET_ERROR_TYPE_INFO, au->coin_pub = *coin_pub;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Aggregator processing payment %s with amount %s\n", "Aggregator processing payment %s with amount %s\n",
TALER_B2S (coin_pub), TALER_B2S (coin_pub),
TALER_amount2s (amount_with_fee)); TALER_amount2s (amount_with_fee));
@ -405,7 +424,7 @@ deposit_cb (void *cls,
{ {
struct TALER_Amount ntotal; struct TALER_Amount ntotal;
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Non-refunded transaction, subtracting deposit fee %s\n", "Non-refunded transaction, subtracting deposit fee %s\n",
TALER_amount2s (deposit_fee)); TALER_amount2s (deposit_fee));
if (0 > if (0 >
@ -428,6 +447,9 @@ deposit_cb (void *cls,
au->total_amount = ntotal; au->total_amount = ntotal;
} }
} }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Amount after fee is %s\n",
TALER_amount2s (&au->total_amount));
GNUNET_assert (NULL == au->payto_uri); GNUNET_assert (NULL == au->payto_uri);
au->payto_uri = GNUNET_strdup (payto_uri); au->payto_uri = GNUNET_strdup (payto_uri);
@ -437,7 +459,7 @@ deposit_cb (void *cls,
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
&au->wtid, &au->wtid,
sizeof (au->wtid)); sizeof (au->wtid));
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Starting aggregation under H(WTID)=%s, starting amount %s at %llu\n", "Starting aggregation under H(WTID)=%s, starting amount %s at %llu\n",
TALER_B2S (&au->wtid), TALER_B2S (&au->wtid),
TALER_amount2s (amount_with_fee), TALER_amount2s (amount_with_fee),
@ -493,7 +515,7 @@ deposit_cb (void *cls,
"Aggregator marks deposit %llu as done\n", "Aggregator marks deposit %llu as done\n",
(unsigned long long) row_id); (unsigned long long) row_id);
qs = db_plugin->mark_deposit_done (db_plugin->cls, qs = db_plugin->mark_deposit_done (db_plugin->cls,
merchant_pub, coin_pub,
row_id); row_id);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
{ {
@ -528,6 +550,8 @@ aggregate_cb (void *cls,
struct TALER_Amount old; struct TALER_Amount old;
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
if (row_id == au->row_id)
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
if (au->rows_offset >= TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) if (au->rows_offset >= TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT)
{ {
/* Bug: we asked for at most #TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT results! */ /* Bug: we asked for at most #TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT results! */
@ -605,18 +629,29 @@ aggregate_cb (void *cls,
} }
/* "append" to our list of rows */ /* "append" to our list of rows */
au->additional_rows[au->rows_offset++] = row_id; au->additional_rows[au->rows_offset].coin_pub = *coin_pub;
au->additional_rows[au->rows_offset].row = row_id;
au->rows_offset++;
/* insert into aggregation tracking table */ /* insert into aggregation tracking table */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Adding %llu to aggregate %s\n",
(unsigned long long) row_id,
TALER_B2S (&au->wtid));
qs = db_plugin->insert_aggregation_tracking (db_plugin->cls, qs = db_plugin->insert_aggregation_tracking (db_plugin->cls,
&au->wtid, &au->wtid,
row_id); row_id);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to add %llu to aggregate %s: %d\n",
(unsigned long long) row_id,
TALER_B2S (&au->wtid),
qs);
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
return qs; return qs;
} }
qs = db_plugin->mark_deposit_done (db_plugin->cls, qs = db_plugin->mark_deposit_done (db_plugin->cls,
&au->merchant_pub, coin_pub,
row_id); row_id);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
{ {
@ -775,7 +810,7 @@ run_aggregation (void *cls)
} }
/* Now try to find other deposits to aggregate */ /* Now try to find other deposits to aggregate */
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Found ready deposit for %s, aggregating by target %llu\n", "Found ready deposit for %s, aggregating by target %llu\n",
TALER_B2S (&au_active.merchant_pub), TALER_B2S (&au_active.merchant_pub),
(unsigned long long) au_active.wire_target); (unsigned long long) au_active.wire_target);
@ -808,13 +843,17 @@ run_aggregation (void *cls)
s); s);
return; return;
} }
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Found %d other deposits to combine into wire transfer.\n", "Found %d other deposits to combine into wire transfer with fee %s.\n",
qs); qs,
TALER_amount2s (&au_active.fees.wire));
/* Subtract wire transfer fee and round to the unit supported by the /* Subtract wire transfer fee and round to the unit supported by the
wire transfer method; Check if after rounding down, we still have wire transfer method; Check if after rounding down, we still have
an amount to transfer, and if not mark as 'tiny'. */ an amount to transfer, and if not mark as 'tiny'. */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Rounding aggregate of %s\n",
TALER_amount2s (&au_active.total_amount));
if ( (0 >= if ( (0 >=
TALER_amount_subtract (&au_active.final_amount, TALER_amount_subtract (&au_active.final_amount,
&au_active.total_amount, &au_active.total_amount,
@ -822,8 +861,7 @@ run_aggregation (void *cls)
(GNUNET_SYSERR == (GNUNET_SYSERR ==
TALER_amount_round_down (&au_active.final_amount, TALER_amount_round_down (&au_active.final_amount,
&currency_round_unit)) || &currency_round_unit)) ||
( (0 == au_active.final_amount.value) && (TALER_amount_is_zero (&au_active.final_amount)) )
(0 == au_active.final_amount.fraction) ) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Aggregate value too low for transfer (%d/%s)\n", "Aggregate value too low for transfer (%d/%s)\n",
@ -848,23 +886,29 @@ run_aggregation (void *cls)
return; return;
} }
/* Mark transactions by row_id as minor */ /* Mark transactions by row_id as minor */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Marking %s (%llu) as tiny\n",
TALER_B2S (&au_active.coin_pub),
(unsigned long long) au_active.row_id);
qs = db_plugin->mark_deposit_tiny (db_plugin->cls, qs = db_plugin->mark_deposit_tiny (db_plugin->cls,
&au_active.merchant_pub, &au_active.coin_pub,
au_active.row_id); au_active.row_id);
if (0 <= qs) if (0 < qs)
{ {
for (unsigned int i = 0; i<au_active.rows_offset; i++) for (unsigned int i = 0; i<au_active.rows_offset; i++)
{ {
qs = db_plugin->mark_deposit_tiny (db_plugin->cls, qs = db_plugin->mark_deposit_tiny (db_plugin->cls,
&au_active.merchant_pub, &au_active.additional_rows[i].
au_active.additional_rows[i]); coin_pub,
if (0 > qs) au_active.additional_rows[i].row);
if (0 >= qs)
break; break;
} }
} }
GNUNET_break (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs);
if (GNUNET_DB_STATUS_SOFT_ERROR == qs) if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Serialization issue, trying again later!\n"); "Serialization issue, trying again later!\n");
db_plugin->rollback (db_plugin->cls); db_plugin->rollback (db_plugin->cls);
cleanup_au (&au_active); cleanup_au (&au_active);
@ -876,6 +920,7 @@ run_aggregation (void *cls)
} }
if (GNUNET_DB_STATUS_HARD_ERROR == qs) if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{ {
GNUNET_break (0);
db_plugin->rollback (db_plugin->cls); db_plugin->rollback (db_plugin->cls);
cleanup_au (&au_active); cleanup_au (&au_active);
global_ret = EXIT_FAILURE; global_ret = EXIT_FAILURE;

View File

@ -55,6 +55,8 @@ DROP TABLE IF EXISTS wire_targets CASCADE;
DROP FUNCTION IF EXISTS add_constraints_to_wire_targets_partition; DROP FUNCTION IF EXISTS add_constraints_to_wire_targets_partition;
DROP TABLE IF EXISTS wire_fee CASCADE; DROP TABLE IF EXISTS wire_fee CASCADE;
DROP TABLE IF EXISTS deposits CASCADE; DROP TABLE IF EXISTS deposits CASCADE;
DROP TABLE IF EXISTS deposits_by_ready CASCADE;
DROP TABLE IF EXISTS deposits_for_matching CASCADE;
DROP FUNCTION IF EXISTS add_constraints_to_deposits_partition; DROP FUNCTION IF EXISTS add_constraints_to_deposits_partition;
DROP TABLE IF EXISTS extension_details CASCADE; DROP TABLE IF EXISTS extension_details CASCADE;
DROP TABLE IF EXISTS refunds CASCADE; DROP TABLE IF EXISTS refunds CASCADE;
@ -88,6 +90,7 @@ DROP TABLE IF EXISTS recoup_by_reserve CASCADE;
DROP TABLE IF EXISTS partners CASCADE; DROP TABLE IF EXISTS partners CASCADE;
DROP TABLE IF EXISTS account_merges CASCADE; DROP TABLE IF EXISTS account_merges CASCADE;
DROP TABLE IF EXISTS purse_merges CASCADE; DROP TABLE IF EXISTS purse_merges CASCADE;
DROP TABLE IF EXISTS purse_deposits CASCADE;
DROP TABLE IF EXISTS contracts CASCADE; DROP TABLE IF EXISTS contracts CASCADE;
DROP TABLE IF EXISTS history_requests CASCADE; DROP TABLE IF EXISTS history_requests CASCADE;
DROP TABLE IF EXISTS close_requests CASCADE; DROP TABLE IF EXISTS close_requests CASCADE;
@ -103,8 +106,9 @@ DROP FUNCTION IF EXISTS exchange_do_withdraw;
DROP FUNCTION IF EXISTS exchange_do_withdraw_limit_check; DROP FUNCTION IF EXISTS exchange_do_withdraw_limit_check;
DROP FUNCTION IF EXISTS recoup_insert_trigger; DROP FUNCTION IF EXISTS recoup_insert_trigger;
DROP FUNCTION IF EXISTS recoup_delete_trigger; DROP FUNCTION IF EXISTS recoup_delete_trigger;
DROP FUNCTION IF EXISTS deposits_by_coin_insert_trigger; DROP FUNCTION IF EXISTS deposits_insert_trigger;
DROP FUNCTION IF EXISTS deposits_by_coin_delete_trigger; DROP FUNCTION IF EXISTS deposits_update_trigger;
DROP FUNCTION IF EXISTS deposits_delete_trigger;
DROP FUNCTION IF EXISTS reserves_out_by_reserve_insert_trigger; DROP FUNCTION IF EXISTS reserves_out_by_reserve_insert_trigger;
DROP FUNCTION IF EXISTS reserves_out_by_reserve_delete_trigger; DROP FUNCTION IF EXISTS reserves_out_by_reserve_delete_trigger;
DROP FUNCTION IF EXISTS exchange_do_deposit; DROP FUNCTION IF EXISTS exchange_do_deposit;

View File

@ -610,7 +610,7 @@ CREATE TABLE IF NOT EXISTS deposits
(deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- PRIMARY KEY (deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- PRIMARY KEY
,shard INT8 NOT NULL ,shard INT8 NOT NULL
,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32) -- REFERENCES known_coins (coin_pub) ON DELETE CASCADE ,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32) -- REFERENCES known_coins (coin_pub) ON DELETE CASCADE
,known_coin_id BIGINT NOT NULL -- REFERENCES known_coins (known_coin_id) ON DELETE CASCADE ,known_coin_id BIGINT NOT NULL -- REFERENCES known_coins (known_coin_id) ON DELETE CASCADE --- FIXME: column needed???
,amount_with_fee_val INT8 NOT NULL ,amount_with_fee_val INT8 NOT NULL
,amount_with_fee_frac INT4 NOT NULL ,amount_with_fee_frac INT4 NOT NULL
,wallet_timestamp INT8 NOT NULL ,wallet_timestamp INT8 NOT NULL
@ -626,22 +626,11 @@ CREATE TABLE IF NOT EXISTS deposits
,done BOOLEAN NOT NULL DEFAULT FALSE ,done BOOLEAN NOT NULL DEFAULT FALSE
,extension_blocked BOOLEAN NOT NULL DEFAULT FALSE ,extension_blocked BOOLEAN NOT NULL DEFAULT FALSE
,extension_details_serial_id INT8 REFERENCES extension_details (extension_details_serial_id) ON DELETE CASCADE ,extension_details_serial_id INT8 REFERENCES extension_details (extension_details_serial_id) ON DELETE CASCADE
,UNIQUE (shard, coin_pub, merchant_pub, h_contract_terms) ,UNIQUE (coin_pub, merchant_pub, h_contract_terms)
) )
PARTITION BY HASH (shard); -- FIXME: why not BY RANGE? RANGE would seem better for 'deposits_get_ready'! PARTITION BY HASH (coin_pub);
-- FIXME: -- FIXME:
-- new idea: partition deposits by coin_pub (remove deposits_by_coin) -- TODO: dynamically (!) creating/deleting partitions:
-- define 'ready' == ! (tiny || done || blocked)
-- add new deposits_by_ready (on shard + wire_deadline), select by shard, then ready + deadline
-- -- use triggers to ONLY include 'ready' deposits (delete on update)!
-- -- use multi-level partitions: Hash(shard) + Range(wire_deadline/sec)
-- add new deposits_by_match (on shard + refund_deadline)
-- -- use triggers to ONLY include 'ready' deposits (delete on update)!
-- -- use multi-level partitions: Hash(shard) + Range(refund_deadline/sec)
-- => first we select per-merchant shard, basically stay on the same system as other ops for the same merchant
-- => second we select by deadline, use enough values so that _usually_ the aggregator
-- and the 'insert' process _can_ work on different shards!
-- => the latter could be achieved by dynamically (!) creating/deleting partitions:
-- create new partitions 'as needed', drop old ones once the aggregator has made -- create new partitions 'as needed', drop old ones once the aggregator has made
-- them empty; as 'new' deposits will always have deadlines in the future, this -- them empty; as 'new' deposits will always have deadlines in the future, this
-- would basically guarantee no conflict between aggregator and exchange service! -- would basically guarantee no conflict between aggregator and exchange service!
@ -683,31 +672,15 @@ COMMENT ON COLUMN deposits.extension_details_serial_id
COMMENT ON COLUMN deposits.tiny COMMENT ON COLUMN deposits.tiny
IS 'Set to TRUE if we decided that the amount is too small to ever trigger a wire transfer by itself (requires real aggregation)'; IS 'Set to TRUE if we decided that the amount is too small to ever trigger a wire transfer by itself (requires real aggregation)';
-- FIXME: we sometimes go ONLY by 'deposit_serial_id',
-- check if queries could be improved by adding shard or adding another index without shard here, or inverting the order of the index here!
CREATE INDEX IF NOT EXISTS deposits_deposit_by_serial_id_index CREATE INDEX IF NOT EXISTS deposits_deposit_by_serial_id_index
ON deposits ON deposits
(shard,deposit_serial_id); (shard,deposit_serial_id);
CREATE INDEX IF NOT EXISTS deposits_for_get_ready_index
ON deposits
(shard ASC
,done
,extension_blocked
,tiny
,wire_deadline ASC
);
COMMENT ON INDEX deposits_for_get_ready_index
IS 'for deposits_get_ready';
CREATE INDEX IF NOT EXISTS deposits_for_iterate_matching_index CREATE INDEX IF NOT EXISTS deposits_by_coin_pub_index
ON deposits ON deposits
(shard (coin_pub);
,merchant_pub
,wire_target_h_payto
,done
,extension_blocked
,refund_deadline ASC
);
COMMENT ON INDEX deposits_for_iterate_matching_index
IS 'for deposits_iterate_matching';
CREATE TABLE IF NOT EXISTS deposits_default CREATE TABLE IF NOT EXISTS deposits_default
@ -732,66 +705,198 @@ $$;
SELECT add_constraints_to_deposits_partition('default'); SELECT add_constraints_to_deposits_partition('default');
CREATE TABLE IF NOT EXISTS deposits_by_ready
CREATE TABLE IF NOT EXISTS deposits_by_coin (wire_deadline INT8 NOT NULL
(deposit_serial_id BIGINT
,shard INT8 NOT NULL ,shard INT8 NOT NULL
,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32) ,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)
,deposit_serial_id INT8
) )
PARTITION BY HASH (coin_pub); PARTITION BY RANGE (wire_deadline);
COMMENT ON TABLE deposits_by_coin COMMENT ON TABLE deposits_by_ready
IS 'Enables fast lookups of deposit by coin_pub, auto-populated via TRIGGER below'; IS 'Enables fast lookups for deposits_get_ready, auto-populated via TRIGGER below';
CREATE INDEX IF NOT EXISTS deposits_by_coin_main_index CREATE INDEX IF NOT EXISTS deposits_by_ready_main_index
ON deposits_by_coin ON deposits_by_ready
(coin_pub); (wire_deadline ASC, shard ASC, coin_pub);
CREATE TABLE IF NOT EXISTS deposits_by_coin_default CREATE TABLE IF NOT EXISTS deposits_by_ready_default
PARTITION OF deposits_by_coin PARTITION OF deposits_by_ready
FOR VALUES WITH (MODULUS 1, REMAINDER 0); DEFAULT;
CREATE OR REPLACE FUNCTION deposits_by_coin_insert_trigger()
CREATE TABLE IF NOT EXISTS deposits_for_matching
(refund_deadline INT8 NOT NULL
,shard INT8 NOT NULL
,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)
,deposit_serial_id INT8
)
PARTITION BY RANGE (refund_deadline);
COMMENT ON TABLE deposits_for_matching
IS 'Enables fast lookups for deposits_iterate_matching, auto-populated via TRIGGER below';
CREATE INDEX IF NOT EXISTS deposits_for_matching_main_index
ON deposits_for_matching
(refund_deadline ASC, shard, coin_pub);
CREATE TABLE IF NOT EXISTS deposits_for_matching_default
PARTITION OF deposits_for_matching
DEFAULT;
CREATE OR REPLACE FUNCTION deposits_insert_trigger()
RETURNS trigger RETURNS trigger
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
DECLARE
is_ready BOOLEAN;
DECLARE
is_tready BOOLEAN; -- is ready, but may be tiny
BEGIN BEGIN
INSERT INTO deposits_by_coin is_ready = NOT (NEW.done OR NEW.tiny OR NEW.extension_blocked);
(deposit_serial_id is_tready = NOT (NEW.done OR NEW.extension_blocked);
,shard
,coin_pub) IF (is_ready)
VALUES THEN
(NEW.deposit_serial_id INSERT INTO deposits_by_ready
,NEW.shard (wire_deadline
,NEW.coin_pub); ,shard
,coin_pub
,deposit_serial_id)
VALUES
(NEW.wire_deadline
,NEW.shard
,NEW.coin_pub
,NEW.deposit_serial_id);
END IF;
IF (is_tready)
THEN
INSERT INTO deposits_for_matching
(refund_deadline
,shard
,coin_pub
,deposit_serial_id)
VALUES
(NEW.refund_deadline
,NEW.shard
,NEW.coin_pub
,NEW.deposit_serial_id);
END IF;
RETURN NEW; RETURN NEW;
END $$; END $$;
COMMENT ON FUNCTION deposits_by_coin_insert_trigger() COMMENT ON FUNCTION deposits_insert_trigger()
IS 'Replicate deposit inserts into deposits_by_coin table.'; IS 'Replicate deposit inserts into materialized indices.';
CREATE TRIGGER deposits_on_insert CREATE TRIGGER deposits_on_insert
AFTER INSERT AFTER INSERT
ON deposits ON deposits
FOR EACH ROW EXECUTE FUNCTION deposits_by_coin_insert_trigger(); FOR EACH ROW EXECUTE FUNCTION deposits_insert_trigger();
CREATE OR REPLACE FUNCTION deposits_by_coin_delete_trigger() CREATE OR REPLACE FUNCTION deposits_update_trigger()
RETURNS trigger RETURNS trigger
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
DECLARE
was_ready BOOLEAN;
DECLARE
is_ready BOOLEAN;
DECLARE
was_tready BOOLEAN; -- was ready, but may be tiny
DECLARE
is_tready BOOLEAN; -- is ready, but may be tiny
BEGIN BEGIN
DELETE FROM deposits_by_coin was_ready = NOT (OLD.done OR OLD.tiny OR OLD.extension_blocked);
WHERE coin_pub = OLD.coin_pub is_ready = NOT (NEW.done OR NEW.tiny OR NEW.extension_blocked);
AND shard = OLD.shard was_tready = NOT (OLD.done OR OLD.extension_blocked);
AND deposit_serial_id = OLD.deposit_serial_id; is_tready = NOT (NEW.done OR NEW.extension_blocked);
RETURN OLD; IF (was_ready AND NOT is_ready)
THEN
DELETE FROM deposits_by_ready
WHERE wire_deadline = OLD.wire_deadline
AND shard = OLD.shard
AND coin_pub = OLD.coin_pub
AND deposit_serial_id = OLD.deposit_serial_id;
END IF;
IF (was_tready AND NOT is_tready)
THEN
DELETE FROM deposits_for_matching
WHERE refund_deadline = OLD.refund_deadline
AND shard = OLD.shard
AND coin_pub = OLD.coin_pub
AND deposit_serial_id = OLD.deposit_serial_id;
END IF;
IF (is_ready AND NOT was_ready)
THEN
INSERT INTO deposits_by_ready
(wire_deadline
,shard
,coin_pub
,deposit_serial_id)
VALUES
(NEW.wire_deadline
,NEW.shard
,NEW.coin_pub
,NEW.deposit_serial_id);
END IF;
IF (is_tready AND NOT was_tready)
THEN
INSERT INTO deposits_for_matching
(refund_deadline
,shard
,coin_pub
,deposit_serial_id)
VALUES
(NEW.refund_deadline
,NEW.shard
,NEW.coin_pub
,NEW.deposit_serial_id);
END IF;
RETURN NEW;
END $$;
COMMENT ON FUNCTION deposits_update_trigger()
IS 'Replicate deposits changes into materialized indices.';
CREATE TRIGGER deposits_on_update
AFTER UPDATE
ON deposits
FOR EACH ROW EXECUTE FUNCTION deposits_update_trigger();
CREATE OR REPLACE FUNCTION deposits_delete_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
was_ready BOOLEAN;
DECLARE
was_tready BOOLEAN; -- is ready, but may be tiny
BEGIN
was_ready = NOT (OLD.done OR OLD.tiny OR OLD.extension_blocked);
was_tready = NOT (OLD.done OR OLD.extension_blocked);
IF (was_ready)
THEN
DELETE FROM deposits_by_ready
WHERE wire_deadline = OLD.wire_deadline
AND shard = OLD.shard
AND coin_pub = OLD.coin_pub
AND deposit_serial_id = OLD.deposit_serial_id;
END IF;
IF (was_tready)
THEN
DELETE FROM deposits_for_matching
WHERE refund_deadline = OLD.refund_deadline
AND shard = OLD.shard
AND coin_pub = OLD.coin_pub
AND deposit_serial_id = OLD.deposit_serial_id;
END IF;
RETURN NEW;
END $$; END $$;
COMMENT ON FUNCTION deposits_by_coin_delete_trigger() COMMENT ON FUNCTION deposits_delete_trigger()
IS 'Replicate deposits deletions into deposits_by_coin table.'; IS 'Replicate deposit deletions into materialized indices.';
CREATE TRIGGER deposits_on_delete CREATE TRIGGER deposits_on_delete
AFTER DELETE AFTER DELETE
ON deposits ON deposits
FOR EACH ROW EXECUTE FUNCTION deposits_by_coin_delete_trigger(); FOR EACH ROW EXECUTE FUNCTION deposits_delete_trigger();
CREATE TABLE IF NOT EXISTS refunds CREATE TABLE IF NOT EXISTS refunds
@ -2011,7 +2116,7 @@ DECLARE
BEGIN BEGIN
-- Shards: INSERT extension_details (by extension_details_serial_id) -- Shards: INSERT extension_details (by extension_details_serial_id)
-- INSERT wire_targets (by h_payto), on CONFLICT DO NOTHING; -- INSERT wire_targets (by h_payto), on CONFLICT DO NOTHING;
-- INSERT deposits (by shard + merchant_pub + h_payto), ON CONFLICT DO NOTHING; -- INSERT deposits (by coin_pub, shard), ON CONFLICT DO NOTHING;
-- UPDATE known_coins (by coin_pub) -- UPDATE known_coins (by coin_pub)
IF NOT NULL in_extension_details IF NOT NULL in_extension_details
@ -2356,27 +2461,26 @@ DECLARE
DECLARE DECLARE
deposit_frac INT8; -- amount that was originally deposited deposit_frac INT8; -- amount that was originally deposited
BEGIN BEGIN
-- Shards: SELECT deposits (by shard, coin_pub, h_contract_terms, merchant_pub) -- Shards: SELECT deposits (coin_pub, shard, h_contract_terms, merchant_pub)
-- INSERT refunds (by deposit_serial_id, rtransaction_id) ON CONFLICT DO NOTHING -- INSERT refunds (by deposit_serial_id, rtransaction_id) ON CONFLICT DO NOTHING
-- SELECT refunds (by deposit_serial_id) -- SELECT refunds (by deposit_serial_id)
-- UPDATE known_coins (by coin_pub) -- UPDATE known_coins (by coin_pub)
SELECT SELECT
dep.deposit_serial_id deposit_serial_id
,dep.amount_with_fee_val ,amount_with_fee_val
,dep.amount_with_fee_frac ,amount_with_fee_frac
,dep.done ,done
INTO INTO
dsi dsi
,deposit_val ,deposit_val
,deposit_frac ,deposit_frac
,out_gone ,out_gone
FROM deposits_by_coin dbc FROM deposits
JOIN deposits dep USING (shard,deposit_serial_id) WHERE coin_pub=in_coin_pub
WHERE dbc.coin_pub=in_coin_pub AND shard=in_deposit_shard
AND dep.shard=in_deposit_shard AND merchant_pub=in_merchant_pub
AND dep.merchant_pub=in_merchant_pub AND h_contract_terms=in_h_contract_terms;
AND dep.h_contract_terms=in_h_contract_terms;
IF NOT FOUND IF NOT FOUND
THEN THEN

View File

@ -990,12 +990,11 @@ prepare_statements (struct PostgresClosure *pg)
",rtransaction_id " ",rtransaction_id "
",amount_with_fee_val " ",amount_with_fee_val "
",amount_with_fee_frac " ",amount_with_fee_frac "
") SELECT dbc.deposit_serial_id, $3, $5, $6, $7" ") SELECT deposit_serial_id, $3, $5, $6, $7"
" FROM deposits_by_coin dbc" " FROM deposits" /* FIXME: check if adding additional AND on the 'shard' would help (possibly after reviewing indices on deposits!) */
" JOIN deposits dep USING (shard,deposit_serial_id)" " WHERE coin_pub=$1"
" WHERE dbc.coin_pub=$1" " AND h_contract_terms=$4"
" AND dep.h_contract_terms=$4" " AND merchant_pub=$2",
" AND dep.merchant_pub=$2",
7), 7),
/* Query the 'refunds' by coin public key */ /* Query the 'refunds' by coin public key */
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
@ -1010,12 +1009,11 @@ prepare_statements (struct PostgresClosure *pg)
",denom.fee_refund_val " ",denom.fee_refund_val "
",denom.fee_refund_frac " ",denom.fee_refund_frac "
",ref.refund_serial_id" ",ref.refund_serial_id"
" FROM deposits_by_coin dbc" " FROM deposits dep"
" JOIN refunds ref USING (deposit_serial_id)" " JOIN refunds ref USING (deposit_serial_id)"
" JOIN deposits dep ON (dbc.shard = dep.shard AND dbc.deposit_serial_id = dep.deposit_serial_id)" " JOIN known_coins kc ON (dep.coin_pub = kc.coin_pub)"
" JOIN known_coins kc ON (dbc.coin_pub = kc.coin_pub)"
" JOIN denominations denom USING (denominations_serial)" " JOIN denominations denom USING (denominations_serial)"
" WHERE dbc.coin_pub=$1;", " WHERE dep.coin_pub=$1;",
1), 1),
/* Query the 'refunds' by coin public key, merchant_pub and contract hash */ /* Query the 'refunds' by coin public key, merchant_pub and contract hash */
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
@ -1023,10 +1021,9 @@ prepare_statements (struct PostgresClosure *pg)
"SELECT" "SELECT"
" ref.amount_with_fee_val" " ref.amount_with_fee_val"
",ref.amount_with_fee_frac" ",ref.amount_with_fee_frac"
" FROM deposits_by_coin dbc" " FROM deposits dep"
" JOIN refunds ref USING (shard,deposit_serial_id)" " JOIN refunds ref USING (shard,deposit_serial_id)"
" JOIN deposits dep ON (dbc.shard = dep.shard AND dbc.deposit_serial_id = dep.deposit_serial_id)" " WHERE dep.coin_pub=$1"
" WHERE dbc.coin_pub=$1"
" AND dep.merchant_pub=$2" " AND dep.merchant_pub=$2"
" AND dep.h_contract_terms=$3;", " AND dep.h_contract_terms=$3;",
3), 3),
@ -1053,6 +1050,7 @@ prepare_statements (struct PostgresClosure *pg)
/* Lock deposit table; NOTE: we may want to eventually shard the /* Lock deposit table; NOTE: we may want to eventually shard the
deposit table to avoid this lock being the main point of deposit table to avoid this lock being the main point of
contention limiting transaction performance. */ contention limiting transaction performance. */
// FIXME: check if this query is even still used!
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
"lock_deposit", "lock_deposit",
"LOCK TABLE deposits;", "LOCK TABLE deposits;",
@ -1098,12 +1096,11 @@ prepare_statements (struct PostgresClosure *pg)
",dep.h_contract_terms" ",dep.h_contract_terms"
",dep.wire_salt" ",dep.wire_salt"
",wt.payto_uri AS receiver_wire_account" ",wt.payto_uri AS receiver_wire_account"
" FROM deposits_by_coin dbc" " FROM deposits dep"
" JOIN deposits dep USING (shard,deposit_serial_id)" " JOIN known_coins kc ON (kc.coin_pub = dep.coin_pub)"
" JOIN known_coins kc ON (kc.coin_pub = dbc.coin_pub)"
" JOIN denominations USING (denominations_serial)" " JOIN denominations USING (denominations_serial)"
" JOIN wire_targets wt USING (wire_target_h_payto)" " JOIN wire_targets wt USING (wire_target_h_payto)"
" WHERE dbc.coin_pub=$1" " WHERE dep.coin_pub=$1"
" AND dep.merchant_pub=$3" " AND dep.merchant_pub=$3"
" AND dep.h_contract_terms=$2;", " AND dep.h_contract_terms=$2;",
3), 3),
@ -1150,12 +1147,11 @@ prepare_statements (struct PostgresClosure *pg)
",denom.fee_deposit_val" ",denom.fee_deposit_val"
",denom.fee_deposit_frac" ",denom.fee_deposit_frac"
",dep.wire_deadline" ",dep.wire_deadline"
" FROM deposits_by_coin dbc" " FROM deposits dep"
" JOIN deposits dep USING (shard,deposit_serial_id)"
" JOIN wire_targets wt USING (wire_target_h_payto)" " JOIN wire_targets wt USING (wire_target_h_payto)"
" JOIN known_coins kc ON (kc.coin_pub = dbc.coin_pub)" " JOIN known_coins kc ON (kc.coin_pub = dep.coin_pub)"
" JOIN denominations denom USING (denominations_serial)" " JOIN denominations denom USING (denominations_serial)"
" WHERE dbc.coin_pub=$1" " WHERE dep.coin_pub=$1"
" AND dep.merchant_pub=$3" " AND dep.merchant_pub=$3"
" AND dep.h_contract_terms=$2;", " AND dep.h_contract_terms=$2;",
3), 3),
@ -1163,7 +1159,7 @@ prepare_statements (struct PostgresClosure *pg)
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
"deposits_get_ready", "deposits_get_ready",
"SELECT" "SELECT"
" deposit_serial_id" " dep.deposit_serial_id"
",amount_with_fee_val" ",amount_with_fee_val"
",amount_with_fee_frac" ",amount_with_fee_frac"
",denom.fee_deposit_val" ",denom.fee_deposit_val"
@ -1173,47 +1169,46 @@ prepare_statements (struct PostgresClosure *pg)
",wire_target_serial_id" ",wire_target_serial_id"
",merchant_pub" ",merchant_pub"
",kc.coin_pub" ",kc.coin_pub"
" FROM deposits" " FROM deposits_by_ready dbr"
" JOIN deposits dep"
" ON (dbr.coin_pub = dep.coin_pub AND dbr.deposit_serial_id = dep.deposit_serial_id)"
" JOIN wire_targets " " JOIN wire_targets "
" USING (wire_target_h_payto)" " USING (wire_target_h_payto)"
" JOIN known_coins kc" " JOIN known_coins kc"
" USING (coin_pub)" " ON (kc.coin_pub = dep.coin_pub)"
" JOIN denominations denom" " JOIN denominations denom"
" USING (denominations_serial)" " USING (denominations_serial)"
" WHERE " " WHERE dbr.wire_deadline<=$1"
" shard >= $2" " AND dbr.shard >= $2"
" AND shard <= $3" " AND dbr.shard <= $3"
" AND done=FALSE"
" AND extension_blocked=FALSE"
" AND tiny=FALSE"
" AND wire_deadline<=$1"
" AND (kyc_ok OR $4)" " AND (kyc_ok OR $4)"
" ORDER BY " " ORDER BY "
" shard ASC" " dbr.wire_deadline ASC"
" ,wire_deadline ASC" " ,dbr.shard ASC"
" LIMIT 1;", " LIMIT 1;",
4), 4),
/* Used in #postgres_iterate_matching_deposits() */ /* Used in #postgres_iterate_matching_deposits() */
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
"deposits_iterate_matching", "deposits_iterate_matching",
"SELECT" "SELECT"
" deposit_serial_id" " dep.deposit_serial_id"
",amount_with_fee_val" ",dep.amount_with_fee_val"
",amount_with_fee_frac" ",dep.amount_with_fee_frac"
",denom.fee_deposit_val" ",denom.fee_deposit_val"
",denom.fee_deposit_frac" ",denom.fee_deposit_frac"
",h_contract_terms" ",dep.h_contract_terms"
",kc.coin_pub" ",dfm.coin_pub"
" FROM deposits" " FROM deposits_for_matching dfm"
" JOIN known_coins kc USING (coin_pub)" " JOIN deposits dep "
" JOIN denominations denom USING (denominations_serial)" " ON (dep.coin_pub = dfm.coin_pub and dep.deposit_serial_id = dfm.deposit_serial_id)"
" WHERE shard=$4" " JOIN known_coins kc"
" AND merchant_pub=$1" " ON (dep.coin_pub = kc.coin_pub)"
" AND wire_target_h_payto=$2" " JOIN denominations denom"
" AND done=FALSE" " USING (denominations_serial)"
" AND extension_blocked=FALSE" " WHERE dfm.refund_deadline<$3"
" AND refund_deadline<$3" " AND dfm.shard=$4"
" ORDER BY refund_deadline ASC" " AND dep.merchant_pub=$1"
" AND dep.wire_target_h_payto=$2"
" LIMIT " " LIMIT "
TALER_QUOTE ( TALER_QUOTE (
TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) ";", TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) ";",
@ -1223,16 +1218,16 @@ prepare_statements (struct PostgresClosure *pg)
"mark_deposit_tiny", "mark_deposit_tiny",
"UPDATE deposits" "UPDATE deposits"
" SET tiny=TRUE" " SET tiny=TRUE"
" WHERE shard=$2" " WHERE coin_pub=$1"
" AND deposit_serial_id=$1", " AND deposit_serial_id=$2",
2), 2),
/* Used in #postgres_mark_deposit_done() */ /* Used in #postgres_mark_deposit_done() */
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
"mark_deposit_done", "mark_deposit_done",
"UPDATE deposits" "UPDATE deposits"
" SET done=TRUE" " SET done=TRUE"
" WHERE shard=$2" " WHERE coin_pub=$1"
" AND deposit_serial_id=$1;", " AND deposit_serial_id=$2;",
2), 2),
/* Used in #postgres_get_coin_transactions() to obtain information /* Used in #postgres_get_coin_transactions() to obtain information
about how a coin has been spend with /deposit requests. */ about how a coin has been spend with /deposit requests. */
@ -1255,16 +1250,14 @@ prepare_statements (struct PostgresClosure *pg)
",dep.coin_sig" ",dep.coin_sig"
",dep.deposit_serial_id" ",dep.deposit_serial_id"
",dep.done" ",dep.done"
" FROM deposits_by_coin dbc" " FROM deposits dep"
" JOIN deposits dep"
" USING (shard,deposit_serial_id)"
" JOIN wire_targets wt" " JOIN wire_targets wt"
" USING (wire_target_h_payto)" " USING (wire_target_h_payto)"
" JOIN known_coins kc" " JOIN known_coins kc"
" ON (kc.coin_pub = dbc.coin_pub)" " ON (kc.coin_pub = dep.coin_pub)"
" JOIN denominations denoms" " JOIN denominations denoms"
" USING (denominations_serial)" " USING (denominations_serial)"
" WHERE dbc.coin_pub=$1;", " WHERE dep.coin_pub=$1;",
1), 1),
/* Used in #postgres_get_link_data(). */ /* Used in #postgres_get_link_data(). */
@ -1329,20 +1322,18 @@ prepare_statements (struct PostgresClosure *pg)
",wt.payto_uri" ",wt.payto_uri"
",denom.fee_deposit_val" ",denom.fee_deposit_val"
",denom.fee_deposit_frac" ",denom.fee_deposit_frac"
" FROM deposits_by_coin dbc" " FROM deposits dep"
" JOIN deposits dep"
" USING (shard,deposit_serial_id)"
" JOIN wire_targets wt" " JOIN wire_targets wt"
" USING (wire_target_h_payto)" " USING (wire_target_h_payto)"
" JOIN aggregation_tracking" " JOIN aggregation_tracking"
" USING (deposit_serial_id)" " USING (deposit_serial_id)"
" JOIN known_coins kc" " JOIN known_coins kc"
" ON (kc.coin_pub = dbc.coin_pub)" " ON (kc.coin_pub = dep.coin_pub)"
" JOIN denominations denom" " JOIN denominations denom"
" USING (denominations_serial)" " USING (denominations_serial)"
" JOIN wire_out" " JOIN wire_out"
" USING (wtid_raw)" " USING (wtid_raw)"
" WHERE dbc.coin_pub=$1" " WHERE dep.coin_pub=$1"
" AND dep.merchant_pub=$3" " AND dep.merchant_pub=$3"
" AND dep.h_contract_terms=$2", " AND dep.h_contract_terms=$2",
3), 3),
@ -5898,14 +5889,13 @@ postgres_have_deposit2 (
*/ */
static enum GNUNET_DB_QueryStatus static enum GNUNET_DB_QueryStatus
postgres_mark_deposit_tiny (void *cls, postgres_mark_deposit_tiny (void *cls,
const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub,
uint64_t rowid) uint64_t rowid)
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
uint64_t deposit_shard = compute_shard (merchant_pub);
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (coin_pub),
GNUNET_PQ_query_param_uint64 (&rowid), GNUNET_PQ_query_param_uint64 (&rowid),
GNUNET_PQ_query_param_uint64 (&deposit_shard),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
@ -5927,14 +5917,13 @@ postgres_mark_deposit_tiny (void *cls,
*/ */
static enum GNUNET_DB_QueryStatus static enum GNUNET_DB_QueryStatus
postgres_mark_deposit_done (void *cls, postgres_mark_deposit_done (void *cls,
const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub,
uint64_t rowid) uint64_t rowid)
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
uint64_t deposit_shard = compute_shard (merchant_pub);
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (coin_pub),
GNUNET_PQ_query_param_uint64 (&rowid), GNUNET_PQ_query_param_uint64 (&rowid),
GNUNET_PQ_query_param_uint64 (&deposit_shard),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
@ -6431,6 +6420,12 @@ postgres_insert_deposit (void *cls,
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
return qs; return qs;
} }
if (GNUNET_TIME_timestamp_cmp (deposit->wire_deadline,
<,
deposit->refund_deadline))
{
GNUNET_break (0);
}
{ {
uint64_t shard = compute_shard (&deposit->merchant_pub); uint64_t shard = compute_shard (&deposit->merchant_pub);
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {

View File

@ -2284,7 +2284,7 @@ run (void *cls)
"test-2")); "test-2"));
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->mark_deposit_tiny (plugin->cls, plugin->mark_deposit_tiny (plugin->cls,
&deposit.merchant_pub, &deposit.coin.coin_pub,
deposit_rowid)); deposit_rowid));
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
plugin->get_ready_deposit (plugin->cls, plugin->get_ready_deposit (plugin->cls,
@ -2306,7 +2306,7 @@ run (void *cls)
"test-3")); "test-3"));
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->mark_deposit_done (plugin->cls, plugin->mark_deposit_done (plugin->cls,
&deposit.merchant_pub, &deposit.coin.coin_pub,
deposit_rowid)); deposit_rowid));
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
plugin->commit (plugin->cls)); plugin->commit (plugin->cls));

View File

@ -3060,13 +3060,13 @@ struct TALER_EXCHANGEDB_Plugin
* returned by @e iterate_ready_deposits() * returned by @e iterate_ready_deposits()
* *
* @param cls the @e cls of this struct with the plugin-specific state * @param cls the @e cls of this struct with the plugin-specific state
* @param merchant_pub identifies the beneficiary of the deposit * @param coin_pub identifies the coin of the deposit
* @param deposit_rowid identifies the deposit row to modify * @param deposit_rowid identifies the deposit row to modify
* @return query result status * @return query result status
*/ */
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
(*mark_deposit_tiny)(void *cls, (*mark_deposit_tiny)(void *cls,
const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub,
uint64_t rowid); uint64_t rowid);
@ -3076,13 +3076,13 @@ struct TALER_EXCHANGEDB_Plugin
* @e iterate_ready_deposits() or @e iterate_matching_deposits(). * @e iterate_ready_deposits() or @e iterate_matching_deposits().
* *
* @param cls the @e cls of this struct with the plugin-specific state * @param cls the @e cls of this struct with the plugin-specific state
* @param merchant_pub identifies the beneficiary of the deposit * @param coin_pub identifies the coin of the deposit
* @param deposit_rowid identifies the deposit row to modify * @param deposit_rowid identifies the deposit row to modify
* @return query result status * @return query result status
*/ */
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
(*mark_deposit_done)(void *cls, (*mark_deposit_done)(void *cls,
const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub,
uint64_t rowid); uint64_t rowid);