diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-04-05 17:15:50 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-04-05 17:15:50 +0200 |
commit | f3a4b00907410444055f47d4ff2074b44f981ad3 (patch) | |
tree | cb8f191a285152649e0b780aad8154f5b819f924 /src/exchangedb | |
parent | 71916414069d18ec5b7d5901d52d62a2aaa1403d (diff) |
adapt to latest GNUnet API: GNUNET_JSON_spec_mark_optional() changed
Diffstat (limited to 'src/exchangedb')
-rw-r--r-- | src/exchangedb/exchange-0001-part.sql | 96 | ||||
-rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 104 |
2 files changed, 186 insertions, 14 deletions
diff --git a/src/exchangedb/exchange-0001-part.sql b/src/exchangedb/exchange-0001-part.sql index c068ff6f9..2c416f03e 100644 --- a/src/exchangedb/exchange-0001-part.sql +++ b/src/exchangedb/exchange-0001-part.sql @@ -2469,22 +2469,108 @@ END $$; - - - - CREATE OR REPLACE FUNCTION exchange_do_purse_deposit( + IN in_partner_id INT8, IN in_purse_pub BYTEA, IN in_amount_with_fee_val INT8, IN in_amount_with_fee_frac INT4, IN in_coin_pub BYTEA, IN in_coin_sig BYTEA, + IN in_amount_without_fee_val INT8, + IN in_amount_without_fee_frac INT4, OUT out_balance_ok BOOLEAN, OUT out_conflict BOOLEAN) LANGUAGE plpgsql AS $$ BEGIN - -- FIXME + +-- Store the deposit request. +INSERT INTO purse_deposits + (partner_serial_id + ,purse_pub + ,coin_pub + ,amount_with_fee_val + ,amount_with_fee_frac + ,coin_sig) + VALUES + (in_partner_id + ,in_purse_pub + ,in_coin_pub + ,in_amount_with_fee_val + ,in_amount_with_fee_frac + ,in_coin_sig) + ON CONFLICT DO NOTHING; + +IF NOT FOUND +THEN + -- Idempotency check: check if coin_sig is the same, + -- if so, success, otherwise conflict! + SELECT + 1 + FROM purse_deposits + WHERE coin_pub = in_coin_pub + AND purse_pub = in_purse_pub + AND coin_sig = in_cion_sig; + IF NOT FOUND + THEN + -- Deposit exists, but with differences. Not allowed. + out_balance_ok=FALSE; + out_conflict=TRUE; + RETURN; + END IF; +END IF; + + +-- Debit the coin +-- Check and update balance of the coin. +UPDATE known_coins + SET + remaining_frac=remaining_frac-in_amount_with_fee_frac + + CASE + WHEN remaining_frac < in_amount_with_fee_frac + THEN 100000000 + ELSE 0 + END, + remaining_val=remaining_val-in_amount_with_fee_val + - CASE + WHEN remaining_frac < in_amount_with_fee_frac + THEN 1 + ELSE 0 + END + WHERE coin_pub=in_coin_pub + AND ( (remaining_val > in_amount_with_fee_val) OR + ( (remaining_frac >= in_amount_with_fee_frac) AND + (remaining_val >= in_amount_with_fee_val) ) ); + +IF NOT FOUND +THEN + -- Insufficient balance. + out_balance_ok=FALSE; + out_conflict=FALSE; + RETURN; +END IF; + + +-- Credit the purse. +UPDATE purse_requests + SET + balance_frac=balance_frac+in_amount_without_fee_frac + - CASE + WHEN balance_frac+in_amount_without_fee_frac >= 100000000 + THEN 100000000 + ELSE 0 + END, + balance_val=balance_val+in_amount_without_fee_val + + CASE + WHEN balance_frac+in_amount_without_fee_frac >= 100000000 + THEN 1 + ELSE 0 + END + WHERE purse_pub=in_purse_pub; + +out_conflict=FALSE; +out_balance_ok=TRUE; + END $$; diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 64cc0a77e..aed69725b 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -799,6 +799,15 @@ prepare_statements (struct PostgresClosure *pg) " FROM exchange_do_deposit" " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17);", 17), + /* used in postgres_do_purse_deposit() */ + GNUNET_PQ_make_prepare ( + "call_purse_deposit", + "SELECT " + " out_balance_ok AS balance_ok" + ",out_conflict AS conflict" + " FROM exchange_do_purse_deposit" + " ($1,$2,$3,$4,$5,$6,$7,$8);", + 8), /* Used in #postgres_do_melt() to melt a coin. */ GNUNET_PQ_make_prepare ( "call_melt", @@ -3342,13 +3351,19 @@ prepare_statements (struct PostgresClosure *pg) " FROM purse_requests" " WHERE merge_pub=$1;", 1), - /* Used in #postgres_do_purse_deposit() */ + /* Used in #postgres_get_purse_deposit */ GNUNET_PQ_make_prepare ( - "call_purse_deposit", - "SELECT 1" - " FROM exchange_do_purse_deposit" - " ($1, $2, $3, $4, $5);", - 5), + "select_purse_deposit_by_coin_pub", + "SELECT " + " coin_sig" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",partner_base_url" + " FROM purse_deposits" + " LEFT JOIN partners USING (partner_serial_id)" + " WHERE coin_pub=$2" + " AND purse_pub=$1;", + 2), /* Used in #postgres_do_purse_merge() */ GNUNET_PQ_make_prepare ( "call_purse_merge", @@ -13181,10 +13196,79 @@ postgres_do_purse_deposit ( const struct TALER_Amount *amount, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_Amount *amount_minus_fee, - bool *balance_ok) + bool *balance_ok, + bool *conflict) { - GNUNET_break (0); // FIXME - return GNUNET_DB_STATUS_HARD_ERROR; + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (0), /* FIXME: partner ID */ + GNUNET_PQ_query_param_auto_from_type (purse_pub), + TALER_PQ_query_param_amount (amount), + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_auto_from_type (coin_sig), + TALER_PQ_query_param_amount (amount_minus_fee), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("balance_ok", + balance_ok), + GNUNET_PQ_result_spec_bool ("conflict", + conflict), + GNUNET_PQ_result_spec_end + }; + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_purse_deposit", + params, + rs); +} + + +/** + * Function called to obtain a coin deposit data from + * depositing the coin into a purse. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to credit + * @param coin_pub coin to deposit (debit) + * @param[out] amount set fraction of the coin's value that was deposited (with fee) + * @param[out] coin_sig set to signature affirming the operation + * @param[out] partner_url set to the URL of the partner exchange, or NULL for ourselves, must be freed by caller + * @return transaction status code + */ +static enum GNUNET_DB_QueryStatus +postgres_get_purse_deposit ( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_Amount *amount, + struct TALER_CoinSpendSignatureP *coin_sig, + char **partner_url) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_end + }; + bool is_null; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + coin_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + amount), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("partner_base_url", + partner_url), + &is_null), + GNUNET_PQ_result_spec_end + }; + + *partner_url = NULL; + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_purse_deposit_by_coin_pub", + params, + rs); } @@ -13589,6 +13673,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) = &postgres_select_purse_by_merge_pub; plugin->do_purse_deposit = &postgres_do_purse_deposit; + plugin->get_purse_deposit + = &postgres_get_purse_deposit; plugin->do_purse_merge = &postgres_do_purse_merge; plugin->select_purse_merge |