commit 6a879a63af5b71f07d098181f449e537ba3135f3
parent 2a3fb278f3d32feca6077eead2551ee8d11b40b8
Author: Özgür Kesim <oec@codeblau.de>
Date: Tue, 6 May 2025 16:01:22 +0200
Removal of linking protocol
With the new refresh protocol introduced with v27, there is no need
for the /linking protocol anymore: The history data on an old coin is sufficient
to re-create a the fresh coin(s) by the owner of the private key of the old coin.
This commit removes the REST-API endpoint to /linking, the C-API support
for it and the database plugin components.
Diffstat:
12 files changed, 0 insertions(+), 1360 deletions(-)
diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am
@@ -173,7 +173,6 @@ taler_exchange_httpd_SOURCES = \
taler-exchange-httpd_kyc-wallet.c taler-exchange-httpd_kyc-wallet.h \
taler-exchange-httpd_kyc-webhook.c taler-exchange-httpd_kyc-webhook.h \
taler-exchange-httpd_legitimization-measures-get.c taler-exchange-httpd_legitimization-measures-get.h \
- taler-exchange-httpd_link.c taler-exchange-httpd_link.h \
taler-exchange-httpd_management.h \
taler-exchange-httpd_management_aml-officers.c \
taler-exchange-httpd_management_auditors.c \
diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c
@@ -57,7 +57,6 @@
#include "taler-exchange-httpd_kyc-webhook.h"
#include "taler-exchange-httpd_aml-decision.h"
#include "taler-exchange-httpd_legitimization-measures-get.h"
-#include "taler-exchange-httpd_link.h"
#include "taler-exchange-httpd_management.h"
#include "taler-exchange-httpd_melt.h"
#include "taler-exchange-httpd_melt_v27.h"
@@ -467,10 +466,6 @@ handle_get_coins (struct TEH_RequestContext *rc,
"history"))
return TEH_handler_coins_get (rc,
&coin_pub);
- if (0 == strcmp (args[1],
- "link"))
- return TEH_handler_link (rc,
- &coin_pub);
}
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_NOT_FOUND,
diff --git a/src/exchange/taler-exchange-httpd_link.c b/src/exchange/taler-exchange-httpd_link.c
@@ -1,210 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2019, 2022 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-exchange-httpd_link.c
- * @brief Handle /coins/$COIN_PUB/link requests
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <jansson.h>
-#include <microhttpd.h>
-#include "taler_mhd_lib.h"
-#include "taler-exchange-httpd_mhd.h"
-#include "taler-exchange-httpd_link.h"
-#include "taler-exchange-httpd_responses.h"
-
-
-/**
- * Closure for #handle_link_data().
- */
-struct HTD_Context
-{
-
- /**
- * Public key of the coin for which we are running link.
- */
- const struct TALER_CoinSpendPublicKeyP *coin_pub;
-
- /**
- * Json array with transfer data we collect.
- */
- json_t *mlist;
-
- /**
- * Taler error code.
- */
- enum TALER_ErrorCode ec;
-};
-
-
-/**
- * Function called with the session hashes and transfer secret
- * information for a given coin. Gets the linkage data and
- * builds the reply for the client.
- *
- * @param cls closure, a `struct HTD_Context`
- * @param transfer_pub public transfer key for the session
- * @param ldl link data related to @a transfer_pub
- */
-static void
-handle_link_data (void *cls,
- const struct TALER_TransferPublicKeyP *transfer_pub,
- const struct TALER_EXCHANGEDB_LinkList *ldl)
-{
- struct HTD_Context *ctx = cls;
- json_t *list;
-
- if (NULL == ctx->mlist)
- return; /* we failed earlier */
- if (NULL == (list = json_array ()))
- goto fail;
-
- for (const struct TALER_EXCHANGEDB_LinkList *pos = ldl;
- NULL != pos;
- pos = pos->next)
- {
- json_t *obj;
-
- obj = GNUNET_JSON_PACK (
- TALER_JSON_pack_denom_pub ("denom_pub",
- &pos->denom_pub),
- TALER_JSON_pack_blinded_denom_sig ("ev_sig",
- &pos->ev_sig),
- GNUNET_JSON_pack_uint64 ("coin_idx",
- pos->coin_refresh_offset),
- TALER_JSON_pack_exchange_blinding_values ("ewv",
- &pos->alg_values),
- GNUNET_JSON_pack_data_auto ("link_sig",
- &pos->orig_coin_link_sig),
- GNUNET_JSON_pack_allow_null (
- pos->have_nonce
- ? GNUNET_JSON_pack_data_auto ("cs_nonce",
- &pos->nonce)
- : GNUNET_JSON_pack_string ("cs_nonce",
- NULL)));
- if ( (NULL == obj) ||
- (0 !=
- json_array_append_new (list,
- obj)) )
- {
- json_decref (list);
- goto fail;
- }
- }
- {
- json_t *root;
-
- root = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_array_steal ("new_coins",
- list),
- GNUNET_JSON_pack_data_auto ("transfer_pub",
- transfer_pub));
- if ( (NULL == root) ||
- (0 !=
- json_array_append_new (ctx->mlist,
- root)) )
- goto fail;
- }
- return;
-fail:
- ctx->ec = TALER_EC_GENERIC_JSON_ALLOCATION_FAILURE;
- json_decref (ctx->mlist);
- ctx->mlist = NULL;
-}
-
-
-/**
- * Execute a link operation. Returns the linkage information that will allow
- * the owner of a coin to follow the trail to the refreshed coin.
- *
- * If it returns a non-error code, the transaction logic MUST NOT queue a MHD
- * response. IF it returns an hard error, the transaction logic MUST queue a
- * MHD response and set @a mhd_ret. IF it returns the soft error code, the
- * function MAY be called again to retry and MUST not queue a MHD response.
- *
- * @param cls closure
- * @param connection MHD request which triggered the transaction
- * @param[out] mhd_ret set to MHD response status for @a connection,
- * if transaction failed (!)
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-link_transaction (void *cls,
- struct MHD_Connection *connection,
- MHD_RESULT *mhd_ret)
-{
- struct HTD_Context *ctx = cls;
- enum GNUNET_DB_QueryStatus qs;
-
- qs = TEH_plugin->get_link_data (TEH_plugin->cls,
- ctx->coin_pub,
- &handle_link_data,
- ctx);
- if (NULL == ctx->mlist)
- {
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- ctx->ec,
- NULL);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_EXCHANGE_LINK_COIN_UNKNOWN,
- NULL);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- return qs;
-}
-
-
-MHD_RESULT
-TEH_handler_link (struct TEH_RequestContext *rc,
- const struct TALER_CoinSpendPublicKeyP *coin_pub)
-{
- struct HTD_Context ctx = {
- .coin_pub = coin_pub
- };
- MHD_RESULT mhd_ret;
-
- ctx.mlist = json_array ();
- GNUNET_assert (NULL != ctx.mlist);
- if (GNUNET_OK !=
- TEH_DB_run_transaction (rc->connection,
- "run link",
- TEH_MT_REQUEST_OTHER,
- &mhd_ret,
- &link_transaction,
- &ctx))
- {
- if (NULL != ctx.mlist)
- json_decref (ctx.mlist);
- return mhd_ret;
- }
- mhd_ret = TALER_MHD_reply_json (rc->connection,
- ctx.mlist,
- MHD_HTTP_OK);
- json_decref (ctx.mlist);
- return mhd_ret;
-}
-
-
-/* end of taler-exchange-httpd_link.c */
diff --git a/src/exchange/taler-exchange-httpd_link.h b/src/exchange/taler-exchange-httpd_link.h
@@ -1,43 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2017 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-exchange-httpd_link.h
- * @brief Handle /coins/$COIN_PUB/link requests
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#ifndef TALER_EXCHANGE_HTTPD_LINK_H
-#define TALER_EXCHANGE_HTTPD_LINK_H
-
-#include <gnunet/gnunet_util_lib.h>
-#include <microhttpd.h>
-#include "taler-exchange-httpd.h"
-
-
-/**
- * Handle a "/coins/$COIN_PUB/link" request.
- *
- * @param rc request context
- * @param coin_pub the coin public key
- * @return MHD result code
- */
-MHD_RESULT
-TEH_handler_link (struct TEH_RequestContext *rc,
- const struct TALER_CoinSpendPublicKeyP *coin_pub);
-
-
-#endif
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
@@ -208,7 +208,6 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
pg_get_global_fees.h pg_get_global_fees.c \
pg_get_known_coin.h pg_get_known_coin.c \
pg_get_kyc_rules.h pg_get_kyc_rules.c \
- pg_get_link_data.h pg_get_link_data.c \
pg_get_melt.h pg_get_melt.c \
pg_get_refresh.h pg_get_refresh.c \
pg_get_old_coin_by_h_blind.h pg_get_old_coin_by_h_blind.c \
@@ -408,7 +407,6 @@ libtalerexchangedb_la_LDFLAGS = \
noinst_PROGRAMS = \
bench-db-postgres\
- perf_get_link_data-postgres\
perf_select_refunds_by_coin-postgres\
perf_reserves_in_insert-postgres \
perf_deposits_get_ready-postgres
@@ -466,19 +464,6 @@ perf_select_refunds_by_coin_postgres_LDADD = \
-lm \
$(XLIB)
-perf_get_link_data_postgres_SOURCES = \
- perf_get_link_data.c
-perf_get_link_data_postgres_LDADD = \
- libtalerexchangedb.la \
- $(top_builddir)/src/json/libtalerjson.la \
- $(top_builddir)/src/util/libtalerutil.la \
- $(top_builddir)/src/pq/libtalerpq.la \
- -ljansson \
- -lgnunetjson \
- -lgnunetutil \
- -lm \
- $(XLIB)
-
perf_deposits_get_ready_postgres_SOURCES = \
perf_deposits_get_ready.c
perf_deposits_get_ready_postgres_LDADD = \
diff --git a/src/exchangedb/pg_get_link_data.c b/src/exchangedb/pg_get_link_data.c
@@ -1,367 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 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
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_link_data.c
- * @brief Implementation of the get_link_data function for Postgres
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_error_codes.h"
-#include "taler_dbevents.h"
-#include "taler_pq_lib.h"
-#include "pg_get_link_data.h"
-#include "pg_helper.h"
-
-
-/**
- * Closure for #add_ldl().
- */
-struct LinkDataContext
-{
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_LinkCallback ldc;
-
- /**
- * Closure for @e ldc.
- */
- void *ldc_cls;
-
- /**
- * Last transfer public key for which we have information in @e last.
- * Only valid if @e last is non-NULL.
- */
- struct TALER_TransferPublicKeyP transfer_pub;
-
- /**
- * Status, set to #GNUNET_SYSERR on errors,
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Free memory of the link data list.
- *
- * @param ldl link data list to release
- */
-static void
-free_link_data_list (struct TALER_EXCHANGEDB_LinkList *ldl)
-{
- struct TALER_EXCHANGEDB_LinkList *next;
-
- while (NULL != ldl)
- {
- next = ldl->next;
- TALER_denom_pub_free (&ldl->denom_pub);
- TALER_blinded_denom_sig_free (&ldl->ev_sig);
- TALER_denom_ewv_free (&ldl->alg_values);
- GNUNET_free (ldl);
- ldl = next;
- }
-}
-
-
-struct Results
-{
- struct TALER_EXCHANGEDB_LinkList *pos;
- struct TALER_TransferPublicKeyP transfer_pub;
-};
-
-
-static int
-transfer_pub_cmp (const void *a,
- const void *b)
-{
- const struct Results *ra = a;
- const struct Results *rb = b;
-
- return GNUNET_memcmp (&ra->transfer_pub,
- &rb->transfer_pub);
-}
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct LinkDataContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_ldl (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LinkDataContext *ldctx = cls;
- struct Results *temp = GNUNET_new_array (num_results,
- struct Results);
- unsigned int temp_off = 0;
-
- for (int i = num_results - 1; i >= 0; i--)
- {
- struct TALER_EXCHANGEDB_LinkList *pos;
-
- pos = GNUNET_new (struct TALER_EXCHANGEDB_LinkList);
- {
- struct TALER_BlindedPlanchet bp;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("transfer_pub",
- &temp[temp_off].transfer_pub),
- GNUNET_PQ_result_spec_auto_from_type ("link_sig",
- &pos->orig_coin_link_sig),
- TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
- &pos->ev_sig),
- GNUNET_PQ_result_spec_uint32 ("freshcoin_index",
- &pos->coin_refresh_offset),
- TALER_PQ_result_spec_exchange_withdraw_values ("ewv",
- &pos->alg_values),
- TALER_PQ_result_spec_denom_pub ("denom_pub",
- &pos->denom_pub),
- TALER_PQ_result_spec_blinded_planchet ("coin_ev",
- &bp),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- GNUNET_free (pos);
- ldctx->status = GNUNET_SYSERR;
- return;
- }
- if (GNUNET_CRYPTO_BSA_CS == bp.blinded_message->cipher)
- {
- pos->nonce.cs_nonce
- = bp.blinded_message->details.cs_blinded_message.nonce;
- pos->have_nonce = true;
- }
- TALER_blinded_planchet_free (&bp);
- }
- temp[temp_off].pos = pos;
- temp_off++;
- }
- qsort (temp,
- temp_off,
- sizeof (struct Results),
- &transfer_pub_cmp);
- if (temp_off > 0)
- {
- struct TALER_EXCHANGEDB_LinkList *head = NULL;
-
- head = temp[0].pos;
- for (unsigned int i = 1; i < temp_off; i++)
- {
- struct TALER_EXCHANGEDB_LinkList *pos = temp[i].pos;
- const struct TALER_TransferPublicKeyP *tp = &temp[i].transfer_pub;
-
- if (0 == GNUNET_memcmp (tp,
- &temp[i - 1].transfer_pub))
- {
- pos->next = head;
- head = pos;
- }
- else
- {
- ldctx->ldc (ldctx->ldc_cls,
- &temp[i - 1].transfer_pub,
- head);
- free_link_data_list (head);
- head = pos;
- }
- }
- ldctx->ldc (ldctx->ldc_cls,
- &temp[temp_off - 1].transfer_pub,
- head);
- free_link_data_list (head);
- }
- GNUNET_free (temp);
-}
-
-
-enum GNUNET_DB_QueryStatus
-TEH_PG_get_link_data (void *cls,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- TALER_EXCHANGEDB_LinkCallback ldc,
- void *ldc_cls)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
- struct LinkDataContext ldctx;
- static int percent_refund = -2;
- const char *query;
-
- if (-2 == percent_refund)
- {
- const char *mode = getenv ("TALER_POSTGRES_GET_LINK_DATA_LOGIC");
- char dummy;
-
- if ( (NULL==mode) ||
- (1 != sscanf (mode,
- "%d%c",
- &percent_refund,
- &dummy)) )
- {
- if (NULL != mode)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Bad mode `%s' specified\n",
- mode);
- percent_refund = 4; /* Fastest known */
- }
- }
- switch (percent_refund)
- {
- case 0:
- query = "get_link";
- PREPARE (pg,
- query,
- "SELECT "
- " tp.transfer_pub"
- ",denoms.denom_pub"
- ",rrc.ev_sig"
- ",rrc.ewv"
- ",rrc.link_sig"
- ",rrc.freshcoin_index"
- ",rrc.coin_ev"
- " FROM refresh_commitments"
- " JOIN refresh_revealed_coins rrc"
- " USING (melt_serial_id)"
- " JOIN refresh_transfer_keys tp"
- " USING (melt_serial_id)"
- " JOIN denominations denoms"
- " ON (rrc.denominations_serial = denoms.denominations_serial)"
- " WHERE old_coin_pub=$1"
- " ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
- break;
- case 1:
- query = "get_link_v1";
- PREPARE (pg,
- query,
- "WITH rc AS MATERIALIZED ("
- "SELECT"
- " melt_serial_id"
- " FROM refresh_commitments"
- " WHERE old_coin_pub=$1"
- ")"
- "SELECT "
- " tp.transfer_pub"
- ",denoms.denom_pub"
- ",rrc.ev_sig"
- ",rrc.ewv"
- ",rrc.link_sig"
- ",rrc.freshcoin_index"
- ",rrc.coin_ev "
- "FROM "
- "refresh_revealed_coins rrc"
- " JOIN refresh_transfer_keys tp"
- " USING (melt_serial_id)"
- " JOIN denominations denoms"
- " USING (denominations_serial)"
- " WHERE rrc.melt_serial_id = (SELECT melt_serial_id FROM rc)"
- " ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
- break;
- case 2:
- query = "get_link_v2";
- PREPARE (pg,
- query,
- "SELECT"
- " *"
- " FROM"
- " exchange_do_get_link_data"
- " ($1) "
- " AS "
- " (transfer_pub BYTEA"
- " ,denom_pub BYTEA"
- " ,ev_sig BYTEA"
- " ,ewv BYTEA"
- " ,link_sig BYTEA"
- " ,freshcoin_index INT4"
- " ,coin_ev BYTEA);");
- break;
- case 3:
- query = "get_link_v3";
- PREPARE (pg,
- query,
- "SELECT "
- " tp.transfer_pub"
- ",denoms.denom_pub"
- ",rrc.ev_sig"
- ",rrc.ewv"
- ",rrc.link_sig"
- ",rrc.freshcoin_index"
- ",rrc.coin_ev"
- " FROM refresh_commitments"
- " JOIN refresh_revealed_coins rrc"
- " USING (melt_serial_id)"
- " JOIN refresh_transfer_keys tp"
- " USING (melt_serial_id)"
- " JOIN denominations denoms"
- " ON (rrc.denominations_serial = denoms.denominations_serial)"
- " WHERE old_coin_pub=$1");
- break;
- case 4:
- query = "get_link_v4";
- PREPARE (pg,
- query,
- "WITH rc AS MATERIALIZED ("
- "SELECT"
- " melt_serial_id"
- " FROM refresh_commitments"
- " WHERE old_coin_pub=$1"
- ")"
- "SELECT "
- " tp.transfer_pub"
- ",denoms.denom_pub"
- ",rrc.ev_sig"
- ",rrc.ewv"
- ",rrc.link_sig"
- ",rrc.freshcoin_index"
- ",rrc.coin_ev "
- "FROM "
- "refresh_revealed_coins rrc"
- " JOIN refresh_transfer_keys tp"
- " USING (melt_serial_id)"
- " JOIN denominations denoms"
- " USING (denominations_serial)"
- " WHERE rrc.melt_serial_id = (SELECT melt_serial_id FROM rc)"
- );
- break;
- default:
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
- ldctx.ldc = ldc;
- ldctx.ldc_cls = ldc_cls;
- ldctx.status = GNUNET_OK;
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- query,
- params,
- &add_ldl,
- &ldctx);
- if (GNUNET_OK != ldctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_get_link_data.h b/src/exchangedb/pg_get_link_data.h
@@ -1,45 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 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
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_link_data.h
- * @brief implementation of the get_link_data function for Postgres
- * @author Christian Grothoff
- */
-#ifndef PG_GET_LINK_DATA_H
-#define PG_GET_LINK_DATA_H
-
-#include "taler_util.h"
-#include "taler_json_lib.h"
-#include "taler_exchangedb_plugin.h"
-
-
-/**
- * Obtain the link data of a coin, that is the encrypted link
- * information, the denomination keys and the signatures.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param coin_pub public key of the coin
- * @param ldc function to call for each session the coin was melted into
- * @param ldc_cls closure for @a tdc
- * @return transaction status code
- */
-enum GNUNET_DB_QueryStatus
-TEH_PG_get_link_data (void *cls,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- TALER_EXCHANGEDB_LinkCallback ldc,
- void *ldc_cls);
-
-#endif
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -83,7 +83,6 @@
#include "pg_get_global_fees.h"
#include "pg_get_known_coin.h"
#include "pg_get_kyc_rules.h"
-#include "pg_get_link_data.h"
#include "pg_get_melt.h"
#include "pg_get_old_coin_by_h_blind.h"
#include "pg_get_pending_kyc_requirement_process.h"
@@ -409,8 +408,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &TEH_PG_insert_close_request;
plugin->delete_aggregation_transient
= &TEH_PG_delete_aggregation_transient;
- plugin->get_link_data
- = &TEH_PG_get_link_data;
plugin->iterate_reserve_close_info
= &TEH_PG_iterate_reserve_close_info;
plugin->iterate_kyc_reference
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
@@ -4064,137 +4064,6 @@ TALER_EXCHANGE_refreshes_reveal_cancel (
struct TALER_EXCHANGE_RefreshesRevealHandle *rrh);
-/* ********************* /coins/$COIN_PUB/link ***************************** */
-
-
-/**
- * @brief A /coins/$COIN_PUB/link Handle
- */
-struct TALER_EXCHANGE_LinkHandle;
-
-
-/**
- * Information about a coin obtained via /link.
- */
-struct TALER_EXCHANGE_LinkedCoinInfo
-{
- /**
- * Private key of the coin.
- */
- struct TALER_CoinSpendPrivateKeyP coin_priv;
-
- /**
- * Age commitment and its hash, if applicable.
- */
- bool has_age_commitment;
- struct TALER_AgeCommitmentProof age_commitment_proof;
- struct TALER_AgeCommitmentHash h_age_commitment;
-
- /**
- * Master secret of this coin.
- */
- struct TALER_PlanchetMasterSecretP ps;
-
- /**
- * Signature affirming the validity of the coin.
- */
- struct TALER_DenominationSignature sig;
-
- /**
- * Denomination public key of the coin.
- */
- struct TALER_DenominationPublicKey pub;
-};
-
-
-/**
- * Result of a /link request.
- */
-struct TALER_EXCHANGE_LinkResult
-{
- /**
- * HTTP status.
- */
- struct TALER_EXCHANGE_HttpResponse hr;
-
- /**
- * Parsed response details, variant depending on the
- * @e hr.http_status.
- */
- union
- {
- /**
- * Results for status #MHD_HTTP_OK.
- */
- struct
- {
- /**
- * Array of @e num_coins values about the
- * coins obtained via linkage.
- */
- const struct TALER_EXCHANGE_LinkedCoinInfo *coins;
-
- /**
- * Number of coins returned.
- */
- unsigned int num_coins;
- } ok;
-
- } details;
-
-};
-
-
-/**
- * Callbacks of this type are used to return the final result of submitting a
- * /coins/$COIN_PUB/link request to a exchange. If the operation was
- * successful, this function returns the signatures over the coins that were
- * created when the original coin was melted.
- *
- * @param cls closure
- * @param lr result of the /link operation
- */
-typedef void
-(*TALER_EXCHANGE_LinkCallback) (
- void *cls,
- const struct TALER_EXCHANGE_LinkResult *lr);
-
-
-/**
- * Submit a link request to the exchange and get the exchange's response.
- *
- * This API is typically not used by anyone, it is more a threat against those
- * trying to receive a funds transfer by abusing the refresh protocol.
- *
- * @param ctx CURL context
- * @param url exchange base URL
- * @param coin_priv private key to request link data for
- * @param age_commitment_proof age commitment to the corresponding coin, might be NULL
- * @param link_cb the callback to call with the useful result of the
- * refresh operation the @a coin_priv was involved in (if any)
- * @param link_cb_cls closure for @a link_cb
- * @return a handle for this request
- */
-struct TALER_EXCHANGE_LinkHandle *
-TALER_EXCHANGE_link (
- struct GNUNET_CURL_Context *ctx,
- const char *url,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv,
- const struct TALER_AgeCommitmentProof *age_commitment_proof,
- TALER_EXCHANGE_LinkCallback link_cb,
- void *link_cb_cls);
-
-
-/**
- * Cancel a link request. This function cannot be used
- * on a request handle if the callback was already invoked.
- *
- * @param lh the link handle
- */
-void
-TALER_EXCHANGE_link_cancel (struct TALER_EXCHANGE_LinkHandle *lh);
-
-
/* ********************* /transfers/$WTID *********************** */
/**
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
@@ -5235,26 +5235,6 @@ struct TALER_EXCHANGEDB_Plugin
TALER_EXCHANGEDB_RefreshCallback cb,
void *cb_cls);
-
- /**
- * Obtain shared secret and transfer public key from the public key of
- * the coin. This information and the link information returned by
- * @e get_link_data_list() enable the owner of an old coin to determine
- * the private keys of the new coins after the melt.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param coin_pub public key of the coin
- * @param ldc function to call for each session the coin was melted into
- * @param ldc_cls closure for @a tdc
- * @return statement execution status
- */
- enum GNUNET_DB_QueryStatus
- (*get_link_data)(void *cls,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- TALER_EXCHANGEDB_LinkCallback ldc,
- void *tdc_cls);
-
-
/**
* Compile a list of (historic) transactions performed with the given coin
* (melt, refund, recoup and deposit operations). Should return 0 if the @a
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
@@ -39,7 +39,6 @@ libtalerexchange_la_SOURCES = \
exchange_api_kyc_proof.c \
exchange_api_kyc_start.c \
exchange_api_kyc_wallet.c \
- exchange_api_link.c \
exchange_api_lookup_aml_decisions.c \
exchange_api_lookup_kyc_attributes.c \
exchange_api_management_add_partner.c \
diff --git a/src/lib/exchange_api_link.c b/src/lib/exchange_api_link.c
@@ -1,519 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2015-2023 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
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file lib/exchange_api_link.c
- * @brief Implementation of the /coins/$COIN_PUB/link request
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_exchange_service.h"
-#include "taler_json_lib.h"
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "exchange_api_curl_defaults.h"
-
-
-/**
- * @brief A /coins/$COIN_PUB/link Handle
- */
-struct TALER_EXCHANGE_LinkHandle
-{
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_LinkCallback link_cb;
-
- /**
- * Closure for @e cb.
- */
- void *link_cb_cls;
-
- /**
- * Private key of the coin, required to decode link information.
- */
- struct TALER_CoinSpendPrivateKeyP coin_priv;
-
- /**
- * Age commitment and proof of the original coin, might be NULL.
- * Required to derive the new age commitment and proof.
- */
- const struct TALER_AgeCommitmentProof *age_commitment_proof;
-
-};
-
-
-/**
- * Parse the provided linkage data from the "200 OK" response
- * for one of the coins.
- *
- * @param lh link handle
- * @param json json reply with the data for one coin
- * @param trans_pub our transfer public key
- * @param[out] lci where to return coin details
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- */
-static enum GNUNET_GenericReturnValue
-parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
- const json_t *json,
- const struct TALER_TransferPublicKeyP *trans_pub,
- struct TALER_EXCHANGE_LinkedCoinInfo *lci)
-{
- struct TALER_BlindedDenominationSignature bsig;
- struct TALER_DenominationPublicKey rpub;
- struct TALER_CoinSpendSignatureP link_sig;
- union GNUNET_CRYPTO_BlindingSecretP bks;
- struct TALER_ExchangeBlindingValues blinding_values;
- union GNUNET_CRYPTO_BlindSessionNonce nonce;
- bool no_nonce;
- uint32_t coin_idx;
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_denom_pub ("denom_pub",
- &rpub),
- TALER_JSON_spec_blinded_denom_sig ("ev_sig",
- &bsig),
- TALER_JSON_spec_exchange_blinding_values ("ewv",
- &blinding_values),
- GNUNET_JSON_spec_fixed_auto ("link_sig",
- &link_sig),
- GNUNET_JSON_spec_uint32 ("coin_idx",
- &coin_idx),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto ("cs_nonce",
- &nonce),
- &no_nonce),
- GNUNET_JSON_spec_end ()
- };
- struct TALER_TransferSecretP secret;
- struct TALER_PlanchetDetail pd;
- struct TALER_CoinPubHashP c_hash;
- struct TALER_AgeCommitmentHash *pah = NULL;
-
- /* parse reply */
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- TALER_link_recover_transfer_secret (trans_pub,
- &lh->coin_priv,
- &secret);
- TALER_transfer_secret_to_planchet_secret (&secret,
- coin_idx,
- &lci->ps);
- TALER_planchet_setup_coin_priv (&lci->ps,
- &blinding_values,
- &lci->coin_priv);
- TALER_planchet_blinding_secret_create (&lci->ps,
- &blinding_values,
- &bks);
-
- lci->has_age_commitment = false;
-
- /* Derive the age commitment and calculate the hash */
- if (NULL != lh->age_commitment_proof)
- {
-
- GNUNET_assert (GNUNET_OK ==
- TALER_age_commitment_proof_derive (
- lh->age_commitment_proof,
- &secret.key,
- &lci->age_commitment_proof));
-
- TALER_age_commitment_hash (
- &lci->age_commitment_proof.commitment,
- &lci->h_age_commitment);
-
- lci->has_age_commitment = true;
- pah = &lci->h_age_commitment;
- }
-
- if (GNUNET_OK !=
- TALER_planchet_prepare (
- &rpub,
- &blinding_values,
- &bks,
- no_nonce
- ? NULL
- : &nonce,
- &lci->coin_priv,
- pah,
- &c_hash,
- &pd))
- {
- GNUNET_break (0);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
- /* extract coin and signature */
- if (GNUNET_OK !=
- TALER_denom_sig_unblind (&lci->sig,
- &bsig,
- &bks,
- &c_hash,
- &blinding_values,
- &rpub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* verify link_sig */
- {
- struct TALER_CoinSpendPublicKeyP old_coin_pub;
- struct TALER_BlindedCoinHashP coin_envelope_hash;
-
- GNUNET_CRYPTO_eddsa_key_get_public (&lh->coin_priv.eddsa_priv,
- &old_coin_pub.eddsa_pub);
-
- TALER_coin_ev_hash (&pd.blinded_planchet,
- &pd.denom_pub_hash,
- &coin_envelope_hash);
- if (GNUNET_OK !=
- TALER_wallet_link_verify (&pd.denom_pub_hash,
- trans_pub,
- &coin_envelope_hash,
- &old_coin_pub,
- &link_sig))
- {
- GNUNET_break_op (0);
- TALER_blinded_planchet_free (&pd.blinded_planchet);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
- TALER_blinded_planchet_free (&pd.blinded_planchet);
- }
-
- /* clean up */
- TALER_denom_pub_copy (&lci->pub,
- &rpub);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_OK;
-}
-
-
-/**
- * Parse the provided linkage data from the "200 OK" response
- * for one of the coins.
- *
- * @param[in,out] lh link handle (callback may be zero'ed out)
- * @param json json reply with the data for one coin
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- */
-static enum GNUNET_GenericReturnValue
-parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
- const json_t *json)
-{
- unsigned int session;
- unsigned int num_coins;
- int ret;
- struct TALER_EXCHANGE_LinkResult lr = {
- .hr.reply = json,
- .hr.http_status = MHD_HTTP_OK
- };
-
- if (! json_is_array (json))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- num_coins = 0;
- /* Theoretically, a coin may have been melted repeatedly
- into different sessions; so the response is an array
- which contains information by melting session. That
- array contains another array. However, our API returns
- a single 1d array, so we flatten the 2d array that is
- returned into a single array. Note that usually a coin
- is melted at most once, and so we'll only run this
- loop once for 'session=0' in most cases.
-
- num_coins tracks the size of the 1d array we return,
- whilst 'i' and 'session' track the 2d array. *///
- for (session = 0; session<json_array_size (json); session++)
- {
- const json_t *jsona;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_array_const ("new_coins",
- &jsona),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json_array_get (json,
- session),
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* count all coins over all sessions */
- num_coins += json_array_size (jsona);
- }
- /* Now that we know how big the 1d array is, allocate
- and fill it. */
- {
- unsigned int off_coin; /* index into 1d array */
- unsigned int i;
- struct TALER_EXCHANGE_LinkedCoinInfo lcis[GNUNET_NZL (num_coins)];
-
- memset (lcis, 0, sizeof (lcis));
- off_coin = 0;
- for (session = 0; session<json_array_size (json); session++)
- {
- const json_t *jsona;
- struct TALER_TransferPublicKeyP trans_pub;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_array_const ("new_coins",
- &jsona),
- GNUNET_JSON_spec_fixed_auto ("transfer_pub",
- &trans_pub),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json_array_get (json,
- session),
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* decode all coins */
- for (i = 0; i<json_array_size (jsona); i++)
- {
- struct TALER_EXCHANGE_LinkedCoinInfo *lci;
-
- lci = &lcis[i + off_coin];
- GNUNET_assert (i + off_coin < num_coins);
- if (GNUNET_OK !=
- parse_link_coin (lh,
- json_array_get (jsona,
- i),
- &trans_pub,
- lci))
- {
- GNUNET_break_op (0);
- break;
- }
- }
- /* check if we really got all, then invoke callback */
- off_coin += i;
- if (i != json_array_size (jsona))
- {
- GNUNET_break_op (0);
- ret = GNUNET_SYSERR;
- break;
- }
- } /* end of for (session) */
-
- if (off_coin == num_coins)
- {
- lr.details.ok.num_coins = num_coins;
- lr.details.ok.coins = lcis;
- lh->link_cb (lh->link_cb_cls,
- &lr);
- lh->link_cb = NULL;
- ret = GNUNET_OK;
- }
- else
- {
- GNUNET_break_op (0);
- ret = GNUNET_SYSERR;
- }
-
- /* clean up */
- GNUNET_assert (off_coin <= num_coins);
- for (i = 0; i<off_coin; i++)
- {
- TALER_denom_sig_free (&lcis[i].sig);
- TALER_denom_pub_free (&lcis[i].pub);
- if (lcis[i].has_age_commitment)
- TALER_age_commitment_proof_free (&lcis[i].age_commitment_proof);
- }
- }
- return ret;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /coins/$COIN_PUB/link request.
- *
- * @param cls the `struct TALER_EXCHANGE_LinkHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_link_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_LinkHandle *lh = cls;
- const json_t *j = response;
- struct TALER_EXCHANGE_LinkResult lr = {
- .hr.reply = j,
- .hr.http_status = (unsigned int) response_code
- };
-
- lh->job = NULL;
- switch (response_code)
- {
- case 0:
- lr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- parse_link_ok (lh,
- j))
- {
- GNUNET_break_op (0);
- lr.hr.http_status = 0;
- lr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- GNUNET_assert (NULL == lh->link_cb);
- TALER_EXCHANGE_link_cancel (lh);
- return;
- case MHD_HTTP_BAD_REQUEST:
- lr.hr.ec = TALER_JSON_get_error_code (j);
- lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_NOT_FOUND:
- lr.hr.ec = TALER_JSON_get_error_code (j);
- lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Nothing really to verify, exchange says this coin was not melted; we
- should pass the JSON reply to the application */
- break;
- case MHD_HTTP_INTERNAL_SERVER_ERROR:
- lr.hr.ec = TALER_JSON_get_error_code (j);
- lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
- break;
- default:
- /* unexpected response code */
- GNUNET_break_op (0);
- lr.hr.ec = TALER_JSON_get_error_code (j);
- lr.hr.hint = TALER_JSON_get_error_hint (j);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d for exchange link\n",
- (unsigned int) response_code,
- (int) lr.hr.ec);
- break;
- }
- if (NULL != lh->link_cb)
- lh->link_cb (lh->link_cb_cls,
- &lr);
- TALER_EXCHANGE_link_cancel (lh);
-}
-
-
-struct TALER_EXCHANGE_LinkHandle *
-TALER_EXCHANGE_link (
- struct GNUNET_CURL_Context *ctx,
- const char *url,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv,
- const struct TALER_AgeCommitmentProof *age_commitment_proof,
- TALER_EXCHANGE_LinkCallback link_cb,
- void *link_cb_cls)
-{
- struct TALER_EXCHANGE_LinkHandle *lh;
- CURL *eh;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
-
- GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
- &coin_pub.eddsa_pub);
- {
- char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
- char *end;
-
- end = GNUNET_STRINGS_data_to_string (
- &coin_pub,
- sizeof (struct TALER_CoinSpendPublicKeyP),
- pub_str,
- sizeof (pub_str));
- *end = '\0';
- GNUNET_snprintf (arg_str,
- sizeof (arg_str),
- "coins/%s/link",
- pub_str);
- }
- lh = GNUNET_new (struct TALER_EXCHANGE_LinkHandle);
- lh->link_cb = link_cb;
- lh->link_cb_cls = link_cb_cls;
- lh->coin_priv = *coin_priv;
- lh->age_commitment_proof = age_commitment_proof;
- lh->url = TALER_url_join (url,
- arg_str,
- NULL);
- if (NULL == lh->url)
- {
- GNUNET_free (lh);
- return NULL;
- }
- eh = TALER_EXCHANGE_curl_easy_get_ (lh->url);
- if (NULL == eh)
- {
- GNUNET_break (0);
- GNUNET_free (lh->url);
- GNUNET_free (lh);
- return NULL;
- }
- lh->job = GNUNET_CURL_job_add_with_ct_json (ctx,
- eh,
- &handle_link_finished,
- lh);
- return lh;
-}
-
-
-void
-TALER_EXCHANGE_link_cancel (struct TALER_EXCHANGE_LinkHandle *lh)
-{
- if (NULL != lh->job)
- {
- GNUNET_CURL_job_cancel (lh->job);
- lh->job = NULL;
- }
-
- GNUNET_free (lh->url);
- GNUNET_free (lh);
-}
-
-
-/* end of exchange_api_link.c */