exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit e5f71e7e97b8cf002d76021b1ff046303b3a45c8
parent 827dcf6d856cf99c7fb0d3cd2577b88ede30f560
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon,  2 Mar 2026 21:36:15 +0100

protocol breaking change for b11169

Diffstat:
MChangeLog | 7+++++++
Mbootstrap | 2+-
Msrc/bank-lib/Makefile.am | 3++-
Asrc/bank-lib/bank_api_helper.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/bank-lib/bank_api_registration.c | 25+++++++++++++++----------
Msrc/exchange-tools/taler-exchange-offline.c | 95++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/exchange/taler-exchange-httpd.h | 14--------------
Msrc/exchange/taler-exchange-httpd_config.c | 8--------
Msrc/exchange/taler-exchange-httpd_config.h | 2+-
Msrc/exchange/taler-exchange-httpd_keys.c | 74++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/exchange/taler-exchange-httpd_management_wire_disable.c | 2++
Msrc/exchange/taler-exchange-httpd_management_wire_enable.c | 34++++++++++++++++++++++++++++++----
Asrc/exchangedb/exchange-0009.sql | 44++++++++++++++++++++++++++++++++++++++++++++
Msrc/exchangedb/pg_get_wire_accounts.c | 14++++++++++++++
Msrc/exchangedb/pg_insert_wire.c | 12+++++++++++-
Msrc/exchangedb/pg_insert_wire.h | 4++++
Msrc/exchangedb/pg_update_wire.c | 10++++++++++
Msrc/exchangedb/pg_update_wire.h | 4++++
Msrc/include/taler/taler-exchange/get-keys.h | 30+++++++++++++++---------------
Msrc/include/taler/taler-exchange/post-management-wire.h | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/include/taler/taler_bank_service.h | 28+++++++++++++++++++++++++---
Msrc/include/taler/taler_crypto_lib.h | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/include/taler/taler_exchangedb_plugin.h | 12++++++++++++
Msrc/lib/exchange_api_common.c | 44++++++++++++++++++++++++++++++++++++--------
Msrc/lib/exchange_api_handle.c | 30+++++++-----------------------
Msrc/lib/exchange_api_post-management-wire.c | 67++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/testing/test_exchange_api.conf | 1+
Msrc/testing/testing_api_cmd_wire_add.c | 18+++++++++++++-----
Msrc/util/offline_signatures.c | 210+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/util/test_crypto.c | 8++++++++
30 files changed, 945 insertions(+), 149 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,10 @@ +Mon Mar 2 07:34:41 PM CET 2026 + Introducing protocol-breaking change that requires operators + to re-sign all of the wire accounts of an exchange. The database + migration will automatically deactivate all of the existing + accounts, so you MUST manually re-sign everything to keep + operating after an upgrade to v1.6.0 -CG + Mon Feb 10 09:32:10 AM CET 2025 Releasing GNU Taler Exchange 0.14.5. -CG diff --git a/bootstrap b/bootstrap @@ -27,7 +27,7 @@ existence() } # Freeze SQL files that must no longer be edited. -for n in 0001 0002 0003 0004 0005 0006 0007 0008 +for n in 0001 0002 0003 0004 0005 0006 0007 0008 0009 do chmod -w src/exchangedb/exchange-$n.sql* chmod -w src/exchangedb/$n-*.sql &> /dev/null || true diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am @@ -34,7 +34,7 @@ lib_LTLIBRARIES = \ libtalerfakebank.la libtalerbank_la_LDFLAGS = \ - -version-info 4:0:0 \ + -version-info 5:0:1 \ -no-undefined libtalerbank_la_SOURCES = \ bank_api_account_token.c \ @@ -43,6 +43,7 @@ libtalerbank_la_SOURCES = \ bank_api_common.c bank_api_common.h \ bank_api_credit.c \ bank_api_debit.c \ + bank_api_helper.c \ bank_api_registration.c \ bank_api_transfer.c \ bank_api_parse.c diff --git a/src/bank-lib/bank_api_helper.c b/src/bank-lib/bank_api_helper.c @@ -0,0 +1,85 @@ +/* + This file is part of TALER + Copyright (C) 2026 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 bank-lib/bank_api_helper.c + * @brief convenience functions for the ``struct TALER_BANK_TransferSubject`` + * @author Christian Grothoff + */ +#include "taler/platform.h" +#include "bank_api_common.h" +#include <microhttpd.h> /* just for HTTP status codes */ +#include "taler/taler_signatures.h" +#include "taler/taler_curl_lib.h" + + +void +TALER_BANK_transfer_subject_copy ( + struct TALER_BANK_TransferSubject *dst, + const struct TALER_BANK_TransferSubject *src) +{ + dst->format = src->format; + + switch (src->format) + { + case TALER_BANK_SUBJECT_FORMAT_SIMPLE: + dst->details.simple.credit_amount = src->details.simple.credit_amount; + dst->details.simple.subject = + (src->details.simple.subject != NULL) + ? GNUNET_strdup (src->details.simple.subject) + : NULL; + return; + + case TALER_BANK_SUBJECT_FORMAT_URI: + dst->details.uri.uri = + (src->details.uri.uri != NULL) + ? GNUNET_strdup (src->details.uri.uri) + : NULL; + return; + + case TALER_BANK_SUBJECT_FORMAT_CH_QR_BILL: + dst->details.ch_qr_bill.credit_amount = + src->details.ch_qr_bill.credit_amount; + dst->details.ch_qr_bill.qr_reference_number = + (src->details.ch_qr_bill.qr_reference_number != NULL) + ? GNUNET_strdup (src->details.ch_qr_bill.qr_reference_number) + : NULL; + return; + } + GNUNET_break (0); +} + + +void +TALER_BANK_transfer_subject_free ( + struct TALER_BANK_TransferSubject *subject) +{ + switch (subject->format) + { + case TALER_BANK_SUBJECT_FORMAT_SIMPLE: + GNUNET_free (subject->details.simple.subject); + return; + + case TALER_BANK_SUBJECT_FORMAT_URI: + GNUNET_free (subject->details.uri.uri); + return; + + case TALER_BANK_SUBJECT_FORMAT_CH_QR_BILL: + GNUNET_free (subject->details.ch_qr_bill.qr_reference_number); + return; + } + GNUNET_break (0); +} diff --git a/src/bank-lib/bank_api_registration.c b/src/bank-lib/bank_api_registration.c @@ -93,10 +93,12 @@ parse_transfer_subject (const json_t *subject_json, "SIMPLE")) { struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount_any ("credit_amount", - &ts->details.simple.credit_amount), - GNUNET_JSON_spec_string ("subject", - &ts->details.simple.subject), + TALER_JSON_spec_amount_any ( + "credit_amount", + &ts->details.simple.credit_amount), + GNUNET_JSON_spec_string ( + "subject", + (const char **) &ts->details.simple.subject), GNUNET_JSON_spec_end () }; @@ -115,8 +117,9 @@ parse_transfer_subject (const json_t *subject_json, "URI")) { struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ("uri", - &ts->details.uri.uri), + GNUNET_JSON_spec_string ( + "uri", + (const char **) &ts->details.uri.uri), GNUNET_JSON_spec_end () }; @@ -135,10 +138,12 @@ parse_transfer_subject (const json_t *subject_json, "CH_QR_BILL")) { struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount_any ("credit_amount", - &ts->details.ch_qr_bill.credit_amount), - GNUNET_JSON_spec_string ("qr_reference_number", - &ts->details.ch_qr_bill.qr_reference_number), + TALER_JSON_spec_amount_any ( + "credit_amount", + &ts->details.ch_qr_bill.credit_amount), + GNUNET_JSON_spec_string ( + "qr_reference_number", + (const char **) &ts->details.ch_qr_bill.qr_reference_number), GNUNET_JSON_spec_end () }; diff --git a/src/exchange-tools/taler-exchange-offline.c b/src/exchange-tools/taler-exchange-offline.c @@ -1615,6 +1615,8 @@ upload_wire_add (const char *exchange_url, struct WireAddRequest *war; const char *err_name; const char *conversion_url = NULL; + const char *open_banking_gateway = NULL; + const char *wire_transfer_gateway = NULL; const char *bank_label = NULL; int64_t priority = 0; const json_t *debit_restrictions; @@ -1628,6 +1630,14 @@ upload_wire_add (const char *exchange_url, &conversion_url), NULL), GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_web_url ("open_banking_gateway", + &open_banking_gateway), + NULL), + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_web_url ("wire_transfer_gateway", + &wire_transfer_gateway), + NULL), + GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("bank_label", &bank_label), NULL), @@ -1699,15 +1709,21 @@ upload_wire_add (const char *exchange_url, TALER_EXCHANGE_post_management_wire_create (ctx, exchange_url, payto_uri, - conversion_url, - debit_restrictions, - credit_restrictions, start_time, &master_sig_add, &master_sig_wire); TALER_EXCHANGE_post_management_wire_set_options ( war->h, TALER_EXCHANGE_post_management_wire_option_bank_label (bank_label), + TALER_EXCHANGE_post_management_wire_option_conversion_url (conversion_url), + TALER_EXCHANGE_post_management_wire_option_open_banking_gateway ( + open_banking_gateway), + TALER_EXCHANGE_post_management_wire_option_wire_transfer_gateway ( + wire_transfer_gateway), + TALER_EXCHANGE_post_management_wire_option_debit_restrictions ( + debit_restrictions), + TALER_EXCHANGE_post_management_wire_option_credit_restrictions ( + credit_restrictions), TALER_EXCHANGE_post_management_wire_option_priority (priority)); TALER_EXCHANGE_post_management_wire_start (war->h, &wire_add_cb, @@ -3169,6 +3185,8 @@ do_add_wire (char *const *args) struct TALER_MasterSignatureP master_sig_wire; struct GNUNET_TIME_Timestamp now; const char *conversion_url = NULL; + const char *open_banking_gateway = NULL; + const char *wire_transfer_gateway = NULL; const char *bank_label = NULL; int64_t priority = 0; json_t *debit_restrictions; @@ -3263,6 +3281,67 @@ do_add_wire (char *const *args) num_args++; continue; } + + if (0 == strcmp (args[num_args], + "open-banking-gateway")) + { + num_args++; + open_banking_gateway = args[num_args]; + if (NULL == open_banking_gateway) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "'open-banking-gateway' requires an argument\n"); + global_ret = EXIT_INVALIDARGUMENT; + GNUNET_SCHEDULER_shutdown (); + json_decref (debit_restrictions); + json_decref (credit_restrictions); + return; + } + if (! TALER_is_web_url (open_banking_gateway)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "'open-banking-gateway' must refer to HTTP(S) endpoint, `%s' is invalid\n", + open_banking_gateway); + global_ret = EXIT_INVALIDARGUMENT; + GNUNET_SCHEDULER_shutdown (); + json_decref (debit_restrictions); + json_decref (credit_restrictions); + return; + } + num_args++; + continue; + } + + if (0 == strcmp (args[num_args], + "wire-transfer-gateway")) + { + num_args++; + wire_transfer_gateway = args[num_args]; + if (NULL == wire_transfer_gateway) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "'wire-transfer-gateway' requires an argument\n"); + global_ret = EXIT_INVALIDARGUMENT; + GNUNET_SCHEDULER_shutdown (); + json_decref (debit_restrictions); + json_decref (credit_restrictions); + return; + } + if (! TALER_is_web_url (wire_transfer_gateway)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "'wire-transfer-gateway' must refer to HTTP(S) endpoint, `%s' is invalid\n", + wire_transfer_gateway); + global_ret = EXIT_INVALIDARGUMENT; + GNUNET_SCHEDULER_shutdown (); + json_decref (debit_restrictions); + json_decref (credit_restrictions); + return; + } + num_args++; + continue; + } + if (0 == strcmp (args[num_args], "credit-restriction")) { @@ -3343,6 +3422,8 @@ do_add_wire (char *const *args) } TALER_exchange_offline_wire_add_sign (payto_uri, conversion_url, + open_banking_gateway, + wire_transfer_gateway, debit_restrictions, credit_restrictions, now, @@ -3350,6 +3431,8 @@ do_add_wire (char *const *args) &master_sig_add); TALER_exchange_wire_signature_make (payto_uri, conversion_url, + open_banking_gateway, + wire_transfer_gateway, debit_restrictions, credit_restrictions, &master_priv, @@ -3366,6 +3449,12 @@ do_add_wire (char *const *args) GNUNET_JSON_pack_string ("conversion_url", conversion_url)), GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("open_banking_gateway", + open_banking_gateway)), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("wire_transfer_gateway", + wire_transfer_gateway)), + GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("bank_label", bank_label)), GNUNET_JSON_pack_int64 ("priority", diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h @@ -154,20 +154,6 @@ extern struct TALER_Amount TEH_tiny_amount; extern char *TEH_shopping_url; /** - * URL where wallets and merchants can request short wire transfer - * subjects for sending funds to the exchange without having to - * encode the full public key in the subject. Can be NULL if not - * supported/available. - */ -extern char *TEH_wire_transfer_gateway; - -/** - * URL where wallets can find an open banking gateway API to - * initiate wire transfers to withdraw money from this exchange. Can be NULL. - */ -extern char *TEH_obg_url; - -/** * Linear STEFAN parameter. */ extern float TEH_stefan_lin; diff --git a/src/exchange/taler-exchange-httpd_config.c b/src/exchange/taler-exchange-httpd_config.c @@ -45,10 +45,6 @@ TEH_handler_config (struct TEH_RequestContext *rc, GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("shopping_url", TEH_shopping_url)), - /* Deprecated in v24 */ - GNUNET_JSON_pack_array_steal ( - "supported_kyc_requirements", - json_array ()), GNUNET_JSON_pack_object_steal ( "currency_specification", TALER_JSON_currency_specs_to_json (TEH_cspec)), @@ -65,10 +61,6 @@ TEH_handler_config (struct TEH_RequestContext *rc, GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("shopping_url", TEH_shopping_url)), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ( - "open_banking_gateway", - TEH_obg_url)), GNUNET_JSON_pack_string ( "implementation", "urn:net:taler:specs:taler-exchange:c-reference"), diff --git a/src/exchange/taler-exchange-httpd_config.h b/src/exchange/taler-exchange-httpd_config.h @@ -41,7 +41,7 @@ * * Returned via both /config and /keys endpoints. */ -#define EXCHANGE_PROTOCOL_VERSION "32:0:10" +#define EXCHANGE_PROTOCOL_VERSION "33:0:0" /** diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c @@ -631,6 +631,8 @@ wire_update_event_cb (void *cls, * @param cls a `json_t *` array to expand with wire account details * @param payto_uri the exchange bank account URI to add * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param open_banking_gateway URL of an open banking gateway, NULL if there is none + * @param wire_transfer_gateway URL of a wire transfer gateway, NULL if there is none * @param debit_restrictions JSON array with debit restrictions on the account * @param credit_restrictions JSON array with credit restrictions on the account * @param master_sig master key signature affirming that this is a bank @@ -639,14 +641,17 @@ wire_update_event_cb (void *cls, * @param priority priority for ordering bank account labels */ static void -add_wire_account (void *cls, - const struct TALER_FullPayto payto_uri, - const char *conversion_url, - const json_t *debit_restrictions, - const json_t *credit_restrictions, - const struct TALER_MasterSignatureP *master_sig, - const char *bank_label, - int64_t priority) +add_wire_account ( + void *cls, + const struct TALER_FullPayto payto_uri, + const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + const struct TALER_MasterSignatureP *master_sig, + const char *bank_label, + int64_t priority) { json_t *a = cls; @@ -654,6 +659,8 @@ add_wire_account (void *cls, TALER_exchange_wire_signature_check ( payto_uri, conversion_url, + open_banking_gateway, + wire_transfer_gateway, debit_restrictions, credit_restrictions, &TEH_master_public_key, @@ -667,22 +674,37 @@ add_wire_account (void *cls, json_array_append_new ( a, GNUNET_JSON_PACK ( - TALER_JSON_pack_full_payto ("payto_uri", - payto_uri), + TALER_JSON_pack_full_payto ( + "payto_uri", + payto_uri), GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ("conversion_url", - conversion_url)), + GNUNET_JSON_pack_string ( + "conversion_url", + conversion_url)), GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ("bank_label", - bank_label)), - GNUNET_JSON_pack_int64 ("priority", - priority), - GNUNET_JSON_pack_array_incref ("debit_restrictions", - (json_t *) debit_restrictions), - GNUNET_JSON_pack_array_incref ("credit_restrictions", - (json_t *) credit_restrictions), - GNUNET_JSON_pack_data_auto ("master_sig", - master_sig)))) + GNUNET_JSON_pack_string ( + "open_banking_gateway", + open_banking_gateway)), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ( + "wire_transfer_gateway", + wire_transfer_gateway)), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ( + "bank_label", + bank_label)), + GNUNET_JSON_pack_int64 ( + "priority", + priority), + GNUNET_JSON_pack_array_incref ( + "debit_restrictions", + (json_t *) debit_restrictions), + GNUNET_JSON_pack_array_incref ( + "credit_restrictions", + (json_t *) credit_restrictions), + GNUNET_JSON_pack_data_auto ( + "master_sig", + master_sig)))) { GNUNET_break (0); /* out of memory!? */ return; @@ -2466,14 +2488,6 @@ create_krd (struct TEH_KeyStateHandle *ksh, GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("shopping_url", TEH_shopping_url)), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ( - "open_banking_gateway", - TEH_obg_url)), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ( - "wire_transfer_gateway", - TEH_wire_transfer_gateway)), TALER_JSON_pack_amount ("tiny_amount", &TEH_tiny_amount), GNUNET_JSON_pack_data_auto ("exchange_pub", diff --git a/src/exchange/taler-exchange-httpd_management_wire_disable.c b/src/exchange/taler-exchange-httpd_management_wire_disable.c @@ -117,6 +117,8 @@ del_wire (void *cls, NULL, NULL, NULL, + NULL, + NULL, awc->validity_end, NULL, NULL, diff --git a/src/exchange/taler-exchange-httpd_management_wire_enable.c b/src/exchange/taler-exchange-httpd_management_wire_enable.c @@ -60,6 +60,16 @@ struct AddWireContext const char *conversion_url; /** + * (optional) address of an open banking gateway service for this account. + */ + const char *open_banking_gateway; + + /** + * (optional) address of a wire transfer gateway service for this account. + */ + const char *wire_transfer_gateway; + + /** * Restrictions imposed when crediting this account. */ const json_t *credit_restrictions; @@ -140,6 +150,8 @@ add_wire (void *cls, qs = TEH_plugin->insert_wire (TEH_plugin->cls, awc->payto_uri, awc->conversion_url, + awc->open_banking_gateway, + awc->wire_transfer_gateway, awc->debit_restrictions, awc->credit_restrictions, awc->validity_start, @@ -150,6 +162,8 @@ add_wire (void *cls, qs = TEH_plugin->update_wire (TEH_plugin->cls, awc->payto_uri, awc->conversion_url, + awc->open_banking_gateway, + awc->wire_transfer_gateway, awc->debit_restrictions, awc->credit_restrictions, awc->validity_start, @@ -181,22 +195,30 @@ TEH_handler_management_post_wire ( .conversion_url = NULL }; struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_full_payto_uri ("payto_uri", + &awc.payto_uri), GNUNET_JSON_spec_fixed_auto ("master_sig_wire", &awc.master_sig_wire), GNUNET_JSON_spec_fixed_auto ("master_sig_add", &awc.master_sig_add), - TALER_JSON_spec_full_payto_uri ("payto_uri", - &awc.payto_uri), + GNUNET_JSON_spec_timestamp ("validity_start", + &awc.validity_start), GNUNET_JSON_spec_mark_optional ( TALER_JSON_spec_web_url ("conversion_url", &awc.conversion_url), NULL), + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_web_url ("open_banking_gateway", + &awc.open_banking_gateway), + NULL), + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_web_url ("wire_transfer_gateway", + &awc.wire_transfer_gateway), + NULL), GNUNET_JSON_spec_array_const ("credit_restrictions", &awc.credit_restrictions), GNUNET_JSON_spec_array_const ("debit_restrictions", &awc.debit_restrictions), - GNUNET_JSON_spec_timestamp ("validity_start", - &awc.validity_start), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("bank_label", &awc.bank_label), @@ -242,6 +264,8 @@ TEH_handler_management_post_wire ( TALER_exchange_offline_wire_add_verify ( awc.payto_uri, awc.conversion_url, + awc.open_banking_gateway, + awc.wire_transfer_gateway, awc.debit_restrictions, awc.credit_restrictions, awc.validity_start, @@ -261,6 +285,8 @@ TEH_handler_management_post_wire ( TALER_exchange_wire_signature_check ( awc.payto_uri, awc.conversion_url, + awc.open_banking_gateway, + awc.wire_transfer_gateway, awc.debit_restrictions, awc.credit_restrictions, &TEH_master_public_key, diff --git a/src/exchangedb/exchange-0009.sql b/src/exchangedb/exchange-0009.sql @@ -0,0 +1,44 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2026 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/> +-- + +BEGIN; + +SELECT _v.register_patch('exchange-0009', NULL, NULL); + +SET search_path TO exchange; + +ALTER TABLE wire_accounts + ADD COLUMN open_banking_gateway + TEXT DEFAULT (NULL) + ,ADD COLUMN wire_transfer_gateway + TEXT DEFAULT (NULL) + ,ADD COLUMN sig_version + INT4 DEFAULT 33; +COMMENT ON COLUMN wire_accounts.open_banking_gateway + IS 'URL of an open banking gateway that can be used to initiate wire transfers to this account; NULL if there is no such service.'; +COMMENT ON COLUMN wire_accounts.wire_transfer_gateway + IS 'URL of a wire transfer gateway that can be used to obtain (short) wire transfer subjects; NULL if there is no such service.'; +COMMENT ON COLUMN wire_accounts.sig_version + IS 'Protocol version used by the master_sig in this column. Used to tell which algorithm is needed to verify the signature.'; + +-- The master_sig changes in protocol v33, hence deactivate all old +-- signatures/accounts. +UPDATE wire_accounts + SET is_active=FALSE + ,sig_version=32; + + +COMMIT; diff --git a/src/exchangedb/pg_get_wire_accounts.c b/src/exchangedb/pg_get_wire_accounts.c @@ -67,6 +67,8 @@ get_wire_accounts_cb (void *cls, { struct TALER_FullPayto payto_uri; char *conversion_url = NULL; + char *open_banking_gateway = NULL; + char *wire_transfer_gateway = NULL; json_t *debit_restrictions = NULL; json_t *credit_restrictions = NULL; struct TALER_MasterSignatureP master_sig; @@ -80,6 +82,14 @@ get_wire_accounts_cb (void *cls, &conversion_url), NULL), GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("open_banking_gateway", + &open_banking_gateway), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("wire_transfer_gateway", + &wire_transfer_gateway), + NULL), + GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_string ("bank_label", &bank_label), NULL), @@ -120,6 +130,8 @@ get_wire_accounts_cb (void *cls, ctx->cb (ctx->cb_cls, payto_uri, conversion_url, + open_banking_gateway, + wire_transfer_gateway, debit_restrictions, credit_restrictions, &master_sig, @@ -151,6 +163,8 @@ TEH_PG_get_wire_accounts (void *cls, "SELECT" " payto_uri" ",conversion_url" + ",open_banking_gateway" + ",wire_transfer_gateway" ",debit_restrictions::TEXT" ",credit_restrictions::TEXT" ",master_sig" diff --git a/src/exchangedb/pg_insert_wire.c b/src/exchangedb/pg_insert_wire.c @@ -31,6 +31,8 @@ TEH_PG_insert_wire ( void *cls, const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp start_date, @@ -52,6 +54,12 @@ TEH_PG_insert_wire ( ? GNUNET_PQ_query_param_null () : GNUNET_PQ_query_param_string (bank_label), GNUNET_PQ_query_param_int64 (&priority), + NULL == open_banking_gateway + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (open_banking_gateway), + NULL == wire_transfer_gateway + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (wire_transfer_gateway), GNUNET_PQ_query_param_end }; @@ -67,8 +75,10 @@ TEH_PG_insert_wire ( ",last_change" ",bank_label" ",priority" + ",open_banking_gateway" + ",wire_transfer_gateway" ") VALUES " - "($1,$2,$3::TEXT::JSONB,$4::TEXT::JSONB,$5,true,$6,$7,$8);"); + "($1,$2,$3::TEXT::JSONB,$4::TEXT::JSONB,$5,true,$6,$7,$8,$9,$10);"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "insert_wire", params); diff --git a/src/exchangedb/pg_insert_wire.h b/src/exchangedb/pg_insert_wire.h @@ -32,6 +32,8 @@ * @param cls closure * @param payto_uri wire account of the exchange * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param open_banking_gateway open banking gateway service, NULL if unavailable + * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable * @param debit_restrictions JSON array with debit restrictions on the account * @param credit_restrictions JSON array with credit restrictions on the account * @param start_date date when the account was added by the offline system @@ -46,6 +48,8 @@ enum GNUNET_DB_QueryStatus TEH_PG_insert_wire (void *cls, const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp start_date, diff --git a/src/exchangedb/pg_update_wire.c b/src/exchangedb/pg_update_wire.c @@ -31,6 +31,8 @@ TEH_PG_update_wire ( void *cls, const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp change_date, @@ -60,6 +62,12 @@ TEH_PG_update_wire ( ? GNUNET_PQ_query_param_null () : GNUNET_PQ_query_param_string (bank_label), GNUNET_PQ_query_param_int64 (&priority), + NULL == open_banking_gateway + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (open_banking_gateway), + NULL == wire_transfer_gateway + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (wire_transfer_gateway), GNUNET_PQ_query_param_end }; @@ -75,6 +83,8 @@ TEH_PG_update_wire ( " ,master_sig=$7" " ,bank_label=$8" " ,priority=$9" + " ,open_banking_gateway=$10" + " ,wire_transfer_gateway=$11" " WHERE payto_uri=$1"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "update_wire", diff --git a/src/exchangedb/pg_update_wire.h b/src/exchangedb/pg_update_wire.h @@ -32,6 +32,8 @@ * @param cls closure * @param payto_uri account the update is about * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param open_banking_gateway open banking gateway service, NULL if unavailable + * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable * @param debit_restrictions JSON array with debit restrictions on the account; NULL allowed if not @a enabled * @param credit_restrictions JSON array with credit restrictions on the account; NULL allowed if not @a enabled * @param change_date date when the account status was last changed @@ -46,6 +48,8 @@ enum GNUNET_DB_QueryStatus TEH_PG_update_wire (void *cls, const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp change_date, diff --git a/src/include/taler/taler-exchange/get-keys.h b/src/include/taler/taler-exchange/get-keys.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2025 Taler Systems SA + Copyright (C) 2014-2026 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 @@ -416,6 +416,20 @@ struct TALER_EXCHANGE_WireAccount char *conversion_url; /** + * Open banking gateway base URL for wallet-initiated wire + * transfers. NULL if not configured. + * @since protocol v33. + */ + char *open_banking_gateway; + + /** + * Wire transfer gateway base URL for short wire transfer + * subjects. NULL if not configured. + * @since protocol v33. + */ + char *wire_transfer_gateway; + + /** * Array of restrictions that apply when crediting * this account. */ @@ -580,20 +594,6 @@ struct TALER_EXCHANGE_Keys char *shopping_url; /** - * Open banking gateway base URL for wallet-initiated wire - * transfers. NULL if not configured. - * @since protocol v30. - */ - char *open_banking_gateway; - - /** - * Wire transfer gateway base URL for short wire transfer - * subjects. NULL if not configured. - * @since protocol v33. - */ - char *wire_transfer_gateway; - - /** * Bank-specific compliance language hint for wallets. * NULL if not configured. * @since protocol v24. diff --git a/src/include/taler/taler-exchange/post-management-wire.h b/src/include/taler/taler-exchange/post-management-wire.h @@ -44,7 +44,37 @@ enum TALER_EXCHANGE_PostManagementWireOption * Priority for ordering the bank accounts when displaying to users. * If not set, defaults to 0. */ - TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_PRIORITY + TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_PRIORITY, + + /** + * URL of conversion service to use. + * If not set, no conversion is used. + */ + TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CONVERSION_URL, + + /** + * Open banking gateway that could be used. + * If not set, no open banking gateway is available. + */ + TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_OPEN_BANKING_GATEWAY, + + /** + * Wire transfer gateway service URL for short wire transfer subjects. + * If not set, no wire transfer gateway is used. + */ + TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_WIRE_TRANSFER_GATEWAY, + + /** + * Set of credit restrictions to apply. + * If not set, no credit restrictions apply. + */ + TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CREDIT_RESTRICTIONS, + + /** + * Set of debit restrictions to apply. + * If not set, no debit restrictions apply. + */ + TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_DEBIT_RESTRICTIONS }; @@ -73,6 +103,41 @@ struct TALER_EXCHANGE_PostManagementWireOptionValue /** * Value if @e option is + * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CONVERSION_URL. + * May be NULL. + */ + const char *conversion_url; + + /** + * Value if @e option is + * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_OPEN_BANKING_GATEWAY. + * May be NULL. + */ + const char *open_banking_gateway; + + /** + * Value if @e option is + * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_WIRE_TRANSFER_GATEWAY. + * May be NULL. + */ + const char *wire_transfer_gateway; + + /** + * Value if @e option is + * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CREDIT_RESTRICTIONS. + * May be NULL. + */ + const json_t *credit_restrictions; + + /** + * Value if @e option is + * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_DEBIT_RESTRICTIONS. + * May be NULL. + */ + const json_t *debit_restrictions; + + /** + * Value if @e option is * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_PRIORITY. */ int64_t priority; @@ -95,9 +160,6 @@ struct TALER_EXCHANGE_PostManagementWireHandle; * @param ctx the context * @param url HTTP base URL for the exchange * @param payto_uri RFC 8905 URI of the exchange's bank account - * @param conversion_url URL of the conversion service, or NULL if none - * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec - * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec * @param validity_start when was this decided? * @param master_sig1 signature affirming the wire addition * of purpose #TALER_SIGNATURE_MASTER_ADD_WIRE @@ -110,9 +172,6 @@ TALER_EXCHANGE_post_management_wire_create ( struct GNUNET_CURL_Context *ctx, const char *url, const struct TALER_FullPayto payto_uri, - const char *conversion_url, - const json_t *debit_restrictions, - const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp validity_start, const struct TALER_MasterSignatureP *master_sig1, const struct TALER_MasterSignatureP *master_sig2); @@ -142,6 +201,7 @@ TALER_EXCHANGE_post_management_wire_create ( .details.bank_label = (l) \ } + /** * Set the priority for ordering the bank accounts. * @@ -157,6 +217,79 @@ TALER_EXCHANGE_post_management_wire_create ( /** + * Set the conversion URL for the wire account. + * + * @param u the conversion service URL string, or NULL for no conversion + * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue + */ +#define TALER_EXCHANGE_post_management_wire_option_conversion_url(u) \ + (const struct TALER_EXCHANGE_PostManagementWireOptionValue) \ + { \ + .option = TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CONVERSION_URL, \ + .details.conversion_url = (u) \ + } + + +/** + * Set the open banking gateway for the wire account. + * + * @param g the open banking gateway URL string, or NULL for no gateway + * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue + */ +#define TALER_EXCHANGE_post_management_wire_option_open_banking_gateway(g) \ + (const struct TALER_EXCHANGE_PostManagementWireOptionValue) \ + { \ + .option = \ + TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_OPEN_BANKING_GATEWAY, \ + .details.open_banking_gateway = (g) \ + } + + +/** + * Set the wire transfer gateway for the wire account. + * + * @param g the wire transfer gateway URL string, or NULL for no gateway + * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue + */ +#define TALER_EXCHANGE_post_management_wire_option_wire_transfer_gateway(g) \ + (const struct TALER_EXCHANGE_PostManagementWireOptionValue) \ + { \ + .option = \ + TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_WIRE_TRANSFER_GATEWAY, \ + .details.wire_transfer_gateway = (g) \ + } + + +/** + * Set the credit restrictions for the wire account. + * + * @param r JSON encoding of the credit restrictions, or NULL for no restrictions + * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue + */ +#define TALER_EXCHANGE_post_management_wire_option_credit_restrictions(r) \ + (const struct TALER_EXCHANGE_PostManagementWireOptionValue) \ + { \ + .option = \ + TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CREDIT_RESTRICTIONS, \ + .details.credit_restrictions = (r) \ + } + + +/** + * Set the debit restrictions for the wire account. + * + * @param r JSON encoding of the debit restrictions, or NULL for no restrictions + * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue + */ +#define TALER_EXCHANGE_post_management_wire_option_debit_restrictions(r) \ + (const struct TALER_EXCHANGE_PostManagementWireOptionValue) \ + { \ + .option = \ + TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_DEBIT_RESTRICTIONS, \ + .details.debit_restrictions = (r) \ + } + +/** * Set the requested options for the operation. * * If any option fails, other options may or may not be applied. diff --git a/src/include/taler/taler_bank_service.h b/src/include/taler/taler_bank_service.h @@ -1120,7 +1120,7 @@ struct TALER_BANK_TransferSubject /** * Encoded string containing the key or derived short subject. */ - const char *subject; + char *subject; } simple; @@ -1133,7 +1133,7 @@ struct TALER_BANK_TransferSubject /** * Prepared-payment confirmation URI. */ - const char *uri; + char *uri; } uri; @@ -1151,7 +1151,7 @@ struct TALER_BANK_TransferSubject /** * 27-digit QR Reference Number (NUL-terminated string). */ - const char *qr_reference_number; + char *qr_reference_number; } ch_qr_bill; @@ -1161,6 +1161,28 @@ struct TALER_BANK_TransferSubject /** + * Make a deep copy of @a src to @a dst. + * + * @param[out] dst copy to initialize + * @param src source to copy from + */ +void +TALER_BANK_transfer_subject_copy ( + struct TALER_BANK_TransferSubject *dst, + const struct TALER_BANK_TransferSubject *src); + + +/** + * Free memory allocated inside of @a subject, but not @a subject itself + * + * @param[in,out] subject memory to free + */ +void +TALER_BANK_transfer_subject_free ( + struct TALER_BANK_TransferSubject *subject); + + +/** * Response details for a /registration POST request. */ struct TALER_BANK_RegistrationResponse diff --git a/src/include/taler/taler_crypto_lib.h b/src/include/taler/taler_crypto_lib.h @@ -6656,6 +6656,8 @@ TALER_exchange_offline_global_fee_verify ( * * @param payto_uri bank account * @param conversion_url URL of the conversion service, or NULL if none + * @param open_banking_gateway open banking gateway service, NULL if unavailable + * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec * @param now timestamp to use for the signature (rounded) @@ -6666,6 +6668,8 @@ void TALER_exchange_offline_wire_add_sign ( const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp now, @@ -6678,6 +6682,8 @@ TALER_exchange_offline_wire_add_sign ( * * @param payto_uri bank account * @param conversion_url URL of the conversion service, or NULL if none + * @param open_banking_gateway open banking gateway service, NULL if unavailable + * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec * @param sign_time timestamp when signature was created @@ -6689,6 +6695,31 @@ enum GNUNET_GenericReturnValue TALER_exchange_offline_wire_add_verify ( const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + struct GNUNET_TIME_Timestamp sign_time, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify wire account addition signature for legacy (pre v33) APIs. + * + * @param payto_uri bank account + * @param conversion_url URL of the conversion service, or NULL if none + * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec + * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec + * @param sign_time timestamp when signature was created + * @param master_pub public key to verify against + * @param master_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_wire_add_verify_32 ( + const struct TALER_FullPayto payto_uri, + const char *conversion_url, const json_t *debit_restrictions, const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp sign_time, @@ -6734,6 +6765,8 @@ TALER_exchange_offline_wire_del_verify ( * * @param payto_uri URI that is signed * @param conversion_url URL of the conversion service, or NULL if none + * @param open_banking_gateway open banking gateway service, NULL if unavailable + * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec * @param master_pub master public key of the exchange @@ -6744,6 +6777,29 @@ enum GNUNET_GenericReturnValue TALER_exchange_wire_signature_check ( const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Check the signature in @a master_sig. Pre v33 version. + * + * @param payto_uri URI that is signed + * @param conversion_url URL of the conversion service, or NULL if none + * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec + * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec + * @param master_pub master public key of the exchange + * @param master_sig signature of the exchange + * @return #GNUNET_OK if signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_wire_signature_check32 ( + const struct TALER_FullPayto payto_uri, + const char *conversion_url, const json_t *debit_restrictions, const json_t *credit_restrictions, const struct TALER_MasterPublicKeyP *master_pub, @@ -6755,6 +6811,8 @@ TALER_exchange_wire_signature_check ( * * @param payto_uri account specification * @param conversion_url URL of the conversion service, or NULL if none + * @param open_banking_gateway open banking gateway service, NULL if unavailable + * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec * @param master_priv private key to sign with @@ -6764,6 +6822,8 @@ void TALER_exchange_wire_signature_make ( const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, const struct TALER_MasterPrivateKeyP *master_priv, diff --git a/src/include/taler/taler_exchangedb_plugin.h b/src/include/taler/taler_exchangedb_plugin.h @@ -3276,6 +3276,8 @@ typedef enum GNUNET_GenericReturnValue * @param cls closure * @param payto_uri the exchange bank account URI * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param open_banking_gateway open banking gateway service, NULL if unavailable + * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable * @param debit_restrictions JSON array with debit restrictions on the account * @param credit_restrictions JSON array with credit restrictions on the account * @param master_sig master key signature affirming that this is a bank @@ -3288,6 +3290,8 @@ typedef void void *cls, const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, const struct TALER_MasterSignatureP *master_sig, @@ -6148,6 +6152,8 @@ struct TALER_EXCHANGEDB_Plugin * @param cls closure * @param payto_uri wire account of the exchange * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param open_banking_gateway open banking gateway service, NULL if unavailable + * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable * @param debit_restrictions JSON array with debit restrictions on the account * @param credit_restrictions JSON array with credit restrictions on the account * @param start_date date when the account was added by the offline system @@ -6162,6 +6168,8 @@ struct TALER_EXCHANGEDB_Plugin (*insert_wire)(void *cls, const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp start_date, @@ -6176,6 +6184,8 @@ struct TALER_EXCHANGEDB_Plugin * @param cls closure * @param payto_uri account the update is about * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param open_banking_gateway open banking gateway service, NULL if unavailable + * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable * @param debit_restrictions JSON array with debit restrictions on the account; NULL allowed if not @a enabled * @param credit_restrictions JSON array with credit restrictions on the account; NULL allowed if not @a enabled * @param change_date date when the account status was last changed @@ -6190,6 +6200,8 @@ struct TALER_EXCHANGEDB_Plugin (*update_wire)(void *cls, const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp change_date, diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c @@ -516,6 +516,8 @@ TALER_EXCHANGE_parse_accounts ( struct TALER_EXCHANGE_WireAccount *wa = &was[i]; struct TALER_FullPayto payto_uri; const char *conversion_url = NULL; + const char *open_banking_gateway = NULL; + const char *wire_transfer_gateway = NULL; const char *bank_label = NULL; int64_t priority = 0; const json_t *credit_restrictions; @@ -528,6 +530,14 @@ TALER_EXCHANGE_parse_accounts ( &conversion_url), NULL), GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("open_banking_gateway", + &open_banking_gateway), + NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("wire_transfer_gateway", + &wire_transfer_gateway), + NULL), + GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_int64 ("priority", &priority), NULL), @@ -557,14 +567,26 @@ TALER_EXCHANGE_parse_accounts ( return GNUNET_SYSERR; } if ( (NULL != master_pub) && - (GNUNET_OK != - TALER_exchange_wire_signature_check ( - payto_uri, - conversion_url, - debit_restrictions, - credit_restrictions, - master_pub, - &wa->master_sig)) ) + (! ( ( (NULL == open_banking_gateway) && + (NULL == wire_transfer_gateway) && + (GNUNET_OK == + TALER_exchange_wire_signature_check32 ( + payto_uri, + conversion_url, + debit_restrictions, + credit_restrictions, + master_pub, + &wa->master_sig)) ) || + (GNUNET_OK == + TALER_exchange_wire_signature_check ( + payto_uri, + conversion_url, + open_banking_gateway, + wire_transfer_gateway, + debit_restrictions, + credit_restrictions, + master_pub, + &wa->master_sig)) ) ) ) { /* bogus reply */ GNUNET_break_op (0); @@ -588,6 +610,10 @@ TALER_EXCHANGE_parse_accounts ( wa->priority = priority; if (NULL != conversion_url) wa->conversion_url = GNUNET_strdup (conversion_url); + if (NULL != open_banking_gateway) + wa->open_banking_gateway = GNUNET_strdup (open_banking_gateway); + if (NULL != wire_transfer_gateway) + wa->wire_transfer_gateway = GNUNET_strdup (wire_transfer_gateway); if (NULL != bank_label) wa->bank_label = GNUNET_strdup (bank_label); } /* end 'for all accounts */ @@ -636,6 +662,8 @@ TALER_EXCHANGE_free_accounts ( GNUNET_free (wa->fpayto_uri.full_payto); GNUNET_free (wa->conversion_url); + GNUNET_free (wa->open_banking_gateway); + GNUNET_free (wa->wire_transfer_gateway); GNUNET_free (wa->bank_label); free_restrictions (wa->credit_restrictions_length, wa->credit_restrictions); diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c @@ -45,7 +45,7 @@ /** * How many versions are we backwards compatible with? */ -#define EXCHANGE_PROTOCOL_AGE 7 +#define EXCHANGE_PROTOCOL_AGE 0 /** * Set to 1 for extra debug logging. @@ -929,8 +929,6 @@ TALER_EXCHANGE_decode_keys_json_ ( const json_t *fees; const json_t *wads; const char *shopping_url = NULL; - const char *open_banking_gateway = NULL; - const char *wire_transfer_gateway = NULL; const char *bank_compliance_language = NULL; struct SignatureContext sig_ctx = { 0 }; @@ -1049,14 +1047,6 @@ TALER_EXCHANGE_decode_keys_json_ ( &shopping_url), NULL), GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_string ("open_banking_gateway", - &open_banking_gateway), - NULL), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_string ("wire_transfer_gateway", - &wire_transfer_gateway), - NULL), - GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("bank_compliance_language", &bank_compliance_language), NULL), @@ -1158,10 +1148,6 @@ TALER_EXCHANGE_decode_keys_json_ ( key_data->asset_type = GNUNET_strdup (asset_type); if (NULL != shopping_url) key_data->shopping_url = GNUNET_strdup (shopping_url); - if (NULL != open_banking_gateway) - key_data->open_banking_gateway = GNUNET_strdup (open_banking_gateway); - if (NULL != wire_transfer_gateway) - key_data->wire_transfer_gateway = GNUNET_strdup (wire_transfer_gateway); if (NULL != bank_compliance_language) key_data->bank_compliance_language = GNUNET_strdup (bank_compliance_language); @@ -1714,8 +1700,6 @@ TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys) GNUNET_free (keys->currency); GNUNET_free (keys->asset_type); GNUNET_free (keys->shopping_url); - GNUNET_free (keys->open_banking_gateway); - GNUNET_free (keys->wire_transfer_gateway); GNUNET_free (keys->bank_compliance_language); for (unsigned int i = 0; i < keys->num_wad_partners; i++) GNUNET_free (keys->wad_partners[i].partner_base_url); @@ -2149,6 +2133,12 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("conversion_url", acc->conversion_url)), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("open_banking_gateway", + acc->open_banking_gateway)), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("wire_transfer_gateway", + acc->wire_transfer_gateway)), GNUNET_JSON_pack_int64 ("priority", acc->priority), GNUNET_JSON_pack_allow_null ( @@ -2324,12 +2314,6 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) GNUNET_JSON_pack_string ("shopping_url", kd->shopping_url)), GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ("open_banking_gateway", - kd->open_banking_gateway)), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ("wire_transfer_gateway", - kd->wire_transfer_gateway)), - GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("bank_compliance_language", kd->bank_compliance_language)), GNUNET_JSON_pack_bool ("disable_direct_deposit", diff --git a/src/lib/exchange_api_post-management-wire.c b/src/lib/exchange_api_post-management-wire.c @@ -79,6 +79,16 @@ struct TALER_EXCHANGE_PostManagementWireHandle char *conversion_url; /** + * URL of the open banking gateway, or NULL. + */ + char *open_banking_gateway; + + /** + * URL of the wire transfer gateway, or NULL. + */ + char *wire_transfer_gateway; + + /** * JSON encoding of debit restrictions (we hold a reference). */ json_t *debit_restrictions; @@ -195,9 +205,6 @@ TALER_EXCHANGE_post_management_wire_create ( struct GNUNET_CURL_Context *ctx, const char *url, const struct TALER_FullPayto payto_uri, - const char *conversion_url, - const json_t *debit_restrictions, - const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp validity_start, const struct TALER_MasterSignatureP *master_sig1, const struct TALER_MasterSignatureP *master_sig2) @@ -218,11 +225,10 @@ TALER_EXCHANGE_post_management_wire_create ( pmwh->ctx = ctx; pmwh->base_url = GNUNET_strdup (url); pmwh->payto_uri_str = GNUNET_strdup (payto_uri.full_payto); - pmwh->conversion_url = (NULL != conversion_url) - ? GNUNET_strdup (conversion_url) - : NULL; - pmwh->debit_restrictions = json_incref ((json_t *) debit_restrictions); - pmwh->credit_restrictions = json_incref ((json_t *) credit_restrictions); + pmwh->debit_restrictions = json_array (); + GNUNET_assert (NULL != pmwh->debit_restrictions); + pmwh->credit_restrictions = json_array (); + GNUNET_assert (NULL != pmwh->credit_restrictions); pmwh->validity_start = validity_start; pmwh->master_sig1 = *master_sig1; pmwh->master_sig2 = *master_sig2; @@ -254,6 +260,36 @@ TALER_EXCHANGE_post_management_wire_set_options_ ( case TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_PRIORITY: pmwh->priority = opt->details.priority; break; + case TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CONVERSION_URL: + GNUNET_free (pmwh->conversion_url); + pmwh->conversion_url = (NULL != opt->details.conversion_url) + ? GNUNET_strdup (opt->details.conversion_url) + : NULL; + break; + case TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_OPEN_BANKING_GATEWAY: + GNUNET_free (pmwh->open_banking_gateway); + pmwh->open_banking_gateway = (NULL != opt->details.open_banking_gateway) + ? GNUNET_strdup (opt->details.open_banking_gateway) + : NULL; + break; + case TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_WIRE_TRANSFER_GATEWAY: + GNUNET_free (pmwh->wire_transfer_gateway); + pmwh->wire_transfer_gateway = (NULL != opt->details.wire_transfer_gateway) + ? GNUNET_strdup (opt->details.wire_transfer_gateway) + : NULL; + break; + case TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CREDIT_RESTRICTIONS: + json_decref (pmwh->credit_restrictions); + pmwh->credit_restrictions = (NULL != opt->details.credit_restrictions) + ? json_incref ((json_t *) opt->details.credit_restrictions) + : json_array (); + break; + case TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_DEBIT_RESTRICTIONS: + json_decref (pmwh->debit_restrictions); + pmwh->debit_restrictions = (NULL != opt->details.debit_restrictions) + ? json_incref ((json_t *) opt->details.debit_restrictions) + : json_array (); + break; default: GNUNET_break (0); return GNUNET_SYSERR; @@ -297,6 +333,12 @@ TALER_EXCHANGE_post_management_wire_start ( GNUNET_JSON_pack_string ("conversion_url", pmwh->conversion_url)), GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("open_banking_gateway", + pmwh->open_banking_gateway)), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("wire_transfer_gateway", + pmwh->wire_transfer_gateway)), + GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("bank_label", pmwh->bank_label)), GNUNET_JSON_pack_int64 ("priority", @@ -318,8 +360,6 @@ TALER_EXCHANGE_post_management_wire_start ( if (NULL != eh) curl_easy_cleanup (eh); json_decref (body); - GNUNET_free (pmwh->url); - pmwh->url = NULL; return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; } json_decref (body); @@ -332,12 +372,7 @@ TALER_EXCHANGE_post_management_wire_start ( &handle_wire_finished, pmwh); if (NULL == pmwh->job) - { - TALER_curl_easy_post_finished (&pmwh->post_ctx); - GNUNET_free (pmwh->url); - pmwh->url = NULL; return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; - } return TALER_EC_NONE; } @@ -356,6 +391,8 @@ TALER_EXCHANGE_post_management_wire_cancel ( json_decref (pmwh->credit_restrictions); GNUNET_free (pmwh->payto_uri_str); GNUNET_free (pmwh->conversion_url); + GNUNET_free (pmwh->open_banking_gateway); + GNUNET_free (pmwh->wire_transfer_gateway); GNUNET_free (pmwh->bank_label); GNUNET_free (pmwh->url); GNUNET_free (pmwh->base_url); diff --git a/src/testing/test_exchange_api.conf b/src/testing/test_exchange_api.conf @@ -53,6 +53,7 @@ HTTP_PORT = 8082 [exchange] CURRENCY = EUR CURRENCY_ROUND_UNIT = EUR:0.01 +TINY_AMOUNT = EUR:0.01 TERMS_ETAG = exchange-tos-tops-v0 PRIVACY_ETAG = 0 PORT = 8081 diff --git a/src/testing/testing_api_cmd_wire_add.c b/src/testing/testing_api_cmd_wire_add.c @@ -155,6 +155,8 @@ wire_add_run (void *cls, &master_priv)); TALER_exchange_offline_wire_add_sign (ds->payto_uri, NULL, + NULL, + NULL, debit_rest, credit_rest, now, @@ -162,6 +164,8 @@ wire_add_run (void *cls, &master_sig1); TALER_exchange_wire_signature_make (ds->payto_uri, NULL, + NULL, + NULL, debit_rest, credit_rest, master_priv, @@ -171,20 +175,24 @@ wire_add_run (void *cls, TALER_TESTING_interpreter_get_context (is), exchange_url, ds->payto_uri, - NULL, - debit_rest, - credit_rest, now, &master_sig1, &master_sig2); - json_decref (debit_rest); - json_decref (credit_rest); if (NULL == ds->dh) { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); return; } + TALER_EXCHANGE_post_management_wire_set_options ( + ds->dh, + TALER_EXCHANGE_post_management_wire_option_bank_label ("test-account"), + TALER_EXCHANGE_post_management_wire_option_debit_restrictions ( + debit_rest), + TALER_EXCHANGE_post_management_wire_option_credit_restrictions ( + credit_rest)); + json_decref (debit_rest); + json_decref (credit_rest); TALER_EXCHANGE_post_management_wire_start (ds->dh, &wire_add_cb, ds); } diff --git a/src/util/offline_signatures.c b/src/util/offline_signatures.c @@ -685,6 +685,18 @@ struct TALER_MasterAddWirePS struct GNUNET_HashCode h_conversion_url; /** + * Hash over the open banking gateway URL, all zeros if there + * is no open banking gateway URL. + */ + struct GNUNET_HashCode h_open_banking_gateway; + + /** + * Hash over the wire transfer gateway URL, all zeros if there + * is no wire transfer gateway URL. + */ + struct GNUNET_HashCode h_wire_transfer_gateway; + + /** * Hash over the debit restrictions. */ struct GNUNET_HashCode h_debit_restrictions; @@ -693,6 +705,51 @@ struct TALER_MasterAddWirePS * Hash over the credit restrictions. */ struct GNUNET_HashCode h_credit_restrictions; + +}; + + +/** + * @brief Signature made by the exchange offline key over the information of + * a payto:// URI to be added to the exchange's set of active wire accounts. + * + * Legacy pre-v33 protocol version. + */ +struct TALER_MasterAddWire32PS +{ + + /** + * Purpose is #TALER_SIGNATURE_MASTER_ADD_WIRE. Signed + * by a `struct TALER_MasterPublicKeyP` using EdDSA. + */ + struct GNUNET_CRYPTO_SignaturePurpose purpose; + + /** + * Time of the change. + */ + struct GNUNET_TIME_TimestampNBO start_date; + + /** + * Hash over the exchange's payto URI. + */ + struct TALER_FullPaytoHashP h_payto GNUNET_PACKED; + + /** + * Hash over the conversion URL, all zeros if there + * is no conversion URL. + */ + struct GNUNET_HashCode h_conversion_url; + + /** + * Hash over the debit restrictions. + */ + struct GNUNET_HashCode h_debit_restrictions; + + /** + * Hash over the credit restrictions. + */ + struct GNUNET_HashCode h_credit_restrictions; + }; GNUNET_NETWORK_STRUCT_END @@ -702,6 +759,8 @@ void TALER_exchange_offline_wire_add_sign ( const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp now, @@ -720,6 +779,14 @@ TALER_exchange_offline_wire_add_sign ( GNUNET_CRYPTO_hash (conversion_url, strlen (conversion_url) + 1, &kv.h_conversion_url); + if (NULL != open_banking_gateway) + GNUNET_CRYPTO_hash (open_banking_gateway, + strlen (open_banking_gateway) + 1, + &kv.h_open_banking_gateway); + if (NULL != wire_transfer_gateway) + GNUNET_CRYPTO_hash (wire_transfer_gateway, + strlen (wire_transfer_gateway) + 1, + &kv.h_wire_transfer_gateway); TALER_json_hash (debit_restrictions, &kv.h_debit_restrictions); TALER_json_hash (credit_restrictions, @@ -734,6 +801,8 @@ enum GNUNET_GenericReturnValue TALER_exchange_offline_wire_add_verify ( const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp sign_time, @@ -752,6 +821,49 @@ TALER_exchange_offline_wire_add_verify ( GNUNET_CRYPTO_hash (conversion_url, strlen (conversion_url) + 1, &aw.h_conversion_url); + if (NULL != open_banking_gateway) + GNUNET_CRYPTO_hash (open_banking_gateway, + strlen (open_banking_gateway) + 1, + &aw.h_open_banking_gateway); + if (NULL != wire_transfer_gateway) + GNUNET_CRYPTO_hash (wire_transfer_gateway, + strlen (wire_transfer_gateway) + 1, + &aw.h_wire_transfer_gateway); + TALER_json_hash (debit_restrictions, + &aw.h_debit_restrictions); + TALER_json_hash (credit_restrictions, + &aw.h_credit_restrictions); + return + GNUNET_CRYPTO_eddsa_verify ( + TALER_SIGNATURE_MASTER_ADD_WIRE, + &aw, + &master_sig->eddsa_signature, + &master_pub->eddsa_pub); +} + + +enum GNUNET_GenericReturnValue +TALER_exchange_offline_wire_add_verify_32 ( + const struct TALER_FullPayto payto_uri, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + struct GNUNET_TIME_Timestamp sign_time, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig) +{ + struct TALER_MasterAddWire32PS aw = { + .purpose.purpose = htonl (TALER_SIGNATURE_MASTER_ADD_WIRE), + .purpose.size = htonl (sizeof (aw)), + .start_date = GNUNET_TIME_timestamp_hton (sign_time), + }; + + TALER_full_payto_hash (payto_uri, + &aw.h_payto); + if (NULL != conversion_url) + GNUNET_CRYPTO_hash (conversion_url, + strlen (conversion_url) + 1, + &aw.h_conversion_url); TALER_json_hash (debit_restrictions, &aw.h_debit_restrictions); TALER_json_hash (credit_restrictions, @@ -1140,6 +1252,53 @@ struct TALER_MasterWireDetailsPS struct GNUNET_HashCode h_conversion_url; /** + * Hash over the open banking gateway URL, all zeros if there + * is no open banking gateway URL. + */ + struct GNUNET_HashCode h_open_banking_gateway; + + /** + * Hash over the wire transfer gateway URL, all zeros if there + * is no wire transfer gateway URL. + */ + struct GNUNET_HashCode h_wire_transfer_gateway; + + /** + * Hash over the debit restrictions. + */ + struct GNUNET_HashCode h_debit_restrictions; + + /** + * Hash over the credit restrictions. + */ + struct GNUNET_HashCode h_credit_restrictions; + +}; + +/** + * @brief Information signed by the exchange's master + * key affirming the IBAN details for the exchange. + */ +struct TALER_MasterWireDetails32PS +{ + + /** + * Purpose is #TALER_SIGNATURE_MASTER_WIRE_DETAILS. + */ + struct GNUNET_CRYPTO_SignaturePurpose purpose; + + /** + * Hash over the account holder's payto:// URL. + */ + struct TALER_FullPaytoHashP h_wire_details GNUNET_PACKED; + + /** + * Hash over the conversion URL, all zeros if there + * is no conversion URL. + */ + struct GNUNET_HashCode h_conversion_url; + + /** * Hash over the debit restrictions. */ struct GNUNET_HashCode h_debit_restrictions; @@ -1155,9 +1314,42 @@ GNUNET_NETWORK_STRUCT_END enum GNUNET_GenericReturnValue +TALER_exchange_wire_signature_check32 ( + const struct TALER_FullPayto payto_uri, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig) +{ + struct TALER_MasterWireDetails32PS wd = { + .purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_DETAILS), + .purpose.size = htonl (sizeof (wd)) + }; + + TALER_full_payto_hash (payto_uri, + &wd.h_wire_details); + if (NULL != conversion_url) + GNUNET_CRYPTO_hash (conversion_url, + strlen (conversion_url) + 1, + &wd.h_conversion_url); + TALER_json_hash (debit_restrictions, + &wd.h_debit_restrictions); + TALER_json_hash (credit_restrictions, + &wd.h_credit_restrictions); + return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_DETAILS, + &wd, + &master_sig->eddsa_signature, + &master_pub->eddsa_pub); +} + + +enum GNUNET_GenericReturnValue TALER_exchange_wire_signature_check ( const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, const struct TALER_MasterPublicKeyP *master_pub, @@ -1174,6 +1366,14 @@ TALER_exchange_wire_signature_check ( GNUNET_CRYPTO_hash (conversion_url, strlen (conversion_url) + 1, &wd.h_conversion_url); + if (NULL != open_banking_gateway) + GNUNET_CRYPTO_hash (open_banking_gateway, + strlen (open_banking_gateway) + 1, + &wd.h_open_banking_gateway); + if (NULL != wire_transfer_gateway) + GNUNET_CRYPTO_hash (wire_transfer_gateway, + strlen (wire_transfer_gateway) + 1, + &wd.h_wire_transfer_gateway); TALER_json_hash (debit_restrictions, &wd.h_debit_restrictions); TALER_json_hash (credit_restrictions, @@ -1189,6 +1389,8 @@ void TALER_exchange_wire_signature_make ( const struct TALER_FullPayto payto_uri, const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, const json_t *debit_restrictions, const json_t *credit_restrictions, const struct TALER_MasterPrivateKeyP *master_priv, @@ -1205,6 +1407,14 @@ TALER_exchange_wire_signature_make ( GNUNET_CRYPTO_hash (conversion_url, strlen (conversion_url) + 1, &wd.h_conversion_url); + if (NULL != open_banking_gateway) + GNUNET_CRYPTO_hash (open_banking_gateway, + strlen (open_banking_gateway) + 1, + &wd.h_open_banking_gateway); + if (NULL != wire_transfer_gateway) + GNUNET_CRYPTO_hash (wire_transfer_gateway, + strlen (wire_transfer_gateway) + 1, + &wd.h_wire_transfer_gateway); TALER_json_hash (debit_restrictions, &wd.h_debit_restrictions); TALER_json_hash (credit_restrictions, diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c @@ -341,6 +341,8 @@ test_exchange_sigs (void) GNUNET_assert (NULL != rest); TALER_exchange_wire_signature_make (pt, NULL, + "https://example.com/", + NULL, rest, rest, &priv, @@ -350,6 +352,8 @@ test_exchange_sigs (void) if (GNUNET_OK != TALER_exchange_wire_signature_check (pt, NULL, + "https://example.com/", + NULL, rest, rest, &pub, @@ -362,6 +366,8 @@ test_exchange_sigs (void) TALER_exchange_wire_signature_check ( pto, NULL, + "https://example.com/", + NULL, rest, rest, &pub, @@ -374,6 +380,8 @@ test_exchange_sigs (void) TALER_exchange_wire_signature_check ( pt, "http://example.com/", + NULL, + NULL, rest, rest, &pub,