breaking protocol changes towards fixing #7810 (incomplete, taler-exchange-offline still unfinished)

This commit is contained in:
Christian Grothoff 2023-04-30 16:21:07 +02:00
parent 5ee567d1ba
commit 75f75c4a51
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
91 changed files with 2077 additions and 1302 deletions

@ -1 +1 @@
Subproject commit bd4e73b2ed06269fdee42eaad21acb5be8be9302
Subproject commit 5cfe18c5bbfd404a5f7cf27a78577c881ddb9ebd

View File

@ -1483,10 +1483,10 @@ history_debit_cb (void *cls,
switch (dhr->http_status)
{
case MHD_HTTP_OK:
for (unsigned int i = 0; i<dhr->details.success.details_length; i++)
for (unsigned int i = 0; i<dhr->details.ok.details_length; i++)
{
const struct TALER_BANK_DebitDetails *dd
= &dhr->details.success.details[i];
= &dhr->details.ok.details[i];
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Analyzing bank DEBIT at %s of %s with WTID %s\n",
GNUNET_TIME_timestamp2s (dd->execution_date),
@ -1978,10 +1978,10 @@ history_credit_cb (void *cls,
switch (chr->http_status)
{
case MHD_HTTP_OK:
for (unsigned int i = 0; i<chr->details.success.details_length; i++)
for (unsigned int i = 0; i<chr->details.ok.details_length; i++)
{
const struct TALER_BANK_CreditDetails *cd
= &chr->details.success.details[i];
= &chr->details.ok.details[i];
if (! analyze_credit (wa,
cd))

View File

@ -131,8 +131,8 @@ parse_account_history (struct TALER_BANK_CreditHistoryHandle *hh,
return GNUNET_SYSERR;
}
}
chr.details.success.details_length = len;
chr.details.success.details = cd;
chr.details.ok.details_length = len;
chr.details.ok.details = cd;
hh->hcb (hh->hcb_cls,
&chr);
}

View File

@ -133,8 +133,8 @@ parse_account_history (struct TALER_BANK_DebitHistoryHandle *hh,
return GNUNET_SYSERR;
}
}
dhr.details.success.details_length = len;
dhr.details.success.details = dd;
dhr.details.ok.details_length = len;
dhr.details.ok.details = dd;
hh->hcb (hh->hcb_cls,
&dhr);
}

View File

@ -179,10 +179,10 @@ credit_history_cb (void *cls,
global_ret = 0;
break;
case MHD_HTTP_OK:
for (unsigned int i = 0; i<reply->details.success.details_length; i++)
for (unsigned int i = 0; i<reply->details.ok.details_length; i++)
{
const struct TALER_BANK_CreditDetails *cd =
&reply->details.success.details[i];
&reply->details.ok.details[i];
/* If credit/debit accounts were specified, use as a filter */
if ( (NULL != credit_account) &&
@ -279,10 +279,10 @@ debit_history_cb (void *cls,
global_ret = 0;
break;
case MHD_HTTP_OK:
for (unsigned int i = 0; i<reply->details.success.details_length; i++)
for (unsigned int i = 0; i<reply->details.ok.details_length; i++)
{
const struct TALER_BANK_DebitDetails *dd =
&reply->details.success.details[i];
&reply->details.ok.details[i];
/* If credit/debit accounts were specified, use as a filter */
if ( (NULL != credit_account) &&

View File

@ -644,26 +644,19 @@ do_upload (char *const *args)
* a particular exchange and what keys the exchange is using.
*
* @param cls closure with the `char **` remaining args
* @param hr HTTP response data
* @param keys information about the various keys used
* by the exchange, NULL if /keys failed
* @param compat protocol compatibility information
* @param kr response data
*/
static void
keys_cb (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_EXCHANGE_Keys *keys,
enum TALER_EXCHANGE_VersionCompatibility compat)
const struct TALER_EXCHANGE_KeysResponse *kr)
{
char *const *args = cls;
(void) keys;
(void) compat;
switch (hr->http_status)
switch (kr->hr.http_status)
{
case MHD_HTTP_OK:
if (! json_is_object (hr->reply))
if (! json_is_object (kr->hr.reply))
{
GNUNET_break (0);
TALER_EXCHANGE_disconnect (exchange);
@ -676,9 +669,9 @@ keys_cb (
default:
fprintf (stderr,
"Failed to download keys: %s (HTTP status: %u/%u)\n",
hr->hint,
hr->http_status,
(unsigned int) hr->ec);
kr->hr.hint,
kr->hr.http_status,
(unsigned int) kr->hr.ec);
TALER_EXCHANGE_disconnect (exchange);
exchange = NULL;
test_shutdown ();
@ -689,7 +682,7 @@ keys_cb (
GNUNET_JSON_pack_string ("operation",
OP_INPUT_KEYS),
GNUNET_JSON_pack_object_incref ("arguments",
(json_t *) hr->reply));
(json_t *) kr->hr.reply));
if (NULL == args[0])
{
json_dumpf (in,

View File

@ -1119,14 +1119,15 @@ load_offline_key (int do_create)
* Function called with information about the post revocation operation result.
*
* @param cls closure with a `struct DenomRevocationRequest`
* @param hr HTTP response data
* @param dr response data
*/
static void
denom_revocation_cb (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementRevokeDenominationResponse *dr)
{
struct DenomRevocationRequest *drr = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &dr->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@ -1208,14 +1209,15 @@ upload_denom_revocation (const char *exchange_url,
* Function called with information about the post revocation operation result.
*
* @param cls closure with a `struct SignkeyRevocationRequest`
* @param hr HTTP response data
* @param sr response data
*/
static void
signkey_revocation_cb (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementRevokeSigningKeyResponse *sr)
{
struct SignkeyRevocationRequest *srr = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &sr->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@ -1489,13 +1491,14 @@ upload_auditor_del (const char *exchange_url,
* Function called with information about the post wire add operation result.
*
* @param cls closure with a `struct WireAddRequest`
* @param hr HTTP response data
* @param wer response data
*/
static void
wire_add_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementWireEnableResponse *wer)
{
struct WireAddRequest *war = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &wer->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@ -1533,10 +1536,21 @@ upload_wire_add (const char *exchange_url,
struct GNUNET_TIME_Timestamp start_time;
struct WireAddRequest *war;
const char *err_name;
const char *conversion_url = NULL;
json_t *debit_restrictions;
json_t *credit_restrictions;
unsigned int err_line;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("payto_uri",
&payto_uri),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("conversion_url",
&conversion_url),
NULL),
GNUNET_JSON_spec_json ("debit_restrictions",
&debit_restrictions),
GNUNET_JSON_spec_json ("credit_restrictions",
&credit_restrictions),
GNUNET_JSON_spec_timestamp ("validity_start",
&start_time),
GNUNET_JSON_spec_fixed_auto ("master_sig_add",
@ -1561,6 +1575,7 @@ upload_wire_add (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
GNUNET_JSON_parse_free (spec);
test_shutdown ();
return;
}
@ -1574,6 +1589,7 @@ upload_wire_add (const char *exchange_url,
"payto:// URI `%s' is malformed\n",
payto_uri);
global_ret = EXIT_FAILURE;
GNUNET_JSON_parse_free (spec);
test_shutdown ();
return;
}
@ -1588,6 +1604,7 @@ upload_wire_add (const char *exchange_url,
"payto URI is malformed: %s\n",
msg);
GNUNET_free (msg);
GNUNET_JSON_parse_free (spec);
test_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
@ -1599,6 +1616,9 @@ upload_wire_add (const char *exchange_url,
TALER_EXCHANGE_management_enable_wire (ctx,
exchange_url,
payto_uri,
conversion_url,
debit_restrictions,
credit_restrictions,
start_time,
&master_sig_add,
&master_sig_wire,
@ -1607,6 +1627,7 @@ upload_wire_add (const char *exchange_url,
GNUNET_CONTAINER_DLL_insert (war_head,
war_tail,
war);
GNUNET_JSON_parse_free (spec);
}
@ -1614,13 +1635,14 @@ upload_wire_add (const char *exchange_url,
* Function called with information about the post wire del operation result.
*
* @param cls closure with a `struct WireDelRequest`
* @param hr HTTP response data
* @param wdres response data
*/
static void
wire_del_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementWireDisableResponse *wdres)
{
struct WireDelRequest *wdr = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &wdres->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@ -1927,14 +1949,15 @@ upload_global_fee (const char *exchange_url,
* Function called with information about the drain profits operation.
*
* @param cls closure with a `struct DrainProfitsRequest`
* @param hr HTTP response data
* @param mdr response data
*/
static void
drain_profits_cb (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementDrainResponse *mdr)
{
struct DrainProfitsRequest *dpr = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &mdr->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@ -2033,14 +2056,15 @@ upload_drain (const char *exchange_url,
* Function called with information about the post upload keys operation result.
*
* @param cls closure with a `struct UploadKeysRequest`
* @param hr HTTP response data
* @param mr response data
*/
static void
keys_cb (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementPostKeysResponse *mr)
{
struct UploadKeysRequest *ukr = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &mr->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@ -2206,14 +2230,15 @@ upload_keys (const char *exchange_url,
* Function called with information about the post upload extensions operation result.
*
* @param cls closure with a `struct UploadExtensionsRequest`
* @param hr HTTP response data
* @param er response data
*/
static void
extensions_cb (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementPostExtensionsResponse *er)
{
struct UploadExtensionsRequest *uer = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &er->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@ -2447,14 +2472,15 @@ add_partner (const char *exchange_url,
* Function called with information about the AML officer update operation.
*
* @param cls closure with a `struct AmlStaffRequest`
* @param hr HTTP response data
* @param ar response data
*/
static void
update_aml_officer_cb (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementUpdateAmlOfficerResponse *ar)
{
struct AmlStaffRequest *asr = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &ar->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@ -2961,6 +2987,10 @@ do_add_wire (char *const *args)
struct TALER_MasterSignatureP master_sig_add;
struct TALER_MasterSignatureP master_sig_wire;
struct GNUNET_TIME_Timestamp now;
const char *conversion_url = NULL;
json_t *debit_restrictions;
json_t *credit_restrictions;
unsigned int num_args = 1;
if (NULL != in)
{
@ -3011,24 +3041,43 @@ do_add_wire (char *const *args)
}
GNUNET_free (wire_method);
}
// FIXME: init new args properly!
debit_restrictions = json_array ();
GNUNET_assert (NULL != debit_restrictions);
credit_restrictions = json_array ();
GNUNET_assert (NULL != credit_restrictions);
TALER_exchange_offline_wire_add_sign (args[0],
conversion_url,
debit_restrictions,
credit_restrictions,
now,
&master_priv,
&master_sig_add);
TALER_exchange_wire_signature_make (args[0],
conversion_url,
debit_restrictions,
credit_restrictions,
&master_priv,
&master_sig_wire);
output_operation (OP_ENABLE_WIRE,
GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("payto_uri",
args[0]),
GNUNET_JSON_pack_array_steal ("debit_restrictions",
debit_restrictions),
GNUNET_JSON_pack_array_steal ("credit_restrictions",
credit_restrictions),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_string ("conversion_url",
conversion_url)),
GNUNET_JSON_pack_timestamp ("validity_start",
now),
GNUNET_JSON_pack_data_auto ("master_sig_add",
&master_sig_add),
GNUNET_JSON_pack_data_auto ("master_sig_wire",
&master_sig_wire)));
next (args + 1);
next (args + num_args);
}
@ -3643,18 +3692,15 @@ enable_aml_staff (char *const *args)
* whether there are subsequent commands).
*
* @param cls closure with the `char **` remaining args
* @param hr HTTP response data
* @param keys information about the various keys used
* by the exchange, NULL if /management/keys failed
* @param mgr response data
*/
static void
download_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_EXCHANGE_FutureKeys *keys)
const struct TALER_EXCHANGE_ManagementGetKeysResponse *mgr)
{
char *const *args = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &mgr->hr;
(void) keys;
mgkh = NULL;
switch (hr->http_status)
{

View File

@ -41,7 +41,7 @@
*
* Returned via both /config and /keys endpoints.
*/
#define EXCHANGE_PROTOCOL_VERSION "14:0:2"
#define EXCHANGE_PROTOCOL_VERSION "15:0:0"
/**

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2020 Taler Systems SA
Copyright (C) 2020-2023 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
@ -114,6 +114,9 @@ del_wire (void *cls,
}
qs = TEH_plugin->update_wire (TEH_plugin->cls,
awc->payto_uri,
NULL,
NULL,
NULL,
awc->validity_end,
false);
if (qs < 0)

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2020 Taler Systems SA
Copyright (C) 2020-2023 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
@ -54,6 +54,21 @@ struct AddWireContext
*/
const char *payto_uri;
/**
* (optional) address of a conversion service for this account.
*/
const char *conversion_url;
/**
* Restrictions imposed when crediting this account.
*/
json_t *credit_restrictions;
/**
* Restrictions imposed when debiting this account.
*/
json_t *debit_restrictions;
/**
* Timestamp for checking against replay attacks.
*/
@ -114,11 +129,17 @@ add_wire (void *cls,
if (0 == qs)
qs = TEH_plugin->insert_wire (TEH_plugin->cls,
awc->payto_uri,
awc->conversion_url,
awc->debit_restrictions,
awc->credit_restrictions,
awc->validity_start,
&awc->master_sig_wire);
else
qs = TEH_plugin->update_wire (TEH_plugin->cls,
awc->payto_uri,
awc->conversion_url,
awc->debit_restrictions,
awc->credit_restrictions,
awc->validity_start,
true);
if (qs < 0)
@ -141,7 +162,9 @@ TEH_handler_management_post_wire (
struct MHD_Connection *connection,
const json_t *root)
{
struct AddWireContext awc;
struct AddWireContext awc = {
.conversion_url = NULL
};
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("master_sig_wire",
&awc.master_sig_wire),
@ -149,6 +172,14 @@ TEH_handler_management_post_wire (
&awc.master_sig_add),
GNUNET_JSON_spec_string ("payto_uri",
&awc.payto_uri),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("conversion_url",
&awc.conversion_url),
NULL),
GNUNET_JSON_spec_json ("credit_restrictions",
&awc.credit_restrictions),
GNUNET_JSON_spec_json ("debit_restrictions",
&awc.debit_restrictions),
GNUNET_JSON_spec_timestamp ("validity_start",
&awc.validity_start),
GNUNET_JSON_spec_end ()
@ -179,17 +210,22 @@ TEH_handler_management_post_wire (
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
msg);
GNUNET_JSON_parse_free (spec);
GNUNET_free (msg);
return ret;
}
}
if (GNUNET_OK !=
TALER_exchange_offline_wire_add_verify (awc.payto_uri,
awc.conversion_url,
awc.debit_restrictions,
awc.credit_restrictions,
awc.validity_start,
&TEH_master_public_key,
&awc.master_sig_add))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_FORBIDDEN,
@ -199,10 +235,14 @@ TEH_handler_management_post_wire (
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
if (GNUNET_OK !=
TALER_exchange_wire_signature_check (awc.payto_uri,
awc.conversion_url,
awc.debit_restrictions,
awc.credit_restrictions,
&TEH_master_public_key,
&awc.master_sig_wire))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_FORBIDDEN,
@ -218,6 +258,7 @@ TEH_handler_management_post_wire (
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"payto:// URI `%s' is malformed\n",
awc.payto_uri);
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_BAD_REQUEST,
@ -237,6 +278,7 @@ TEH_handler_management_post_wire (
&ret,
&add_wire,
&awc);
GNUNET_JSON_parse_free (spec);
if (GNUNET_SYSERR == res)
return ret;
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2015-2022 Taler Systems SA
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 Affero General Public License as published by the Free Software
@ -224,12 +224,18 @@ TEH_wire_done ()
*
* @param cls a `json_t *` object 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 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
* account of the exchange (of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS)
*/
static void
add_wire_account (void *cls,
const char *payto_uri,
const char *conversion_url,
const json_t *debit_restrictions,
const json_t *credit_restrictions,
const struct TALER_MasterSignatureP *master_sig)
{
json_t *a = cls;
@ -240,6 +246,13 @@ add_wire_account (void *cls,
GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("payto_uri",
payto_uri),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_string ("conversion_url",
conversion_url)),
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))))
{
@ -462,6 +475,8 @@ build_wire_state (void)
wsh->wire_reply = TALER_MHD_MAKE_JSON_PACK (
GNUNET_JSON_pack_array_steal ("accounts",
wire_accounts_array),
GNUNET_JSON_pack_array_steal ("wads", /* #7271 */
json_array ()),
GNUNET_JSON_pack_object_steal ("fees",
wire_fee_object),
GNUNET_JSON_pack_data_auto ("master_public_key",

View File

@ -731,8 +731,8 @@ history_cb (void *cls,
{
case MHD_HTTP_OK:
process_reply (wrap_size,
reply->details.success.details,
reply->details.success.details_length);
reply->details.ok.details,
reply->details.ok.details_length);
return;
case MHD_HTTP_NO_CONTENT:
transaction_completed ();

View File

@ -13,3 +13,4 @@ test-exchangedb-by-j-postgres
test-exchangedb-populate-link-data-postgres
test-exchangedb-populate-ready-deposit-postgres
test-exchangedb-populate-select-refunds-by-coin-postgres
exchange-0004.sql

View File

@ -0,0 +1,26 @@
--
-- This file is part of TALER
-- Copyright (C) 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/>
--
ALTER TABLE wire_accounts
ADD COLUMN conversion_url VARCHAR DEFAULT (NULL),
ADD COLUMN debit_restrictions VARCHAR DEFAULT (NULL),
ADD COLUMN credit_restrictions VARCHAR DEFAULT (NULL);
COMMENT ON COLUMN wire_accounts.conversion_url
IS 'URL of a currency conversion service if conversion is needed when this account is used; NULL if there is no conversion.';
COMMENT ON COLUMN wire_accounts.debit_restrictions
IS 'JSON array describing restrictions imposed when debiting this account. Empty for no restrictions, NULL if account was migrated from previous database revision or account is disabled.';
COMMENT ON COLUMN wire_accounts.credit_restrictions
IS 'JSON array describing restrictions imposed when crediting this account. Empty for no restrictions, NULL if account was migrated from previous database revision or account is disabled.';

View File

@ -20,7 +20,9 @@ sqlinputs = \
0002-*.sql \
exchange-0002.sql.in \
0003-*.sql \
exchange-0003.sql.in
exchange-0003.sql.in \
0004-*.sql \
exchange-0004.sql.in
sql_DATA = \
benchmark-0001.sql \
@ -28,6 +30,7 @@ sql_DATA = \
exchange-0001.sql \
exchange-0002.sql \
exchange-0003.sql \
exchange-0004.sql \
drop.sql \
procedures.sql
@ -39,7 +42,8 @@ BUILT_SOURCES = \
CLEANFILES = \
exchange-0002.sql \
exchange-0003.sql
exchange-0003.sql \
exchange-0004.sql
procedures.sql: procedures.sql.in exchange_do_*.sql
chmod +w $@ || true
@ -56,6 +60,11 @@ exchange-0003.sql: exchange-0003.sql.in 0003-*.sql
gcc -E -P -undef - < exchange-0003.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@
chmod ugo-w $@
exchange-0004.sql: exchange-0004.sql.in 0004-*.sql
chmod +w $@ || true
gcc -E -P -undef - < exchange-0004.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@
chmod ugo-w $@
EXTRA_DIST = \
exchangedb.conf \
exchangedb-postgres.conf \

View File

@ -21,6 +21,7 @@ BEGIN;
SELECT _v.unregister_patch('exchange-0001');
SELECT _v.unregister_patch('exchange-0002');
SELECT _v.unregister_patch('exchange-0003');
SELECT _v.unregister_patch('exchange-0004');
DROP SCHEMA exchange CASCADE;

View File

@ -0,0 +1,24 @@
--
-- This file is part of TALER
-- Copyright (C) 2014--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/>
--
BEGIN;
SELECT _v.register_patch('exchange-0004', NULL, NULL);
SET search_path TO exchange;
#include "0004-wire_accounts.sql"
COMMIT;

View File

@ -66,10 +66,25 @@ get_wire_accounts_cb (void *cls,
for (unsigned int i = 0; i < num_results; i++)
{
char *payto_uri;
char *conversion_url = NULL;
json_t *debit_restrictions = NULL;
json_t *credit_restrictions = NULL;
struct TALER_MasterSignatureP master_sig;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_string ("payto_uri",
&payto_uri),
GNUNET_PQ_result_spec_allow_null (
GNUNET_PQ_result_spec_string ("conversion_url",
&conversion_url),
NULL),
GNUNET_PQ_result_spec_allow_null (
TALER_PQ_result_spec_json ("debit_restrictions",
&debit_restrictions),
NULL),
GNUNET_PQ_result_spec_allow_null (
TALER_PQ_result_spec_json ("credit_restrictions",
&credit_restrictions),
NULL),
GNUNET_PQ_result_spec_auto_from_type ("master_sig",
&master_sig),
GNUNET_PQ_result_spec_end
@ -84,8 +99,21 @@ get_wire_accounts_cb (void *cls,
ctx->status = GNUNET_SYSERR;
return;
}
if (NULL == debit_restrictions)
{
debit_restrictions = json_array ();
GNUNET_assert (NULL != debit_restrictions);
}
if (NULL == credit_restrictions)
{
credit_restrictions = json_array ();
GNUNET_assert (NULL != credit_restrictions);
}
ctx->cb (ctx->cb_cls,
payto_uri,
conversion_url,
debit_restrictions,
credit_restrictions,
&master_sig);
GNUNET_PQ_cleanup_result (rs);
}
@ -112,6 +140,9 @@ TEH_PG_get_wire_accounts (void *cls,
"get_wire_accounts",
"SELECT"
" payto_uri"
",conversion_url"
",debit_restrictions"
",credit_restrictions"
",master_sig"
" FROM wire_accounts"
" WHERE is_active");
@ -123,5 +154,4 @@ TEH_PG_get_wire_accounts (void *cls,
if (GNUNET_OK != ctx.status)
return GNUNET_DB_STATUS_HARD_ERROR;
return qs;
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2022 Taler Systems SA
Copyright (C) 2022, 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
@ -29,12 +29,20 @@
enum GNUNET_DB_QueryStatus
TEH_PG_insert_wire (void *cls,
const char *payto_uri,
const char *conversion_url,
json_t *debit_restrictions,
json_t *credit_restrictions,
struct GNUNET_TIME_Timestamp start_date,
const struct TALER_MasterSignatureP *master_sig)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (payto_uri),
NULL == conversion_url
? GNUNET_PQ_query_param_null ()
: GNUNET_PQ_query_param_string (conversion_url),
TALER_PQ_query_param_json (debit_restrictions),
TALER_PQ_query_param_json (credit_restrictions),
GNUNET_PQ_query_param_auto_from_type (master_sig),
GNUNET_PQ_query_param_timestamp (&start_date),
GNUNET_PQ_query_param_end
@ -44,11 +52,14 @@ TEH_PG_insert_wire (void *cls,
"insert_wire",
"INSERT INTO wire_accounts "
"(payto_uri"
",conversion_url"
",debit_restrictions"
",credit_restrictions"
",master_sig"
",is_active"
",last_change"
") VALUES "
"($1, $2, true, $3);");
"($1, $2, $3, $4, $5, true, $6);");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
"insert_wire",
params);

View File

@ -29,6 +29,9 @@
*
* @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 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
* (only to be used for replay detection)
* @param master_sig public signature affirming the existence of the account,
@ -38,6 +41,9 @@
enum GNUNET_DB_QueryStatus
TEH_PG_insert_wire (void *cls,
const char *payto_uri,
const char *conversion_url,
json_t *debit_restrictions,
json_t *credit_restrictions,
struct GNUNET_TIME_Timestamp start_date,
const struct TALER_MasterSignatureP *master_sig);

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2022 Taler Systems SA
Copyright (C) 2022, 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
@ -29,6 +29,9 @@
enum GNUNET_DB_QueryStatus
TEH_PG_update_wire (void *cls,
const char *payto_uri,
const char *conversion_url,
json_t *debit_restrictions,
json_t *credit_restrictions,
struct GNUNET_TIME_Timestamp change_date,
bool enabled)
{
@ -36,17 +39,28 @@ TEH_PG_update_wire (void *cls,
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (payto_uri),
GNUNET_PQ_query_param_bool (enabled),
NULL == conversion_url
? GNUNET_PQ_query_param_null ()
: GNUNET_PQ_query_param_string (conversion_url),
enabled
? TALER_PQ_query_param_json (debit_restrictions)
: GNUNET_PQ_query_param_null (),
enabled
? TALER_PQ_query_param_json (credit_restrictions)
: GNUNET_PQ_query_param_null (),
GNUNET_PQ_query_param_timestamp (&change_date),
GNUNET_PQ_query_param_end
};
/* used in #postgres_update_wire() */
PREPARE (pg,
"update_wire",
"UPDATE wire_accounts"
" SET"
" is_active=$2"
" ,last_change=$3"
" ,conversion_url=$3"
" ,debit_restrictions=$4"
" ,credit_restrictions=$5"
" ,last_change=$6"
" WHERE payto_uri=$1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
"update_wire",

View File

@ -24,11 +24,16 @@
#include "taler_util.h"
#include "taler_json_lib.h"
#include "taler_exchangedb_plugin.h"
/**
* Update information about a wire account of the exchange.
*
* @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 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
* (only to be used for replay detection)
* @param enabled true to enable, false to disable (the actual change)
@ -37,6 +42,9 @@
enum GNUNET_DB_QueryStatus
TEH_PG_update_wire (void *cls,
const char *payto_uri,
const char *conversion_url,
json_t *debit_restrictions,
json_t *credit_restrictions,
struct GNUNET_TIME_Timestamp change_date,
bool enabled);

View File

@ -111,6 +111,7 @@ struct TALER_BANK_AdminAddIncomingHandle;
* @param timestamp time when the transaction was made.
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
*/
// FIXME: bad API
typedef void
(*TALER_BANK_AdminAddIncomingCallback) (
void *cls,
@ -199,6 +200,7 @@ struct TALER_BANK_TransferHandle;
* @param row_id unique ID of the wire transfer in the bank's records
* @param timestamp when did the transaction go into effect
*/
// FIXME: bad API
typedef void
(*TALER_BANK_TransferCallback)(
void *cls,
@ -337,7 +339,7 @@ struct TALER_BANK_CreditHistoryResponse
*/
unsigned int details_length;
} success;
} ok;
} details;
@ -493,7 +495,7 @@ struct TALER_BANK_DebitHistoryResponse
*/
unsigned int details_length;
} success;
} ok;
} details;

View File

@ -5512,6 +5512,9 @@ TALER_exchange_offline_global_fee_verify (
* Create wire account addition signature.
*
* @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 now timestamp to use for the signature (rounded)
* @param master_priv private key to sign with
* @param[out] master_sig where to write the signature
@ -5519,6 +5522,9 @@ TALER_exchange_offline_global_fee_verify (
void
TALER_exchange_offline_wire_add_sign (
const char *payto_uri,
const char *conversion_url,
const json_t *debit_restrictions,
const json_t *credit_restrictions,
struct GNUNET_TIME_Timestamp now,
const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig);
@ -5528,6 +5534,9 @@ TALER_exchange_offline_wire_add_sign (
* Verify wire account addition signature.
*
* @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
@ -5536,6 +5545,9 @@ TALER_exchange_offline_wire_add_sign (
enum GNUNET_GenericReturnValue
TALER_exchange_offline_wire_add_verify (
const char *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);
@ -5578,6 +5590,9 @@ TALER_exchange_offline_wire_del_verify (
* Check the signature in @a master_sig.
*
* @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
@ -5585,6 +5600,9 @@ TALER_exchange_offline_wire_del_verify (
enum GNUNET_GenericReturnValue
TALER_exchange_wire_signature_check (
const char *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);
@ -5593,12 +5611,18 @@ TALER_exchange_wire_signature_check (
* Create a signed wire statement for the given account.
*
* @param payto_uri account specification
* @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_priv private key to sign with
* @param[out] master_sig where to write the signature
*/
void
TALER_exchange_wire_signature_make (
const char *payto_uri,
const char *conversion_url,
const json_t *debit_restrictions,
const json_t *credit_restrictions,
const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig);

File diff suppressed because it is too large Load Diff

View File

@ -2881,6 +2881,9 @@ 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 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
* account of the exchange (of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS)
*/
@ -2888,6 +2891,9 @@ typedef void
(*TALER_EXCHANGEDB_WireAccountCallback)(
void *cls,
const char *payto_uri,
const char *conversion_url,
const json_t *debit_restrictions,
const json_t *credit_restrictions,
const struct TALER_MasterSignatureP *master_sig);
@ -5544,6 +5550,9 @@ 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 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
* (only to be used for replay detection)
* @param master_sig public signature affirming the existence of the account,
@ -5553,6 +5562,9 @@ struct TALER_EXCHANGEDB_Plugin
enum GNUNET_DB_QueryStatus
(*insert_wire)(void *cls,
const char *payto_uri,
const char *conversion_url,
json_t *debit_restrictions,
json_t *credit_restrictions,
struct GNUNET_TIME_Timestamp start_date,
const struct TALER_MasterSignatureP *master_sig);
@ -5562,6 +5574,9 @@ 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 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
* (only to be used for replay detection)
* @param enabled true to enable, false to disable (the actual change)
@ -5570,6 +5585,9 @@ struct TALER_EXCHANGEDB_Plugin
enum GNUNET_DB_QueryStatus
(*update_wire)(void *cls,
const char *payto_uri,
const char *conversion_url,
json_t *debit_restrictions,
json_t *credit_restrictions,
struct GNUNET_TIME_Timestamp change_date,
bool enabled);

View File

@ -674,33 +674,6 @@ TALER_JSON_merchant_wire_signature_hash (const json_t *wire_s,
struct TALER_MerchantWireHashP *hc);
/**
* Check the signature in @a wire_s. Also performs rudimentary
* checks on the account data *if* supported.
*
* @param wire_s signed wire information of an exchange
* @param master_pub master public key of the exchange
* @return #GNUNET_OK if signature is valid
*/
enum GNUNET_GenericReturnValue
TALER_JSON_exchange_wire_signature_check (
const json_t *wire_s,
const struct TALER_MasterPublicKeyP *master_pub);
/**
* Create a signed wire statement for the given account.
*
* @param payto_uri account specification
* @param master_priv private key to sign with
* @return NULL if @a payto_uri is malformed
*/
json_t *
TALER_JSON_exchange_wire_signature_make (
const char *payto_uri,
const struct TALER_MasterPrivateKeyP *master_priv);
/**
* Extract a string from @a object under the field @a field, but respecting
* the Taler i18n rules and the language preferences expressed in @a

View File

@ -147,15 +147,11 @@ TALER_TESTING_prepare_exchange (const char *config_filename,
*
* @param cls closure, typically, the "run" method containing
* all the commands to be run, and a closure for it.
* @param hr http response details
* @param keys the exchange's keys.
* @param compat protocol compatibility information.
* @param kr response details
*/
void
TALER_TESTING_cert_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_EXCHANGE_Keys *keys,
enum TALER_EXCHANGE_VersionCompatibility compat);
const struct TALER_EXCHANGE_KeysResponse *kr);
/**

View File

@ -28,12 +28,10 @@ libtalerjson_la_LIBADD = \
$(XLIB)
TESTS = \
test_json \
test_json_wire
test_json
check_PROGRAMS= \
test_json \
test_json_wire
test_json
test_json_SOURCES = \
test_json.c
@ -43,13 +41,3 @@ test_json_LDADD = \
$(top_builddir)/src/util/libtalerutil.la \
-lgnunetutil \
-ljansson
test_json_wire_SOURCES = \
test_json_wire.c
test_json_wire_LDADD = \
$(top_builddir)/src/json/libtalerjson.la \
-lgnunetjson \
$(top_builddir)/src/util/libtalerutil.la \
-lgnunetutil \
-ljansson

View File

@ -70,80 +70,6 @@ TALER_JSON_merchant_wire_signature_hash (const json_t *wire_s,
}
enum GNUNET_GenericReturnValue
TALER_JSON_exchange_wire_signature_check (
const json_t *wire_s,
const struct TALER_MasterPublicKeyP *master_pub)
{
const char *payto_uri;
struct TALER_MasterSignatureP master_sig;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("payto_uri",
&payto_uri),
GNUNET_JSON_spec_fixed_auto ("master_sig",
&master_sig),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (wire_s,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
{
char *err;
err = TALER_payto_validate (payto_uri);
if (NULL != err)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"URI `%s' ill-formed: %s\n",
payto_uri,
err);
GNUNET_free (err);
return GNUNET_SYSERR;
}
}
return TALER_exchange_wire_signature_check (payto_uri,
master_pub,
&master_sig);
}
json_t *
TALER_JSON_exchange_wire_signature_make (
const char *payto_uri,
const struct TALER_MasterPrivateKeyP *master_priv)
{
struct TALER_MasterSignatureP master_sig;
char *err;
if (NULL !=
(err = TALER_payto_validate (payto_uri)))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Invalid payto URI `%s': %s\n",
payto_uri,
err);
GNUNET_free (err);
return NULL;
}
TALER_exchange_wire_signature_make (payto_uri,
master_priv,
&master_sig);
return GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("payto_uri",
payto_uri),
GNUNET_JSON_pack_data_auto ("master_sig",
&master_sig));
}
char *
TALER_JSON_wire_to_payto (const json_t *wire_s)
{

View File

@ -1,80 +0,0 @@
/*
This file is part of TALER
(C) 2015, 2016 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 json/test_json_wire.c
* @brief Tests for Taler-specific crypto logic
* @author Christian Grothoff <christian@grothoff.org>
*/
#include "platform.h"
#include "taler_util.h"
#include "taler_json_lib.h"
int
main (int argc,
const char *const argv[])
{
struct TALER_MasterPublicKeyP master_pub;
struct TALER_MasterPrivateKeyP master_priv;
json_t *wire_xtalerbank;
json_t *wire_iban;
const char *payto_xtalerbank = "payto://x-taler-bank/42";
const char *payto_iban =
"payto://iban/BIC-TO-BE-SKIPPED/DE89370400440532013000?receiver-name=Test";
char *p_xtalerbank;
char *p_iban;
(void) argc;
(void) argv;
GNUNET_log_setup ("test-json-wire",
"WARNING",
NULL);
GNUNET_CRYPTO_eddsa_key_create (&master_priv.eddsa_priv);
GNUNET_CRYPTO_eddsa_key_get_public (&master_priv.eddsa_priv,
&master_pub.eddsa_pub);
wire_xtalerbank = TALER_JSON_exchange_wire_signature_make (payto_xtalerbank,
&master_priv);
wire_iban = TALER_JSON_exchange_wire_signature_make (payto_iban,
&master_priv);
if (NULL == wire_iban)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not parse payto/IBAN (%s) into 'wire object'\n",
payto_iban);
return 1;
}
p_xtalerbank = TALER_JSON_wire_to_payto (wire_xtalerbank);
p_iban = TALER_JSON_wire_to_payto (wire_iban);
GNUNET_assert (0 == strcmp (p_xtalerbank, payto_xtalerbank));
GNUNET_assert (0 == strcmp (p_iban, payto_iban));
GNUNET_free (p_xtalerbank);
GNUNET_free (p_iban);
GNUNET_assert (GNUNET_OK ==
TALER_JSON_exchange_wire_signature_check (wire_xtalerbank,
&master_pub));
GNUNET_assert (GNUNET_OK ==
TALER_JSON_exchange_wire_signature_check (wire_iban,
&master_pub));
json_decref (wire_xtalerbank);
json_decref (wire_iban);
return 0;
}
/* end of test_json_wire.c */

View File

@ -247,7 +247,7 @@ handle_deposit_finished (void *cls,
&dh->exchange_pub),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("transaction_base_url",
&dr.details.success.transaction_base_url),
&dr.details.ok.transaction_base_url),
NULL),
GNUNET_JSON_spec_timestamp ("exchange_timestamp",
&dh->exchange_timestamp),
@ -341,10 +341,10 @@ handle_deposit_finished (void *cls,
dh);
GNUNET_JSON_parse_free (spec);
}
dr.details.success.exchange_sigs = dh->exchange_sigs;
dr.details.success.exchange_pub = &dh->exchange_pub;
dr.details.success.deposit_timestamp = dh->exchange_timestamp;
dr.details.success.num_signatures = dh->num_cdds;
dr.details.ok.exchange_sigs = dh->exchange_sigs;
dr.details.ok.exchange_pub = &dh->exchange_pub;
dr.details.ok.deposit_timestamp = dh->exchange_timestamp;
dr.details.ok.num_signatures = dh->num_cdds;
break;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy

View File

@ -144,37 +144,34 @@ struct TALER_EXCHANGE_BatchWithdrawHandle
* HTTP /reserves/$RESERVE_PUB/batch-withdraw request.
*
* @param cls the `struct TALER_EXCHANGE_BatchWithdrawHandle`
* @param hr HTTP response data
* @param blind_sigs array of blind signatures over the coins, NULL on error
* @param blind_sigs_length length of the @a blind_sigs array
* @param bw2r response data
*/
static void
handle_reserve_batch_withdraw_finished (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_BlindedDenominationSignature *blind_sigs,
unsigned int blind_sigs_length)
const struct TALER_EXCHANGE_BatchWithdraw2Response *bw2r)
{
struct TALER_EXCHANGE_BatchWithdrawHandle *wh = cls;
struct TALER_EXCHANGE_BatchWithdrawResponse wr = {
.hr = *hr
.hr = bw2r->hr
};
struct TALER_EXCHANGE_PrivateCoinDetails coins[wh->num_coins];
struct TALER_EXCHANGE_PrivateCoinDetails coins[GNUNET_NZL (wh->num_coins)];
wh->wh2 = NULL;
memset (coins,
0,
sizeof (coins));
if (blind_sigs_length != wh->num_coins)
switch (bw2r->hr.http_status)
{
case MHD_HTTP_OK:
{
if (bw2r->details.ok.blind_sigs_length != wh->num_coins)
{
GNUNET_break_op (0);
wr.hr.http_status = 0;
wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
switch (hr->http_status)
{
case MHD_HTTP_OK:
{
for (unsigned int i = 0; i<wh->num_coins; i++)
{
struct CoinData *cd = &wh->coins[i];
@ -183,7 +180,7 @@ handle_reserve_batch_withdraw_finished (
if (GNUNET_OK !=
TALER_planchet_to_coin (&cd->pk.key,
&blind_sigs[i],
&bw2r->details.ok.blind_sigs[i],
&cd->bks,
&cd->priv,
cd->ach,
@ -200,8 +197,8 @@ handle_reserve_batch_withdraw_finished (
coin->sig = fc.sig;
coin->exchange_vals = cd->alg_values;
}
wr.details.success.coins = coins;
wr.details.success.num_coins = wh->num_coins;
wr.details.ok.coins = coins;
wr.details.ok.num_coins = wh->num_coins;
break;
}
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
@ -217,7 +214,7 @@ handle_reserve_batch_withdraw_finished (
};
if (GNUNET_OK !=
GNUNET_JSON_parse (hr->reply,
GNUNET_JSON_parse (bw2r->hr.reply,
spec,
NULL, NULL))
{
@ -289,7 +286,7 @@ withdraw_cs_stage_two_callback (
switch (csrr->hr.http_status)
{
case MHD_HTTP_OK:
cd->alg_values = csrr->details.success.alg_values;
cd->alg_values = csrr->details.ok.alg_values;
TALER_planchet_setup_coin_priv (&cd->ps,
&cd->alg_values,
&cd->priv);

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA
Copyright (C) 2014-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
@ -108,9 +108,9 @@ reserve_batch_withdraw_ok (struct TALER_EXCHANGE_BatchWithdraw2Handle *wh,
"ev_sigs");
const json_t *j;
unsigned int index;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = json,
.http_status = MHD_HTTP_OK
struct TALER_EXCHANGE_BatchWithdraw2Response bwr = {
.hr.reply = json,
.hr.http_status = MHD_HTTP_OK
};
if ( (NULL == ja) ||
@ -141,10 +141,10 @@ reserve_batch_withdraw_ok (struct TALER_EXCHANGE_BatchWithdraw2Handle *wh,
}
/* signature is valid, return it to the application */
bwr.details.ok.blind_sigs = blind_sigs;
bwr.details.ok.blind_sigs_length = wh->num_coins;
wh->cb (wh->cb_cls,
&hr,
blind_sigs,
wh->num_coins);
&bwr);
/* make sure callback isn't called again after return */
wh->cb = NULL;
for (unsigned int i = 0; i<wh->num_coins; i++)
@ -264,16 +264,16 @@ handle_reserve_batch_withdraw_finished (void *cls,
{
struct TALER_EXCHANGE_BatchWithdraw2Handle *wh = cls;
const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
struct TALER_EXCHANGE_BatchWithdraw2Response bwr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
wh->job = NULL;
switch (response_code)
{
case 0:
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
bwr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
@ -281,8 +281,8 @@ handle_reserve_batch_withdraw_finished (void *cls,
j))
{
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
bwr.hr.http_status = 0;
bwr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
GNUNET_assert (NULL == wh->cb);
@ -304,8 +304,8 @@ handle_reserve_batch_withdraw_finished (void *cls,
NULL, NULL))
{
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
bwr.hr.http_status = 0;
bwr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
}
@ -313,24 +313,24 @@ handle_reserve_batch_withdraw_finished (void *cls,
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
bwr.hr.ec = TALER_JSON_get_error_code (j);
bwr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_FORBIDDEN:
GNUNET_break_op (0);
/* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
bwr.hr.ec = TALER_JSON_get_error_code (j);
bwr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, the exchange basically just says
that it doesn't know this reserve. Can happen if we
query before the wire transfer went through.
We should simply pass the JSON reply to the application. */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
bwr.hr.ec = TALER_JSON_get_error_code (j);
bwr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_CONFLICT:
/* The exchange says that the reserve has insufficient funds;
@ -340,13 +340,13 @@ handle_reserve_batch_withdraw_finished (void *cls,
j))
{
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
bwr.hr.http_status = 0;
bwr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
}
else
{
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
bwr.hr.ec = TALER_JSON_get_error_code (j);
bwr.hr.hint = TALER_JSON_get_error_hint (j);
}
break;
case MHD_HTTP_GONE:
@ -354,32 +354,30 @@ handle_reserve_batch_withdraw_finished (void *cls,
/* Note: one might want to check /keys for revocation
signature here, alas tricky in case our /keys
is outdated => left to clients */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
bwr.hr.ec = TALER_JSON_get_error_code (j);
bwr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
bwr.hr.ec = TALER_JSON_get_error_code (j);
bwr.hr.hint = TALER_JSON_get_error_hint (j);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
bwr.hr.ec = TALER_JSON_get_error_code (j);
bwr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange batch withdraw\n",
(unsigned int) response_code,
(int) hr.ec);
(int) bwr.hr.ec);
break;
}
if (NULL != wh->cb)
{
wh->cb (wh->cb_cls,
&hr,
NULL,
0);
&bwr);
wh->cb = NULL;
}
TALER_EXCHANGE_batch_withdraw2_cancel (wh);

View File

@ -109,7 +109,7 @@ handle_contract_get_finished (void *cls,
struct TALER_PurseContractSignatureP econtract_sig;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("purse_pub",
&dr.details.success.purse_pub),
&dr.details.ok.purse_pub),
GNUNET_JSON_spec_fixed_auto ("econtract_sig",
&econtract_sig),
GNUNET_JSON_spec_varsize ("econtract",
@ -133,7 +133,7 @@ handle_contract_get_finished (void *cls,
econtract,
econtract_size,
&cgh->cpub,
&dr.details.success.purse_pub,
&dr.details.ok.purse_pub,
&econtract_sig))
{
GNUNET_break (0);
@ -142,8 +142,8 @@ handle_contract_get_finished (void *cls,
GNUNET_JSON_parse_free (spec);
break;
}
dr.details.success.econtract = econtract;
dr.details.success.econtract_size = econtract_size;
dr.details.ok.econtract = econtract;
dr.details.ok.econtract_size = econtract_size;
cgh->cb (cgh->cb_cls,
&dr);
GNUNET_JSON_parse_free (spec);

View File

@ -94,8 +94,8 @@ csr_ok (struct TALER_EXCHANGE_CsRMeltHandle *csrh,
struct TALER_ExchangeWithdrawValues alg_values[GNUNET_NZL (alen)];
struct TALER_EXCHANGE_CsRMeltResponse csrr = {
.hr = *hr,
.details.success.alg_values_len = alen,
.details.success.alg_values = alg_values
.details.ok.alg_values_len = alen,
.details.ok.alg_values = alg_values
};
for (unsigned int i = 0; i<alen; i++)

View File

@ -96,7 +96,7 @@ csr_ok (struct TALER_EXCHANGE_CsRWithdrawHandle *csrh,
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_exchange_withdraw_values (
"ewv",
&csrr.details.success.alg_values),
&csrr.details.ok.alg_values),
GNUNET_JSON_spec_end ()
};

View File

@ -236,7 +236,7 @@ handle_deposit_finished (void *cls,
&dh->exchange_pub),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("transaction_base_url",
&dr.details.success.transaction_base_url),
&dr.details.ok.transaction_base_url),
NULL),
GNUNET_JSON_spec_timestamp ("exchange_timestamp",
&dh->exchange_timestamp),
@ -297,9 +297,9 @@ handle_deposit_finished (void *cls,
&auditor_cb,
dh);
}
dr.details.success.exchange_sig = &dh->exchange_sig;
dr.details.success.exchange_pub = &dh->exchange_pub;
dr.details.success.deposit_timestamp = dh->exchange_timestamp;
dr.details.ok.exchange_sig = &dh->exchange_sig;
dr.details.ok.exchange_pub = &dh->exchange_pub;
dr.details.ok.deposit_timestamp = dh->exchange_timestamp;
break;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy

View File

@ -118,15 +118,15 @@ handle_deposit_wtid_finished (void *cls,
{
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("wtid",
&dr.details.success.wtid),
&dr.details.ok.wtid),
GNUNET_JSON_spec_timestamp ("execution_time",
&dr.details.success.execution_time),
&dr.details.ok.execution_time),
TALER_JSON_spec_amount_any ("coin_contribution",
&dr.details.success.coin_contribution),
&dr.details.ok.coin_contribution),
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
&dr.details.success.exchange_sig),
&dr.details.ok.exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
&dr.details.success.exchange_pub),
&dr.details.ok.exchange_pub),
GNUNET_JSON_spec_end ()
};
const struct TALER_EXCHANGE_Keys *key_state;
@ -145,7 +145,7 @@ handle_deposit_wtid_finished (void *cls,
}
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
&dr.details.success.exchange_pub))
&dr.details.ok.exchange_pub))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
@ -156,12 +156,12 @@ handle_deposit_wtid_finished (void *cls,
TALER_exchange_online_confirm_wire_verify (
&dwh->h_wire,
&dwh->h_contract_terms,
&dr.details.success.wtid,
&dr.details.ok.wtid,
&dwh->coin_pub,
dr.details.success.execution_time,
&dr.details.success.coin_contribution,
&dr.details.success.exchange_pub,
&dr.details.success.exchange_sig))
dr.details.ok.execution_time,
&dr.details.ok.coin_contribution,
&dr.details.ok.exchange_pub,
&dr.details.ok.exchange_sig))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA
Copyright (C) 2014-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
@ -40,7 +40,7 @@
* Which version of the Taler protocol is implemented
* by this library? Used to determine compatibility.
*/
#define EXCHANGE_PROTOCOL_CURRENT 14
#define EXCHANGE_PROTOCOL_CURRENT 15
/**
* How many versions are we backwards compatible with?
@ -1305,15 +1305,18 @@ keys_completed_cb (void *cls,
{
struct KeysRequest *kr = cls;
struct TALER_EXCHANGE_Handle *exchange = kr->exchange;
struct TALER_EXCHANGE_Keys kd;
struct TALER_EXCHANGE_Keys kd_old;
enum TALER_EXCHANGE_VersionCompatibility vc;
const json_t *j = resp_obj;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
struct TALER_EXCHANGE_Keys kd;
struct TALER_EXCHANGE_KeysResponse kresp = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code,
.details.ok.compat = TALER_EXCHANGE_VC_PROTOCOL_ERROR,
};
memset (&kd,
0,
sizeof (kd));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received keys from URL `%s' with status %ld and expiration %s.\n",
kr->url,
@ -1330,10 +1333,6 @@ keys_completed_cb (void *cls,
GNUNET_TIME_relative_to_absolute (DEFAULT_EXPIRATION));
}
kd_old = exchange->key_data;
memset (&kd,
0,
sizeof (struct TALER_EXCHANGE_Keys));
vc = TALER_EXCHANGE_VC_PROTOCOL_ERROR;
switch (response_code)
{
case 0:
@ -1358,8 +1357,10 @@ keys_completed_cb (void *cls,
}
/* We keep the denomination keys and auditor signatures from the
previous iteration (/keys cherry picking) */
kd.num_denom_keys = kd_old.num_denom_keys;
kd.last_denom_issue_date = kd_old.last_denom_issue_date;
kd.num_denom_keys
= kd_old.num_denom_keys;
kd.last_denom_issue_date
= kd_old.last_denom_issue_date;
GNUNET_array_grow (kd.denom_keys,
kd.denom_keys_size,
kd.num_denom_keys);
@ -1401,11 +1402,11 @@ keys_completed_cb (void *cls,
decode_keys_json (j,
true,
&kd,
&vc))
&kresp.details.ok.compat))
{
TALER_LOG_ERROR ("Could not decode /keys response\n");
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
kresp.hr.http_status = 0;
kresp.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
for (unsigned int i = 0; i<kd.num_auditors; i++)
{
struct TALER_EXCHANGE_AuditorInformation *anew = &kd.auditors[i];
@ -1436,13 +1437,13 @@ keys_completed_cb (void *cls,
case MHD_HTTP_NOT_FOUND:
if (NULL == j)
{
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
hr.hint = TALER_ErrorCode_get_hint (hr.ec);
kresp.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
kresp.hr.hint = TALER_ErrorCode_get_hint (kresp.hr.ec);
}
else
{
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
kresp.hr.ec = TALER_JSON_get_error_code (j);
kresp.hr.hint = TALER_JSON_get_error_hint (j);
}
break;
default:
@ -1450,18 +1451,18 @@ keys_completed_cb (void *cls,
exchange->keys_error_count++;
if (NULL == j)
{
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
hr.hint = TALER_ErrorCode_get_hint (hr.ec);
kresp.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
kresp.hr.hint = TALER_ErrorCode_get_hint (kresp.hr.ec);
}
else
{
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
kresp.hr.ec = TALER_JSON_get_error_code (j);
kresp.hr.hint = TALER_JSON_get_error_hint (j);
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n",
(unsigned int) response_code,
(int) hr.ec);
(int) kresp.hr.ec);
break;
}
exchange->key_data = kd;
@ -1491,9 +1492,7 @@ keys_completed_cb (void *cls,
free_key_data (&kd_old);
/* notify application that we failed */
exchange->cert_cb (exchange->cert_cb_cls,
&hr,
NULL,
vc);
&kresp);
return;
}
@ -1504,11 +1503,11 @@ keys_completed_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Successfully downloaded exchange's keys\n");
update_auditors (exchange);
kresp.details.ok.keys = &exchange->key_data;
/* notify application about the key information */
exchange->cert_cb (exchange->cert_cb_cls,
&hr,
&exchange->key_data,
vc);
&kresp);
free_key_data (&kd_old);
}
@ -1702,7 +1701,6 @@ static void
deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
const json_t *data)
{
enum TALER_EXCHANGE_VersionCompatibility vc;
json_t *keys;
const char *url;
uint32_t version;
@ -1719,10 +1717,11 @@ deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
GNUNET_JSON_spec_end ()
};
struct TALER_EXCHANGE_Keys key_data;
struct TALER_EXCHANGE_HttpResponse hr = {
.ec = TALER_EC_NONE,
.http_status = MHD_HTTP_OK,
.reply = data
struct TALER_EXCHANGE_KeysResponse kresp = {
.hr.ec = TALER_EC_NONE,
.hr.http_status = MHD_HTTP_OK,
.hr.reply = data,
.details.ok.keys = &exchange->key_data
};
if (NULL == data)
@ -1754,7 +1753,7 @@ deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
decode_keys_json (keys,
false,
&key_data,
&vc))
&kresp.details.ok.compat))
{
GNUNET_break (0);
GNUNET_JSON_parse_free (spec);
@ -1771,9 +1770,7 @@ deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
update_auditors (exchange);
/* notify application about the key information */
exchange->cert_cb (exchange->cert_cb_cls,
&hr,
&exchange->key_data,
vc);
&kresp);
GNUNET_JSON_parse_free (spec);
}
@ -2056,17 +2053,18 @@ request_keys (void *cls)
url);
if (NULL == kr->url)
{
struct TALER_EXCHANGE_HttpResponse hr = {
.ec = TALER_EC_GENERIC_CONFIGURATION_INVALID
struct TALER_EXCHANGE_KeysResponse kresp = {
.hr.ec = TALER_EC_GENERIC_CONFIGURATION_INVALID,
/* Next line is technically unnecessary, as the
http status we set is 0 */
.details.ok.compat = TALER_EXCHANGE_VC_PROTOCOL_ERROR
};
GNUNET_free (kr);
exchange->keys_error_count++;
exchange->state = MHS_FAILED;
exchange->cert_cb (exchange->cert_cb_cls,
&hr,
NULL,
TALER_EXCHANGE_VC_PROTOCOL_ERROR);
&kresp);
return;
}

View File

@ -100,11 +100,11 @@ handle_kyc_check_finished (void *cls,
uint32_t status;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
&ks.details.success.exchange_sig),
&ks.details.ok.exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
&ks.details.success.exchange_pub),
&ks.details.ok.exchange_pub),
GNUNET_JSON_spec_timestamp ("now",
&ks.details.success.timestamp),
&ks.details.ok.timestamp),
GNUNET_JSON_spec_json ("kyc_details",
&kyc_details),
GNUNET_JSON_spec_uint32 ("aml_status",
@ -123,13 +123,13 @@ handle_kyc_check_finished (void *cls,
ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
}
ks.details.success.kyc_details = kyc_details;
ks.details.success.aml_status
ks.details.ok.kyc_details = kyc_details;
ks.details.ok.aml_status
= (enum TALER_AmlDecisionState) status;
key_state = TALER_EXCHANGE_get_keys (kch->exchange);
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
&ks.details.success.exchange_pub))
&ks.details.ok.exchange_pub))
{
GNUNET_break_op (0);
ks.http_status = 0;
@ -141,10 +141,10 @@ handle_kyc_check_finished (void *cls,
if (GNUNET_OK !=
TALER_exchange_online_account_setup_success_verify (
&kch->h_payto,
ks.details.success.kyc_details,
ks.details.success.timestamp,
&ks.details.success.exchange_pub,
&ks.details.success.exchange_sig))
ks.details.ok.kyc_details,
ks.details.ok.timestamp,
&ks.details.ok.exchange_pub,
&ks.details.ok.exchange_sig))
{
GNUNET_break_op (0);
ks.http_status = 0;

View File

@ -365,8 +365,8 @@ parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
if (off_coin == num_coins)
{
lr.details.success.num_coins = num_coins;
lr.details.success.coins = lcis;
lr.details.ok.num_coins = num_coins;
lr.details.ok.coins = lcis;
lh->link_cb (lh->link_cb_cls,
&lr);
lh->link_cb = NULL;

View File

@ -190,17 +190,17 @@ parse_decision_ok (struct TALER_EXCHANGE_LookupAmlDecision *lh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
lr.details.success.aml_history_length = json_array_size (aml_history);
lr.details.success.kyc_attributes_length = json_array_size (kyc_attributes);
lr.details.ok.aml_history_length = json_array_size (aml_history);
lr.details.ok.kyc_attributes_length = json_array_size (kyc_attributes);
{
struct TALER_EXCHANGE_AmlDecisionDetail aml_history_ar[
GNUNET_NZL (lr.details.success.aml_history_length)];
GNUNET_NZL (lr.details.ok.aml_history_length)];
struct TALER_EXCHANGE_KycHistoryDetail kyc_attributes_ar[
lr.details.success.kyc_attributes_length];
lr.details.ok.kyc_attributes_length];
enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR;
lr.details.success.aml_history = aml_history_ar;
lr.details.success.kyc_attributes = kyc_attributes_ar;
lr.details.ok.aml_history = aml_history_ar;
lr.details.ok.kyc_attributes = kyc_attributes_ar;
ret = parse_aml_history (aml_history,
aml_history_ar);
if (GNUNET_OK == ret)

View File

@ -139,13 +139,13 @@ parse_decisions_ok (struct TALER_EXCHANGE_LookupAmlDecisions *lh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
lr.details.success.decisions_length = json_array_size (records);
lr.details.ok.decisions_length = json_array_size (records);
{
struct TALER_EXCHANGE_AmlDecisionSummary decisions[
GNUNET_NZL (lr.details.success.decisions_length)];
GNUNET_NZL (lr.details.ok.decisions_length)];
enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR;
lr.details.success.decisions = decisions;
lr.details.ok.decisions = decisions;
ret = parse_aml_decisions (records,
decisions);
if (GNUNET_OK == ret)

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2020-2022 Taler Systems SA
Copyright (C) 2020-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
@ -79,9 +79,9 @@ handle_drain_profits_finished (void *cls,
{
struct TALER_EXCHANGE_ManagementDrainProfitsHandle *dp = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
struct TALER_EXCHANGE_ManagementDrainResponse dr = {
.hr.http_status = (unsigned int) response_code,
.hr.reply = json
};
dp->job = NULL;
@ -90,32 +90,32 @@ handle_drain_profits_finished (void *cls,
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
dr.hr.ec = TALER_JSON_get_error_code (json);
dr.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_CONFLICT:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
dr.hr.ec = TALER_JSON_get_error_code (json);
dr.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_PRECONDITION_FAILED:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
dr.hr.ec = TALER_JSON_get_error_code (json);
dr.hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
dr.hr.ec = TALER_JSON_get_error_code (json);
dr.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange management drain profits\n",
(unsigned int) response_code,
(int) hr.ec);
(int) dr.hr.ec);
break;
}
if (NULL != dp->cb)
{
dp->cb (dp->cb_cls,
&hr);
&dr);
dp->cb = NULL;
}
TALER_EXCHANGE_management_drain_profits_cancel (dp);

View File

@ -75,11 +75,16 @@ struct TALER_EXCHANGE_ManagementGetKeysHandle
* @param response the response
* @return #GNUNET_OK if the response was well-formed
*/
static int
static enum GNUNET_GenericReturnValue
handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
const json_t *response)
{
struct TALER_EXCHANGE_FutureKeys fk;
struct TALER_EXCHANGE_ManagementGetKeysResponse gkr = {
.hr.http_status = MHD_HTTP_OK,
.hr.reply = response,
};
struct TALER_EXCHANGE_FutureKeys *fk
= &gkr.details.ok.keys;
json_t *sk;
json_t *dk;
bool ok;
@ -89,13 +94,13 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
GNUNET_JSON_spec_json ("future_signkeys",
&sk),
GNUNET_JSON_spec_fixed_auto ("master_pub",
&fk.master_pub),
&fk->master_pub),
GNUNET_JSON_spec_fixed_auto ("denom_secmod_public_key",
&fk.denom_secmod_public_key),
&fk->denom_secmod_public_key),
GNUNET_JSON_spec_fixed_auto ("denom_secmod_cs_public_key",
&fk.denom_secmod_cs_public_key),
&fk->denom_secmod_cs_public_key),
GNUNET_JSON_spec_fixed_auto ("signkey_secmod_public_key",
&fk.signkey_secmod_public_key),
&fk->signkey_secmod_public_key),
GNUNET_JSON_spec_end ()
};
@ -107,21 +112,21 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
fk.num_sign_keys = json_array_size (sk);
fk.num_denom_keys = json_array_size (dk);
fk.sign_keys = GNUNET_new_array (
fk.num_sign_keys,
fk->num_sign_keys = json_array_size (sk);
fk->num_denom_keys = json_array_size (dk);
fk->sign_keys = GNUNET_new_array (
fk->num_sign_keys,
struct TALER_EXCHANGE_FutureSigningPublicKey);
fk.denom_keys = GNUNET_new_array (
fk.num_denom_keys,
fk->denom_keys = GNUNET_new_array (
fk->num_denom_keys,
struct TALER_EXCHANGE_FutureDenomPublicKey);
ok = true;
for (unsigned int i = 0; i<fk.num_sign_keys; i++)
for (unsigned int i = 0; i<fk->num_sign_keys; i++)
{
json_t *j = json_array_get (sk,
i);
struct TALER_EXCHANGE_FutureSigningPublicKey *sign_key
= &fk.sign_keys[i];
= &fk->sign_keys[i];
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("key",
&sign_key->key),
@ -155,7 +160,7 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
&sign_key->key,
sign_key->valid_from,
duration,
&fk.signkey_secmod_public_key,
&fk->signkey_secmod_public_key,
&sign_key->signkey_secmod_sig))
{
GNUNET_break_op (0);
@ -164,12 +169,12 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
}
}
}
for (unsigned int i = 0; i<fk.num_denom_keys; i++)
for (unsigned int i = 0; i<fk->num_denom_keys; i++)
{
json_t *j = json_array_get (dk,
i);
struct TALER_EXCHANGE_FutureDenomPublicKey *denom_key
= &fk.denom_keys[i];
= &fk->denom_keys[i];
const char *section_name;
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount_any ("value",
@ -236,7 +241,7 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
section_name,
denom_key->valid_from,
duration,
&fk.denom_secmod_public_key,
&fk->denom_secmod_public_key,
&denom_key->denom_secmod_sig))
{
GNUNET_break_op (0);
@ -256,7 +261,7 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
section_name,
denom_key->valid_from,
duration,
&fk.denom_secmod_cs_public_key,
&fk->denom_secmod_cs_public_key,
&denom_key->denom_secmod_sig))
{
GNUNET_break_op (0);
@ -277,19 +282,13 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
}
if (ok)
{
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = MHD_HTTP_OK,
.reply = response
};
gh->cb (gh->cb_cls,
&hr,
&fk);
&gkr);
}
for (unsigned int i = 0; i<fk.num_denom_keys; i++)
TALER_denom_pub_free (&fk.denom_keys[i].key);
GNUNET_free (fk.sign_keys);
GNUNET_free (fk.denom_keys);
for (unsigned int i = 0; i<fk->num_denom_keys; i++)
TALER_denom_pub_free (&fk->denom_keys[i].key);
GNUNET_free (fk->sign_keys);
GNUNET_free (fk->denom_keys);
GNUNET_JSON_parse_free (spec);
return (ok) ? GNUNET_OK : GNUNET_SYSERR;
}
@ -310,9 +309,9 @@ handle_get_keys_finished (void *cls,
{
struct TALER_EXCHANGE_ManagementGetKeysHandle *gh = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
struct TALER_EXCHANGE_ManagementGetKeysResponse gkr = {
.hr.http_status = (unsigned int) response_code,
.hr.reply = json
};
gh->job = NULL;
@ -334,25 +333,24 @@ handle_get_keys_finished (void *cls,
/* unexpected response code */
if (NULL != json)
{
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
gkr.hr.ec = TALER_JSON_get_error_code (json);
gkr.hr.hint = TALER_JSON_get_error_hint (json);
}
else
{
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
hr.hint = TALER_ErrorCode_get_hint (hr.ec);
gkr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
gkr.hr.hint = TALER_ErrorCode_get_hint (gkr.hr.ec);
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange management get keys\n",
(unsigned int) response_code,
(int) hr.ec);
(int) gkr.hr.ec);
break;
}
if (NULL != gh->cb)
{
gh->cb (gh->cb_cls,
&hr,
NULL);
&gkr);
gh->cb = NULL;
}
TALER_EXCHANGE_get_management_keys_cancel (gh);

View File

@ -83,9 +83,9 @@ handle_post_extensions_finished (void *cls,
{
struct TALER_EXCHANGE_ManagementPostExtensionsHandle *ph = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
struct TALER_EXCHANGE_ManagementPostExtensionsResponse per = {
.hr.http_status = (unsigned int) response_code,
.hr.reply = json
};
ph->job = NULL;
@ -94,28 +94,28 @@ handle_post_extensions_finished (void *cls,
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
per.hr.ec = TALER_JSON_get_error_code (json);
per.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_NOT_FOUND:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
per.hr.ec = TALER_JSON_get_error_code (json);
per.hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
per.hr.ec = TALER_JSON_get_error_code (json);
per.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange management post extensions\n",
(unsigned int) response_code,
(int) hr.ec);
(int) per.hr.ec);
break;
}
if (NULL != ph->cb)
{
ph->cb (ph->cb_cls,
&hr);
&per);
ph->cb = NULL;
}
TALER_EXCHANGE_management_post_extensions_cancel (ph);

View File

@ -82,9 +82,9 @@ handle_post_keys_finished (void *cls,
{
struct TALER_EXCHANGE_ManagementPostKeysHandle *ph = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
struct TALER_EXCHANGE_ManagementPostKeysResponse pkr = {
.hr.http_status = (unsigned int) response_code,
.hr.reply = json
};
ph->job = NULL;
@ -93,32 +93,32 @@ handle_post_keys_finished (void *cls,
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
pkr.hr.ec = TALER_JSON_get_error_code (json);
pkr.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_NOT_FOUND:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
pkr.hr.ec = TALER_JSON_get_error_code (json);
pkr.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_REQUEST_ENTITY_TOO_LARGE:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
pkr.hr.ec = TALER_JSON_get_error_code (json);
pkr.hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
pkr.hr.ec = TALER_JSON_get_error_code (json);
pkr.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange management post keys\n",
(unsigned int) response_code,
(int) hr.ec);
(int) pkr.hr.ec);
break;
}
if (NULL != ph->cb)
{
ph->cb (ph->cb_cls,
&hr);
&pkr);
ph->cb = NULL;
}
TALER_EXCHANGE_post_management_keys_cancel (ph);

View File

@ -82,9 +82,9 @@ handle_revoke_denomination_finished (void *cls,
{
struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle *rh = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
struct TALER_EXCHANGE_ManagementRevokeDenominationResponse rdr = {
.hr.http_status = (unsigned int) response_code,
.hr.reply = json
};
rh->job = NULL;
@ -92,30 +92,30 @@ handle_revoke_denomination_finished (void *cls,
{
case 0:
/* no reply */
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
hr.hint = "server offline?";
rdr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
rdr.hr.hint = "server offline?";
break;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
rdr.hr.ec = TALER_JSON_get_error_code (json);
rdr.hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
rdr.hr.ec = TALER_JSON_get_error_code (json);
rdr.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange management revoke denomination\n",
(unsigned int) response_code,
(int) hr.ec);
(int) rdr.hr.ec);
break;
}
if (NULL != rh->cb)
{
rh->cb (rh->cb_cls,
&hr);
&rdr);
rh->cb = NULL;
}
TALER_EXCHANGE_management_revoke_denomination_key_cancel (rh);

View File

@ -79,9 +79,9 @@ handle_revoke_signing_finished (void *cls,
{
struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle *rh = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
struct TALER_EXCHANGE_ManagementRevokeSigningKeyResponse rsr = {
.hr.http_status = (unsigned int) response_code,
.hr.reply = json
};
rh->job = NULL;
@ -89,30 +89,30 @@ handle_revoke_signing_finished (void *cls,
{
case 0:
/* no reply */
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
hr.hint = "server offline?";
rsr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
rsr.hr.hint = "server offline?";
break;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
rsr.hr.ec = TALER_JSON_get_error_code (json);
rsr.hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
rsr.hr.ec = TALER_JSON_get_error_code (json);
rsr.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange management revoke signkey\n",
(unsigned int) response_code,
(int) hr.ec);
(int) rsr.hr.ec);
break;
}
if (NULL != rh->cb)
{
rh->cb (rh->cb_cls,
&hr);
&rsr);
rh->cb = NULL;
}
TALER_EXCHANGE_management_revoke_signing_key_cancel (rh);

View File

@ -79,9 +79,9 @@ handle_update_aml_officer_finished (void *cls,
{
struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *wh = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
struct TALER_EXCHANGE_ManagementUpdateAmlOfficerResponse uar = {
.hr.http_status = (unsigned int) response_code,
.hr.reply = json
};
wh->job = NULL;
@ -89,34 +89,34 @@ handle_update_aml_officer_finished (void *cls,
{
case 0:
/* no reply */
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
hr.hint = "server offline?";
uar.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
uar.hr.hint = "server offline?";
break;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
uar.hr.ec = TALER_JSON_get_error_code (json);
uar.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_CONFLICT:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
uar.hr.ec = TALER_JSON_get_error_code (json);
uar.hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
uar.hr.ec = TALER_JSON_get_error_code (json);
uar.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange management update AML officer\n",
(unsigned int) response_code,
(int) hr.ec);
(int) uar.hr.ec);
break;
}
if (NULL != wh->cb)
{
wh->cb (wh->cb_cls,
&hr);
&uar);
wh->cb = NULL;
}
TALER_EXCHANGE_management_update_aml_officer_cancel (wh);

View File

@ -79,9 +79,9 @@ handle_auditor_disable_finished (void *cls,
{
struct TALER_EXCHANGE_ManagementWireDisableHandle *wh = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
struct TALER_EXCHANGE_ManagementWireDisableResponse wdr = {
.hr.http_status = (unsigned int) response_code,
.hr.reply = json
};
wh->job = NULL;
@ -89,38 +89,38 @@ handle_auditor_disable_finished (void *cls,
{
case 0:
/* no reply */
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
hr.hint = "server offline?";
wdr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
wdr.hr.hint = "server offline?";
break;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
wdr.hr.ec = TALER_JSON_get_error_code (json);
wdr.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_NOT_FOUND:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
wdr.hr.ec = TALER_JSON_get_error_code (json);
wdr.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_CONFLICT:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
wdr.hr.ec = TALER_JSON_get_error_code (json);
wdr.hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
wdr.hr.ec = TALER_JSON_get_error_code (json);
wdr.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d exchange management disable wire\n",
(unsigned int) response_code,
(int) hr.ec);
(int) wdr.hr.ec);
break;
}
if (NULL != wh->cb)
{
wh->cb (wh->cb_cls,
&hr);
&wdr);
wh->cb = NULL;
}
TALER_EXCHANGE_management_disable_wire_cancel (wh);

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2015-2021 Taler Systems SA
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
@ -79,9 +79,9 @@ handle_auditor_enable_finished (void *cls,
{
struct TALER_EXCHANGE_ManagementWireEnableHandle *wh = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
struct TALER_EXCHANGE_ManagementWireEnableResponse wer = {
.hr.http_status = (unsigned int) response_code,
.hr.reply = json
};
wh->job = NULL;
@ -89,34 +89,34 @@ handle_auditor_enable_finished (void *cls,
{
case 0:
/* no reply */
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
hr.hint = "server offline?";
wer.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
wer.hr.hint = "server offline?";
break;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
wer.hr.ec = TALER_JSON_get_error_code (json);
wer.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_CONFLICT:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
wer.hr.ec = TALER_JSON_get_error_code (json);
wer.hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
wer.hr.ec = TALER_JSON_get_error_code (json);
wer.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange management enable wire\n",
(unsigned int) response_code,
(int) hr.ec);
(int) wer.hr.ec);
break;
}
if (NULL != wh->cb)
{
wh->cb (wh->cb_cls,
&hr);
&wer);
wh->cb = NULL;
}
TALER_EXCHANGE_management_enable_wire_cancel (wh);
@ -128,6 +128,9 @@ TALER_EXCHANGE_management_enable_wire (
struct GNUNET_CURL_Context *ctx,
const char *url,
const char *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,
@ -167,6 +170,13 @@ TALER_EXCHANGE_management_enable_wire (
body = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("payto_uri",
payto_uri),
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_allow_null (
GNUNET_JSON_pack_string ("conversion_url",
conversion_url)),
GNUNET_JSON_pack_data_auto ("master_sig_add",
master_sig1),
GNUNET_JSON_pack_data_auto ("master_sig_wire",

View File

@ -221,16 +221,16 @@ handle_melt_finished (void *cls,
if (GNUNET_OK !=
verify_melt_signature_ok (mh,
j,
&mr.details.success.sign_key))
&mr.details.ok.sign_key))
{
GNUNET_break_op (0);
mr.hr.http_status = 0;
mr.hr.ec = TALER_EC_EXCHANGE_MELT_INVALID_SIGNATURE_BY_EXCHANGE;
break;
}
mr.details.success.noreveal_index = mh->noreveal_index;
mr.details.success.num_mbds = mh->rd->fresh_pks_len;
mr.details.success.mbds = mh->mbds;
mr.details.ok.noreveal_index = mh->noreveal_index;
mr.details.ok.num_mbds = mh->rd->fresh_pks_len;
mr.details.ok.mbds = mh->mbds;
mh->melt_cb (mh->melt_cb_cls,
&mr);
mh->melt_cb = NULL;
@ -478,7 +478,7 @@ csr_cb (void *cls,
break;
case TALER_DENOMINATION_CS:
GNUNET_assert (TALER_DENOMINATION_CS == wv->cipher);
*wv = csrr->details.success.alg_values[nks_off];
*wv = csrr->details.ok.alg_values[nks_off];
nks_off++;
break;
}

View File

@ -164,17 +164,17 @@ handle_purse_deposit_finished (void *cls,
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
&exchange_pub),
GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
&dr.details.success.h_contract_terms),
&dr.details.ok.h_contract_terms),
GNUNET_JSON_spec_timestamp ("exchange_timestamp",
&etime),
GNUNET_JSON_spec_timestamp ("purse_expiration",
&dr.details.success.purse_expiration),
&dr.details.ok.purse_expiration),
TALER_JSON_spec_amount ("total_deposited",
keys->currency,
&dr.details.success.total_deposited),
&dr.details.ok.total_deposited),
TALER_JSON_spec_amount ("purse_value_after_fees",
keys->currency,
&dr.details.success.purse_value_after_fees),
&dr.details.ok.purse_value_after_fees),
GNUNET_JSON_spec_end ()
};
@ -200,11 +200,11 @@ handle_purse_deposit_finished (void *cls,
if (GNUNET_OK !=
TALER_exchange_online_purse_created_verify (
etime,
dr.details.success.purse_expiration,
&dr.details.success.purse_value_after_fees,
&dr.details.success.total_deposited,
dr.details.ok.purse_expiration,
&dr.details.ok.purse_value_after_fees,
&dr.details.ok.total_deposited,
&pch->purse_pub,
&dr.details.success.h_contract_terms,
&dr.details.ok.h_contract_terms,
&exchange_pub,
&exchange_sig))
{

View File

@ -152,11 +152,11 @@ handle_purse_merge_finished (void *cls,
struct TALER_Amount total_deposited;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
&dr.details.success.exchange_sig),
&dr.details.ok.exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
&dr.details.success.exchange_pub),
&dr.details.ok.exchange_pub),
GNUNET_JSON_spec_timestamp ("exchange_timestamp",
&dr.details.success.etime),
&dr.details.ok.etime),
TALER_JSON_spec_amount ("merge_amount",
pch->purse_value_after_fees.currency,
&total_deposited),
@ -176,7 +176,7 @@ handle_purse_merge_finished (void *cls,
key_state = TALER_EXCHANGE_get_keys (pch->exchange);
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
&dr.details.success.exchange_pub))
&dr.details.ok.exchange_pub))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
@ -185,15 +185,15 @@ handle_purse_merge_finished (void *cls,
}
if (GNUNET_OK !=
TALER_exchange_online_purse_merged_verify (
dr.details.success.etime,
dr.details.ok.etime,
pch->purse_expiration,
&pch->purse_value_after_fees,
&pch->purse_pub,
&pch->h_contract_terms,
&pch->reserve_pub,
pch->provider_url,
&dr.details.success.exchange_pub,
&dr.details.success.exchange_sig))
&dr.details.ok.exchange_pub,
&dr.details.ok.exchange_sig))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;

View File

@ -101,16 +101,16 @@ handle_purse_get_finished (void *cls,
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_timestamp ("merge_timestamp",
&dr.details.success.merge_timestamp),
&dr.details.ok.merge_timestamp),
&no_merge),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_timestamp ("deposit_timestamp",
&dr.details.success.deposit_timestamp),
&dr.details.ok.deposit_timestamp),
&no_deposit),
TALER_JSON_spec_amount_any ("balance",
&dr.details.success.balance),
&dr.details.ok.balance),
GNUNET_JSON_spec_timestamp ("purse_expiration",
&dr.details.success.purse_expiration),
&dr.details.ok.purse_expiration),
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
&exchange_pub),
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
@ -142,9 +142,9 @@ handle_purse_get_finished (void *cls,
}
if (GNUNET_OK !=
TALER_exchange_online_purse_status_verify (
dr.details.success.merge_timestamp,
dr.details.success.deposit_timestamp,
&dr.details.success.balance,
dr.details.ok.merge_timestamp,
dr.details.ok.deposit_timestamp,
&dr.details.ok.balance,
&exchange_pub,
&exchange_sig))
{

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2017-2022 Taler Systems SA
Copyright (C) 2017-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
@ -100,16 +100,15 @@ static enum GNUNET_GenericReturnValue
process_recoup_response (const struct TALER_EXCHANGE_RecoupHandle *ph,
const json_t *json)
{
struct TALER_ReservePublicKeyP reserve_pub;
struct TALER_EXCHANGE_RecoupResponse rr = {
.hr.reply = json,
.hr.http_status = MHD_HTTP_OK
};
struct GNUNET_JSON_Specification spec_withdraw[] = {
GNUNET_JSON_spec_fixed_auto ("reserve_pub",
&reserve_pub),
&rr.details.ok.reserve_pub),
GNUNET_JSON_spec_end ()
};
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = json,
.http_status = MHD_HTTP_OK
};
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
@ -120,8 +119,7 @@ process_recoup_response (const struct TALER_EXCHANGE_RecoupHandle *ph,
return GNUNET_SYSERR;
}
ph->cb (ph->cb_cls,
&hr,
&reserve_pub);
&rr);
return GNUNET_OK;
}
@ -141,9 +139,9 @@ handle_recoup_finished (void *cls,
{
struct TALER_EXCHANGE_RecoupHandle *ph = cls;
const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
struct TALER_EXCHANGE_RecoupResponse rr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
const struct TALER_EXCHANGE_Keys *keys;
@ -152,7 +150,7 @@ handle_recoup_finished (void *cls,
switch (response_code)
{
case 0:
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
rr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
@ -160,8 +158,8 @@ handle_recoup_finished (void *cls,
j))
{
GNUNET_break_op (0);
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
hr.http_status = 0;
rr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
rr.hr.http_status = 0;
break;
}
TALER_EXCHANGE_recoup_cancel (ph);
@ -169,22 +167,22 @@ handle_recoup_finished (void *cls,
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_CONFLICT:
{
struct TALER_Amount min_key;
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
if (GNUNET_OK !=
TALER_EXCHANGE_get_min_denomination_ (keys,
&min_key))
{
GNUNET_break (0);
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
hr.http_status = 0;
rr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
rr.hr.http_status = 0;
break;
}
if (GNUNET_OK !=
@ -197,8 +195,8 @@ handle_recoup_finished (void *cls,
&min_key))
{
GNUNET_break (0);
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
hr.http_status = 0;
rr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
rr.hr.http_status = 0;
break;
}
break;
@ -207,41 +205,40 @@ handle_recoup_finished (void *cls,
/* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_GONE:
/* Kind of normal: the money was already sent to the merchant
(it was too late for the refund). */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
default:
/* unexpected response code */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange recoup\n",
(unsigned int) response_code,
(int) hr.ec);
(int) rr.hr.ec);
GNUNET_break (0);
break;
}
ph->cb (ph->cb_cls,
&hr,
NULL);
&rr);
TALER_EXCHANGE_recoup_cancel (ph);
}

View File

@ -101,16 +101,15 @@ process_recoup_response (
const struct TALER_EXCHANGE_RecoupRefreshHandle *ph,
const json_t *json)
{
struct TALER_CoinSpendPublicKeyP old_coin_pub;
struct TALER_EXCHANGE_RecoupRefreshResponse rrr = {
.hr.reply = json,
.hr.http_status = MHD_HTTP_OK
};
struct GNUNET_JSON_Specification spec_refresh[] = {
GNUNET_JSON_spec_fixed_auto ("old_coin_pub",
&old_coin_pub),
&rrr.details.ok.old_coin_pub),
GNUNET_JSON_spec_end ()
};
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = json,
.http_status = MHD_HTTP_OK
};
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
@ -121,8 +120,7 @@ process_recoup_response (
return GNUNET_SYSERR;
}
ph->cb (ph->cb_cls,
&hr,
&old_coin_pub);
&rrr);
return GNUNET_OK;
}
@ -142,9 +140,9 @@ handle_recoup_refresh_finished (void *cls,
{
struct TALER_EXCHANGE_RecoupRefreshHandle *ph = cls;
const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
struct TALER_EXCHANGE_RecoupRefreshResponse rrr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
const struct TALER_EXCHANGE_Keys *keys;
@ -153,7 +151,7 @@ handle_recoup_refresh_finished (void *cls,
switch (response_code)
{
case 0:
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
rrr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
@ -161,8 +159,8 @@ handle_recoup_refresh_finished (void *cls,
j))
{
GNUNET_break_op (0);
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
hr.http_status = 0;
rrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
rrr.hr.http_status = 0;
break;
}
TALER_EXCHANGE_recoup_refresh_cancel (ph);
@ -170,35 +168,35 @@ handle_recoup_refresh_finished (void *cls,
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rrr.hr.ec = TALER_JSON_get_error_code (j);
rrr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_FORBIDDEN:
/* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rrr.hr.ec = TALER_JSON_get_error_code (j);
rrr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rrr.hr.ec = TALER_JSON_get_error_code (j);
rrr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_CONFLICT:
{
struct TALER_Amount min_key;
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rrr.hr.ec = TALER_JSON_get_error_code (j);
rrr.hr.hint = TALER_JSON_get_error_hint (j);
if (GNUNET_OK !=
TALER_EXCHANGE_get_min_denomination_ (keys,
&min_key))
{
GNUNET_break (0);
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
hr.http_status = 0;
rrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
rrr.hr.http_status = 0;
break;
}
if (GNUNET_OK !=
@ -211,8 +209,8 @@ handle_recoup_refresh_finished (void *cls,
&min_key))
{
GNUNET_break (0);
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
hr.http_status = 0;
rrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
rrr.hr.http_status = 0;
break;
}
break;
@ -220,29 +218,28 @@ handle_recoup_refresh_finished (void *cls,
case MHD_HTTP_GONE:
/* Kind of normal: the money was already sent to the merchant
(it was too late for the refund). */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rrr.hr.ec = TALER_JSON_get_error_code (j);
rrr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rrr.hr.ec = TALER_JSON_get_error_code (j);
rrr.hr.hint = TALER_JSON_get_error_hint (j);
break;
default:
/* unexpected response code */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rrr.hr.ec = TALER_JSON_get_error_code (j);
rrr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange recoup\n",
(unsigned int) response_code,
(int) hr.ec);
(int) rrr.hr.ec);
GNUNET_break (0);
break;
}
ph->cb (ph->cb_cls,
&hr,
NULL);
&rrr);
TALER_EXCHANGE_recoup_refresh_cancel (ph);
}

View File

@ -266,8 +266,8 @@ handle_refresh_reveal_finished (void *cls,
else
{
GNUNET_assert (rrh->noreveal_index < TALER_CNC_KAPPA);
rr.details.success.num_coins = rrh->md.num_fresh_coins;
rr.details.success.coins = rcis;
rr.details.ok.num_coins = rrh->md.num_fresh_coins;
rr.details.ok.coins = rcis;
rrh->reveal_cb (rrh->reveal_cb_cls,
&rr);
rrh->reveal_cb = NULL;

View File

@ -585,37 +585,28 @@ handle_refund_finished (void *cls,
const void *response)
{
struct TALER_EXCHANGE_RefundHandle *rh = cls;
struct TALER_ExchangePublicKeyP exchange_pub;
struct TALER_ExchangeSignatureP exchange_sig;
struct TALER_ExchangePublicKeyP *ep = NULL;
struct TALER_ExchangeSignatureP *es = NULL;
const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
struct TALER_EXCHANGE_RefundResponse rr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
rh->job = NULL;
switch (response_code)
{
case 0:
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
rr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
verify_refund_signature_ok (rh,
j,
&exchange_pub,
&exchange_sig))
&rr.details.ok.exchange_pub,
&rr.details.ok.exchange_sig))
{
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_SIGNATURE_BY_EXCHANGE;
}
else
{
ep = &exchange_pub;
es = &exchange_sig;
rr.hr.http_status = 0;
rr.hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_SIGNATURE_BY_EXCHANGE;
}
break;
case MHD_HTTP_BAD_REQUEST:
@ -623,21 +614,21 @@ handle_refund_finished (void *cls,
(or API version conflict); also can happen if the currency
differs (which we should obviously never support).
Just pass JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_FORBIDDEN:
/* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_CONFLICT:
/* Requested total refunds exceed deposited amount */
@ -649,19 +640,19 @@ handle_refund_finished (void *cls,
json_dumpf (j,
stderr,
JSON_INDENT (2));
hr.http_status = 0;
hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE;
hr.hint = "conflict information provided by exchange is invalid";
rr.hr.http_status = 0;
rr.hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE;
rr.hr.hint = "conflict information provided by exchange is invalid";
break;
}
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_GONE:
/* Kind of normal: the money was already sent to the merchant
(it was too late for the refund). */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_PRECONDITION_FAILED:
if (GNUNET_OK !=
@ -669,37 +660,35 @@ handle_refund_finished (void *cls,
j))
{
GNUNET_break (0);
hr.http_status = 0;
hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE;
hr.hint = "failed precondition proof returned by exchange is invalid";
rr.hr.http_status = 0;
rr.hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE;
rr.hr.hint = "failed precondition proof returned by exchange is invalid";
break;
}
/* Two different refund requests were made about the same deposit, but
carrying identical refund transaction ids. */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange refund\n",
(unsigned int) response_code,
hr.ec);
rr.hr.ec);
break;
}
rh->cb (rh->cb_cls,
&hr,
ep,
es);
&rr);
TALER_EXCHANGE_refund_cancel (rh);
}

View File

@ -85,23 +85,32 @@ check_transfers_get_response_ok (
const json_t *json)
{
json_t *details_j;
struct TALER_EXCHANGE_TransferData td;
struct TALER_Amount total_expected;
struct TALER_MerchantPublicKeyP merchant_pub;
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount_any ("total", &td.total_amount),
TALER_JSON_spec_amount_any ("wire_fee", &td.wire_fee),
GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub),
GNUNET_JSON_spec_fixed_auto ("h_payto", &td.h_payto),
GNUNET_JSON_spec_timestamp ("execution_time", &td.execution_time),
GNUNET_JSON_spec_json ("deposits", &details_j),
GNUNET_JSON_spec_fixed_auto ("exchange_sig", &td.exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub", &td.exchange_pub),
GNUNET_JSON_spec_end ()
struct TALER_EXCHANGE_TransfersGetResponse tgr = {
.hr.reply = json,
.hr.http_status = MHD_HTTP_OK
};
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = json,
.http_status = MHD_HTTP_OK
struct TALER_EXCHANGE_TransferData *td
= &tgr.details.ok.td;
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount_any ("total",
&td->total_amount),
TALER_JSON_spec_amount_any ("wire_fee",
&td->wire_fee),
GNUNET_JSON_spec_fixed_auto ("merchant_pub",
&merchant_pub),
GNUNET_JSON_spec_fixed_auto ("h_payto",
&td->h_payto),
GNUNET_JSON_spec_timestamp ("execution_time",
&td->execution_time),
GNUNET_JSON_spec_json ("deposits",
&details_j),
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
&td->exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
&td->exchange_pub),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
@ -113,7 +122,7 @@ check_transfers_get_response_ok (
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
TALER_amount_set_zero (td.total_amount.currency,
TALER_amount_set_zero (td->total_amount.currency,
&total_expected))
{
GNUNET_break_op (0);
@ -123,22 +132,22 @@ check_transfers_get_response_ok (
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (
TALER_EXCHANGE_get_keys (wdh->exchange),
&td.exchange_pub))
&td->exchange_pub))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
td.details_length = json_array_size (details_j);
td->details_length = json_array_size (details_j);
{
struct GNUNET_HashContext *hash_context;
struct TALER_TrackTransferDetails *details;
details = GNUNET_new_array (td.details_length,
details = GNUNET_new_array (td->details_length,
struct TALER_TrackTransferDetails);
td.details = details;
td->details = details;
hash_context = GNUNET_CRYPTO_hash_context_start ();
for (unsigned int i = 0; i<td.details_length; i++)
for (unsigned int i = 0; i<td->details_length; i++)
{
struct TALER_TrackTransferDetails *detail = &details[i];
struct json_t *detail_j = json_array_get (details_j, i);
@ -180,7 +189,7 @@ check_transfers_get_response_ok (
TALER_exchange_online_wire_deposit_append (
hash_context,
&detail->h_contract_terms,
td.execution_time,
td->execution_time,
&detail->coin_pub,
&detail->coin_value,
&detail->coin_fee);
@ -193,13 +202,13 @@ check_transfers_get_response_ok (
&h_details);
if (GNUNET_OK !=
TALER_exchange_online_wire_deposit_verify (
&td.total_amount,
&td.wire_fee,
&td->total_amount,
&td->wire_fee,
&merchant_pub,
&td.h_payto,
&td->h_payto,
&h_details,
&td.exchange_pub,
&td.exchange_sig))
&td->exchange_pub,
&td->exchange_sig))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
@ -211,7 +220,7 @@ check_transfers_get_response_ok (
if (0 >
TALER_amount_subtract (&total_expected,
&total_expected,
&td.wire_fee))
&td->wire_fee))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
@ -220,7 +229,7 @@ check_transfers_get_response_ok (
}
if (0 !=
TALER_amount_cmp (&total_expected,
&td.total_amount))
&td->total_amount))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
@ -228,8 +237,7 @@ check_transfers_get_response_ok (
return GNUNET_SYSERR;
}
wdh->cb (wdh->cb_cls,
&hr,
&td);
&tgr);
GNUNET_free (details);
}
GNUNET_JSON_parse_free (spec);
@ -253,16 +261,16 @@ handle_transfers_get_finished (void *cls,
{
struct TALER_EXCHANGE_TransfersGetHandle *wdh = cls;
const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
struct TALER_EXCHANGE_TransfersGetResponse tgr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
wdh->job = NULL;
switch (response_code)
{
case 0:
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
tgr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
if (GNUNET_OK ==
@ -270,48 +278,47 @@ handle_transfers_get_finished (void *cls,
j))
return;
GNUNET_break_op (0);
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
hr.http_status = 0;
tgr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
tgr.hr.http_status = 0;
break;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
tgr.hr.ec = TALER_JSON_get_error_code (j);
tgr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_FORBIDDEN:
/* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
tgr.hr.ec = TALER_JSON_get_error_code (j);
tgr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_NOT_FOUND:
/* Exchange does not know about transaction;
we should pass the reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
tgr.hr.ec = TALER_JSON_get_error_code (j);
tgr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
tgr.hr.ec = TALER_JSON_get_error_code (j);
tgr.hr.hint = TALER_JSON_get_error_hint (j);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
tgr.hr.ec = TALER_JSON_get_error_code (j);
tgr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for transfers get\n",
(unsigned int) response_code,
(int) hr.ec);
(int) tgr.hr.ec);
break;
}
wdh->cb (wdh->cb_cls,
&hr,
NULL);
&tgr);
TALER_EXCHANGE_transfers_get_cancel (wdh);
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA
Copyright (C) 2014-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
@ -66,82 +66,65 @@ struct TALER_EXCHANGE_WireHandle
/**
* List of wire fees by method.
*/
struct FeeMap
{
/**
* Next entry in list.
*/
struct FeeMap *next;
/**
* Wire method this fee structure is for.
*/
char *method;
/**
* Array of wire fees, also linked list, but allocated
* only once.
*/
struct TALER_EXCHANGE_WireAggregateFees *fee_list;
};
/**
* Frees @a fm.
* Frees @a wfm array.
*
* @param fm memory to release
* @param wfm fee array to release
* @param wfm_len length of the @a wfm array
*/
static void
free_fees (struct FeeMap *fm)
free_fees (struct TALER_EXCHANGE_WireFeesByMethod *wfm,
unsigned int wfm_len)
{
while (NULL != fm)
for (unsigned int i = 0; i<wfm_len; i++)
{
struct FeeMap *fe = fm->next;
struct TALER_EXCHANGE_WireFeesByMethod *wfmi = &wfm[i];
GNUNET_free (fm->fee_list);
GNUNET_free (fm->method);
GNUNET_free (fm);
fm = fe;
while (NULL != wfmi->fees_head)
{
struct TALER_EXCHANGE_WireAggregateFees *fe
= wfmi->fees_head;
wfmi->fees_head = fe->next;
GNUNET_free (fe);
}
}
GNUNET_free (wfm);
}
/**
* Parse wire @a fees and return map.
* Parse wire @a fees and return array.
*
* @param master_pub master public key to use to check signatures
* @param fees json AggregateTransferFee to parse
* @param[out] fees_len set to length of returned array
* @return NULL on error
*/
static struct FeeMap *
static struct TALER_EXCHANGE_WireFeesByMethod *
parse_fees (const struct TALER_MasterPublicKeyP *master_pub,
json_t *fees)
const json_t *fees,
unsigned int *fees_len)
{
struct FeeMap *fm = NULL;
struct TALER_EXCHANGE_WireFeesByMethod *fbm;
unsigned int fbml = json_object_size (fees);
unsigned int i = 0;
const char *key;
json_t *fee_array;
const json_t *fee_array;
json_object_foreach (fees, key, fee_array) {
struct FeeMap *fe = GNUNET_new (struct FeeMap);
unsigned int len;
fbm = GNUNET_new_array (fbml,
struct TALER_EXCHANGE_WireFeesByMethod);
*fees_len = fbml;
json_object_foreach ((json_t *) fees, key, fee_array) {
struct TALER_EXCHANGE_WireFeesByMethod *fe = &fbm[i++];
unsigned int idx;
json_t *fee;
if (0 == (len = json_array_size (fee_array)))
{
GNUNET_free (fe);
continue; /* skip */
}
fe->method = GNUNET_strdup (key);
fe->next = fm;
fe->fee_list = GNUNET_new_array (len,
struct TALER_EXCHANGE_WireAggregateFees);
fm = fe;
fe->method = key;
fe->fees_head = NULL;
json_array_foreach (fee_array, idx, fee)
{
struct TALER_EXCHANGE_WireAggregateFees *wa = &fe->fee_list[idx];
struct TALER_EXCHANGE_WireAggregateFees *wa
= GNUNET_new (struct TALER_EXCHANGE_WireAggregateFees);
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("sig",
&wa->master_sig),
@ -156,6 +139,8 @@ parse_fees (const struct TALER_MasterPublicKeyP *master_pub,
GNUNET_JSON_spec_end ()
};
wa->next = fe->fees_head;
fe->fees_head = wa;
if (GNUNET_OK !=
GNUNET_JSON_parse (fee,
spec,
@ -163,7 +148,8 @@ parse_fees (const struct TALER_MasterPublicKeyP *master_pub,
NULL))
{
GNUNET_break_op (0);
free_fees (fm);
free_fees (fbm,
i);
return NULL;
}
if (GNUNET_OK !=
@ -176,35 +162,122 @@ parse_fees (const struct TALER_MasterPublicKeyP *master_pub,
&wa->master_sig))
{
GNUNET_break_op (0);
free_fees (fm);
free_fees (fbm,
i);
return NULL;
}
if (idx + 1 < len)
wa->next = &fe->fee_list[idx + 1];
else
wa->next = NULL;
}
}
return fm;
} /* for all fees over time */
} /* for all methods */
GNUNET_assert (i == fbml);
return fbm;
}
/**
* Find fee by @a method.
* Parse account restriction in @a jrest into @a rest.
*
* @param fm map to look in
* @param method key to look for
* @return NULL if fee is not specified in @a fm
* @param jrest array of account restrictions in JSON
* @param[out] resta_len set to length of @a resta
* @param[out] resta account restriction array to set
* @return #GNUNET_OK on success
*/
static const struct TALER_EXCHANGE_WireAggregateFees *
lookup_fee (const struct FeeMap *fm,
const char *method)
static enum GNUNET_GenericReturnValue
parse_restrictions (const json_t *jresta,
unsigned int *resta_len,
struct TALER_EXCHANGE_AccountRestriction **resta)
{
for (; NULL != fm; fm = fm->next)
if (0 == strcasecmp (fm->method,
method))
return fm->fee_list;
return NULL;
if (! json_is_array (jresta))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
*resta_len = json_array_size (jresta);
if (0 == *resta_len)
{
/* no restrictions, perfectly OK */
*resta = NULL;
return GNUNET_OK;
}
*resta = GNUNET_new_array (*resta_len,
struct TALER_EXCHANGE_AccountRestriction);
for (unsigned int i = 0; i<*resta_len; i++)
{
const json_t *jr = json_array_get (jresta,
i);
struct TALER_EXCHANGE_AccountRestriction *ar = &(*resta)[i];
const char *type = json_string_value (json_object_get (jr,
"type"));
if (NULL == type)
{
GNUNET_break (0);
goto fail;
}
if (0 == strcmp (type,
"deny"))
{
ar->type = TALER_EXCHANGE_AR_DENY;
continue;
}
if (0 == strcmp (type,
"regex"))
{
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string (
"payto_regex",
&ar->details.regex.posix_egrep),
GNUNET_JSON_spec_string (
"human_hint",
&ar->details.regex.human_hint),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_object_const (
"human_hint_i18n",
&ar->details.regex.human_hint_i18n),
NULL),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (jr,
spec,
NULL, NULL))
{
/* bogus reply */
GNUNET_break_op (0);
goto fail;
}
ar->type = TALER_EXCHANGE_AR_REGEX;
continue;
}
/* unsupported type */
GNUNET_break (0);
return GNUNET_SYSERR;
}
return GNUNET_OK;
fail:
GNUNET_free (*resta);
*resta_len = 0;
return GNUNET_SYSERR;
}
/**
* Free data within @a was, but not @a was itself.
*
* @param was array of wire account data
* @param was_len length of the @a was array
*/
static void
free_accounts (struct TALER_EXCHANGE_WireAccount *was,
unsigned int was_len)
{
for (unsigned int i = 0; i<was_len; i++)
{
struct TALER_EXCHANGE_WireAccount *wa = &was[i];
GNUNET_free (wa->credit_restrictions);
GNUNET_free (wa->debit_restrictions);
}
}
@ -223,9 +296,9 @@ handle_wire_finished (void *cls,
{
struct TALER_EXCHANGE_WireHandle *wh = cls;
const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
struct TALER_EXCHANGE_WireResponse wr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
TALER_LOG_DEBUG ("Checking raw /wire response\n");
@ -233,28 +306,29 @@ handle_wire_finished (void *cls,
switch (response_code)
{
case 0:
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
wr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
wh->exchange->wire_error_count++;
break;
case MHD_HTTP_OK:
{
json_t *accounts;
json_t *fees;
unsigned int num_accounts;
struct FeeMap *fm;
const json_t *accounts;
const json_t *fees;
const json_t *wads;
struct TALER_EXCHANGE_WireFeesByMethod *fbm;
struct TALER_MasterPublicKeyP master_pub;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("master_public_key",
&master_pub),
GNUNET_JSON_spec_json ("accounts",
GNUNET_JSON_spec_array_const ("accounts",
&accounts),
GNUNET_JSON_spec_json ("fees",
GNUNET_JSON_spec_object_const ("fees",
&fees),
GNUNET_JSON_spec_array_const ("wads",
&wads),
GNUNET_JSON_spec_end ()
};
wh->exchange->wire_error_count = 0;
if (GNUNET_OK !=
GNUNET_JSON_parse (j,
spec,
@ -262,8 +336,8 @@ handle_wire_finished (void *cls,
{
/* bogus reply */
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
wr.hr.http_status = 0;
wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
{
@ -275,61 +349,70 @@ handle_wire_finished (void *cls,
{
/* bogus reply: master public key in /wire differs from that in /keys */
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
wr.hr.http_status = 0;
wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
}
if (0 == (num_accounts = json_array_size (accounts)))
wr.details.ok.accounts_len
= json_array_size (accounts);
if (0 == wr.details.ok.accounts_len)
{
/* bogus reply */
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
wr.hr.http_status = 0;
wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
if (NULL == (fm = parse_fees (&master_pub,
fees)))
fbm = parse_fees (&master_pub,
fees,
&wr.details.ok.fees_len);
if (NULL == fbm)
{
/* bogus reply */
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
wr.hr.http_status = 0;
wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
/* parse accounts */
{
struct TALER_EXCHANGE_WireAccount was[num_accounts];
struct TALER_EXCHANGE_WireAccount was[wr.details.ok.accounts_len];
for (unsigned int i = 0; i<num_accounts; i++)
memset (was,
0,
sizeof (was));
wr.details.ok.accounts = was;
for (unsigned int i = 0;
i<wr.details.ok.accounts_len;
i++)
{
struct TALER_EXCHANGE_WireAccount *wa = &was[i];
json_t *account;
json_t *credit_restrictions;
json_t *debit_restrictions;
struct GNUNET_JSON_Specification spec_account[] = {
GNUNET_JSON_spec_string ("payto_uri",
&wa->payto_uri),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("conversion_url",
&wa->conversion_url),
NULL),
GNUNET_JSON_spec_json ("credit_restrictions",
&credit_restrictions),
GNUNET_JSON_spec_json ("debit_restrictions",
&debit_restrictions),
GNUNET_JSON_spec_fixed_auto ("master_sig",
&wa->master_sig),
GNUNET_JSON_spec_end ()
};
char *method;
json_t *account;
account = json_array_get (accounts,
i);
if (GNUNET_OK !=
TALER_JSON_exchange_wire_signature_check (account,
&master_pub))
{
/* bogus reply */
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_EXCHANGE_WIRE_SIGNATURE_INVALID;
break;
}
if (GNUNET_OK !=
GNUNET_JSON_parse (account,
spec_account,
@ -337,80 +420,104 @@ handle_wire_finished (void *cls,
{
/* bogus reply */
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
wr.hr.http_status = 0;
wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
if (NULL == (method = TALER_payto_get_method (wa->payto_uri)))
{
char *err;
err = TALER_payto_validate (wa->payto_uri);
if (NULL != err)
{
GNUNET_break_op (0);
wr.hr.http_status = 0;
wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
GNUNET_free (err);
break;
}
}
if (GNUNET_OK !=
TALER_exchange_wire_signature_check (wa->payto_uri,
wa->conversion_url,
debit_restrictions,
credit_restrictions,
&master_pub,
&wa->master_sig))
{
/* bogus reply */
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
wr.hr.http_status = 0;
wr.hr.ec = TALER_EC_EXCHANGE_WIRE_SIGNATURE_INVALID;
break;
}
if (NULL == (wa->fees = lookup_fee (fm,
method)))
if ( (GNUNET_OK !=
parse_restrictions (credit_restrictions,
&wa->credit_restrictions_length,
&wa->credit_restrictions)) ||
(GNUNET_OK !=
parse_restrictions (debit_restrictions,
&wa->debit_restrictions_length,
&wa->debit_restrictions)) )
{
/* bogus reply */
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
GNUNET_free (method);
wr.hr.http_status = 0;
wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
GNUNET_free (method);
GNUNET_JSON_parse_free (spec_account);
} /* end 'for all accounts */
if ( (0 != response_code) &&
if ( (0 != wr.hr.http_status) &&
(NULL != wh->cb) )
{
wh->cb (wh->cb_cls,
&hr,
num_accounts,
was);
&wr);
wh->cb = NULL;
}
free_accounts (was,
wr.details.ok.accounts_len);
} /* end of 'parse accounts */
free_fees (fm);
free_fees (fbm,
wr.details.ok.fees_len);
GNUNET_JSON_parse_free (spec);
} /* end of MHD_HTTP_OK */
break;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
wr.hr.ec = TALER_JSON_get_error_code (j);
wr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
wr.hr.ec = TALER_JSON_get_error_code (j);
wr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
wr.hr.ec = TALER_JSON_get_error_code (j);
wr.hr.hint = TALER_JSON_get_error_hint (j);
break;
default:
/* unexpected response code */
if (MHD_HTTP_GATEWAY_TIMEOUT == response_code)
wh->exchange->wire_error_count++;
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
wr.hr.ec = TALER_JSON_get_error_code (j);
wr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange wire\n",
(unsigned int) response_code,
(int) hr.ec);
(int) wr.hr.ec);
break;
}
if (NULL != wh->cb)
wh->cb (wh->cb_cls,
&hr,
0,
NULL);
&wr);
TALER_EXCHANGE_wire_cancel (wh);
}

View File

@ -116,22 +116,20 @@ struct TALER_EXCHANGE_WithdrawHandle
* HTTP /reserves/$RESERVE_PUB/withdraw request.
*
* @param cls the `struct TALER_EXCHANGE_WithdrawHandle`
* @param hr HTTP response data
* @param blind_sig blind signature over the coin, NULL on error
* @param w2r response data
*/
static void
handle_reserve_withdraw_finished (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_BlindedDenominationSignature *blind_sig)
const struct TALER_EXCHANGE_Withdraw2Response *w2r)
{
struct TALER_EXCHANGE_WithdrawHandle *wh = cls;
struct TALER_EXCHANGE_WithdrawResponse wr = {
.hr = *hr
.hr = w2r->hr
};
wh->wh2 = NULL;
switch (hr->http_status)
switch (w2r->hr.http_status)
{
case MHD_HTTP_OK:
{
@ -139,7 +137,7 @@ handle_reserve_withdraw_finished (
if (GNUNET_OK !=
TALER_planchet_to_coin (&wh->pk.key,
blind_sig,
&w2r->details.ok.blind_sig,
&wh->bks,
&wh->priv,
wh->ach,
@ -151,10 +149,10 @@ handle_reserve_withdraw_finished (
wr.hr.ec = TALER_EC_EXCHANGE_WITHDRAW_UNBLIND_FAILURE;
break;
}
wr.details.success.coin_priv = wh->priv;
wr.details.success.bks = wh->bks;
wr.details.success.sig = fc.sig;
wr.details.success.exchange_vals = wh->alg_values;
wr.details.ok.coin_priv = wh->priv;
wr.details.ok.bks = wh->bks;
wr.details.ok.sig = fc.sig;
wr.details.ok.exchange_vals = wh->alg_values;
break;
}
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
@ -170,7 +168,7 @@ handle_reserve_withdraw_finished (
};
if (GNUNET_OK !=
GNUNET_JSON_parse (hr->reply,
GNUNET_JSON_parse (w2r->hr.reply,
spec,
NULL, NULL))
{
@ -186,8 +184,8 @@ handle_reserve_withdraw_finished (
}
wh->cb (wh->cb_cls,
&wr);
if (MHD_HTTP_OK == hr->http_status)
TALER_denom_sig_free (&wr.details.success.sig);
if (MHD_HTTP_OK == w2r->hr.http_status)
TALER_denom_sig_free (&wr.details.ok.sig);
TALER_EXCHANGE_withdraw_cancel (wh);
}
@ -213,7 +211,7 @@ withdraw_cs_stage_two_callback (
switch (csrr->hr.http_status)
{
case MHD_HTTP_OK:
wh->alg_values = csrr->details.success.alg_values;
wh->alg_values = csrr->details.ok.alg_values;
TALER_planchet_setup_coin_priv (&wh->ps,
&wh->alg_values,
&wh->priv);

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA
Copyright (C) 2014-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
@ -99,16 +99,15 @@ static enum GNUNET_GenericReturnValue
reserve_withdraw_ok (struct TALER_EXCHANGE_Withdraw2Handle *wh,
const json_t *json)
{
struct TALER_BlindedDenominationSignature blind_sig;
struct TALER_EXCHANGE_Withdraw2Response w2r = {
.hr.reply = json,
.hr.http_status = MHD_HTTP_OK
};
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_blinded_denom_sig ("ev_sig",
&blind_sig),
&w2r.details.ok.blind_sig),
GNUNET_JSON_spec_end ()
};
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = json,
.http_status = MHD_HTTP_OK
};
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
@ -121,8 +120,7 @@ reserve_withdraw_ok (struct TALER_EXCHANGE_Withdraw2Handle *wh,
/* signature is valid, return it to the application */
wh->cb (wh->cb_cls,
&hr,
&blind_sig);
&w2r);
/* make sure callback isn't called again after return */
wh->cb = NULL;
GNUNET_JSON_parse_free (spec);
@ -240,16 +238,16 @@ handle_reserve_withdraw_finished (void *cls,
{
struct TALER_EXCHANGE_Withdraw2Handle *wh = cls;
const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
struct TALER_EXCHANGE_Withdraw2Response w2r = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
wh->job = NULL;
switch (response_code)
{
case 0:
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
w2r.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
@ -257,8 +255,8 @@ handle_reserve_withdraw_finished (void *cls,
j))
{
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
w2r.hr.http_status = 0;
w2r.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
GNUNET_assert (NULL == wh->cb);
@ -267,24 +265,24 @@ handle_reserve_withdraw_finished (void *cls,
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
w2r.hr.ec = TALER_JSON_get_error_code (j);
w2r.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_FORBIDDEN:
GNUNET_break_op (0);
/* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
w2r.hr.ec = TALER_JSON_get_error_code (j);
w2r.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, the exchange basically just says
that it doesn't know this reserve. Can happen if we
query before the wire transfer went through.
We should simply pass the JSON reply to the application. */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
w2r.hr.ec = TALER_JSON_get_error_code (j);
w2r.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_CONFLICT:
/* The exchange says that the reserve has insufficient funds;
@ -294,13 +292,13 @@ handle_reserve_withdraw_finished (void *cls,
j))
{
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
w2r.hr.http_status = 0;
w2r.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
}
else
{
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
w2r.hr.ec = TALER_JSON_get_error_code (j);
w2r.hr.hint = TALER_JSON_get_error_hint (j);
}
break;
case MHD_HTTP_GONE:
@ -308,8 +306,8 @@ handle_reserve_withdraw_finished (void *cls,
/* Note: one might want to check /keys for revocation
signature here, alas tricky in case our /keys
is outdated => left to clients */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
w2r.hr.ec = TALER_JSON_get_error_code (j);
w2r.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
/* only validate reply is well-formed */
@ -327,8 +325,8 @@ handle_reserve_withdraw_finished (void *cls,
NULL, NULL))
{
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
w2r.hr.http_status = 0;
w2r.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
}
@ -336,25 +334,24 @@ handle_reserve_withdraw_finished (void *cls,
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
w2r.hr.ec = TALER_JSON_get_error_code (j);
w2r.hr.hint = TALER_JSON_get_error_hint (j);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
w2r.hr.ec = TALER_JSON_get_error_code (j);
w2r.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange withdraw\n",
(unsigned int) response_code,
(int) hr.ec);
(int) w2r.hr.ec);
break;
}
if (NULL != wh->cb)
{
wh->cb (wh->cb_cls,
&hr,
NULL);
&w2r);
wh->cb = NULL;
}
TALER_EXCHANGE_withdraw2_cancel (wh);

View File

@ -386,10 +386,10 @@ history_cb (void *cls,
GNUNET_break (0);
goto error;
case MHD_HTTP_OK:
for (unsigned int i = 0; i<chr->details.success.details_length; i++)
for (unsigned int i = 0; i<chr->details.ok.details_length; i++)
{
const struct TALER_BANK_CreditDetails *cd =
&chr->details.success.details[i];
&chr->details.ok.details[i];
/* check current element */
if (GNUNET_OK !=

View File

@ -378,10 +378,10 @@ history_cb (void *cls,
GNUNET_break (0);
goto error;
case MHD_HTTP_OK:
for (unsigned int i = 0; i<dhr->details.success.details_length; i++)
for (unsigned int i = 0; i<dhr->details.ok.details_length; i++)
{
const struct TALER_BANK_DebitDetails *dd =
&dhr->details.success.details[i];
&dhr->details.ok.details[i];
/* check current element */
if (GNUNET_OK !=

View File

@ -212,17 +212,17 @@ batch_deposit_cb (void *cls,
}
if (MHD_HTTP_OK == dr->hr.http_status)
{
if (ds->num_coins != dr->details.success.num_signatures)
if (ds->num_coins != dr->details.ok.num_signatures)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (ds->is);
return;
}
ds->deposit_succeeded = GNUNET_YES;
ds->exchange_timestamp = dr->details.success.deposit_timestamp;
ds->exchange_pub = *dr->details.success.exchange_pub;
ds->exchange_sigs = GNUNET_memdup (dr->details.success.exchange_sigs,
dr->details.success.num_signatures
ds->exchange_timestamp = dr->details.ok.deposit_timestamp;
ds->exchange_pub = *dr->details.ok.exchange_pub;
ds->exchange_sigs = GNUNET_memdup (dr->details.ok.exchange_sigs,
dr->details.ok.num_signatures
* sizeof (struct
TALER_ExchangeSignatureP));
}

View File

@ -210,7 +210,7 @@ reserve_batch_withdraw_cb (void *cls,
{
struct CoinState *cs = &ws->coins[i];
const struct TALER_EXCHANGE_PrivateCoinDetails *pcd
= &wr->details.success.coins[i];
= &wr->details.ok.coins[i];
TALER_denom_sig_deep_copy (&cs->sig,
&pcd->sig);

View File

@ -116,10 +116,10 @@ check_aml_decision_cb (void *cls,
GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_amount (ref,
&amount));
for (unsigned int i = 0; i<adr->details.success.aml_history_length; i++)
for (unsigned int i = 0; i<adr->details.ok.aml_history_length; i++)
{
const struct TALER_EXCHANGE_AmlDecisionDetail *aml_history
= &adr->details.success.aml_history[i];
= &adr->details.ok.aml_history[i];
if ( (NULL == oldest) ||
(0 !=

View File

@ -121,7 +121,7 @@ get_cb (void *cls,
const struct TALER_PurseMergePrivateKeyP *mp;
const json_t *ct;
ds->purse_pub = dr->details.success.purse_pub;
ds->purse_pub = dr->details.ok.purse_pub;
if (ds->merge)
{
if (GNUNET_OK !=
@ -136,8 +136,8 @@ get_cb (void *cls,
TALER_CRYPTO_contract_decrypt_for_merge (
&ds->contract_priv,
&ds->purse_pub,
dr->details.success.econtract,
dr->details.success.econtract_size,
dr->details.ok.econtract,
dr->details.ok.econtract_size,
&ds->merge_priv);
if (0 !=
GNUNET_memcmp (mp,
@ -153,8 +153,8 @@ get_cb (void *cls,
ds->contract_terms =
TALER_CRYPTO_contract_decrypt_for_deposit (
&ds->contract_priv,
dr->details.success.econtract,
dr->details.success.econtract_size);
dr->details.ok.econtract,
dr->details.ok.econtract_size);
}
if (NULL == ds->contract_terms)
{

View File

@ -264,9 +264,9 @@ deposit_cb (void *cls,
if (MHD_HTTP_OK == dr->hr.http_status)
{
ds->deposit_succeeded = GNUNET_YES;
ds->exchange_timestamp = dr->details.success.deposit_timestamp;
ds->exchange_pub = *dr->details.success.exchange_pub;
ds->exchange_sig = *dr->details.success.exchange_sig;
ds->exchange_timestamp = dr->details.ok.deposit_timestamp;
ds->exchange_pub = *dr->details.ok.exchange_pub;
ds->exchange_sig = *dr->details.ok.exchange_sig;
}
TALER_TESTING_interpreter_next (ds->is);
}

View File

@ -128,7 +128,7 @@ deposit_wtid_cb (void *cls,
switch (dr->hr.http_status)
{
case MHD_HTTP_OK:
tts->wtid = dr->details.success.wtid;
tts->wtid = dr->details.ok.wtid;
if (NULL != tts->bank_transfer_reference)
{
const struct TALER_TESTING_Command *bank_transfer_cmd;
@ -155,7 +155,7 @@ deposit_wtid_cb (void *cls,
}
/* Compare that expected and gotten subjects match. */
if (0 != GNUNET_memcmp (&dr->details.success.wtid,
if (0 != GNUNET_memcmp (&dr->details.ok.wtid,
wtid_want))
{
GNUNET_break (0);

View File

@ -80,6 +80,7 @@ nft_run (void *cls,
"wget",
"--header=Content-Type:application/json",
"--auth-no-challenge",
"--output-file=/dev/null",
"--post-data={\"level\":\"all\",\"rangeType\":\"latest\"}",
user,
pass,

View File

@ -176,8 +176,8 @@ deposit_cb (void *cls,
}
if (MHD_HTTP_OK == dr->hr.http_status)
{
ds->exchange_pub = dr->details.success.exchange_pub;
ds->exchange_sig = dr->details.success.exchange_sig;
ds->exchange_pub = dr->details.ok.exchange_pub;
ds->exchange_sig = dr->details.ok.exchange_sig;
}
TALER_TESTING_interpreter_next (ds->is);
}

View File

@ -152,8 +152,8 @@ deposit_cb (void *cls,
if (MHD_HTTP_OK == dr->hr.http_status)
{
if (-1 !=
TALER_amount_cmp (&dr->details.success.total_deposited,
&dr->details.success.purse_value_after_fees))
TALER_amount_cmp (&dr->details.ok.total_deposited,
&dr->details.ok.purse_value_after_fees))
{
const struct TALER_TESTING_Command *purse_cmd;
const struct TALER_ReserveSignatureP *reserve_sig;
@ -213,7 +213,7 @@ deposit_cb (void *cls,
/* Note: change when flags below changes! */
ds->reserve_history.amount
= dr->details.success.purse_value_after_fees;
= dr->details.ok.purse_value_after_fees;
if (true)
{
ds->reserve_history.details.merge_details.purse_fee = gf->fees.purse;
@ -226,7 +226,7 @@ deposit_cb (void *cls,
}
}
ds->reserve_history.details.merge_details.h_contract_terms
= dr->details.success.h_contract_terms;
= dr->details.ok.h_contract_terms;
ds->reserve_history.details.merge_details.merge_pub
= *merge_pub;
ds->reserve_history.details.merge_details.purse_pub
@ -236,7 +236,7 @@ deposit_cb (void *cls,
ds->reserve_history.details.merge_details.merge_timestamp
= *merge_timestamp;
ds->reserve_history.details.merge_details.purse_expiration
= dr->details.success.purse_expiration;
= dr->details.ok.purse_expiration;
ds->reserve_history.details.merge_details.min_age
= ds->min_age;
ds->reserve_history.details.merge_details.flags

View File

@ -147,11 +147,11 @@ purse_status_cb (void *cls,
TALER_string_to_amount (ss->expected_balance,
&eb));
if (0 != TALER_amount_cmp (&eb,
&rs->details.success.balance))
&rs->details.ok.balance))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected amount in purse: %s\n",
TALER_amount_to_string (&rs->details.success.balance));
TALER_amount_to_string (&rs->details.ok.balance));
TALER_TESTING_interpreter_fail (ss->is);
return;
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2018 Taler Systems SA
Copyright (C) 2014-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
@ -73,15 +73,14 @@ struct RecoupState
* was paid back belonged to the right reserve.
*
* @param cls closure
* @param hr HTTP response details
* @param reserve_pub public key of the reserve receiving the recoup
* @param rr response details
*/
static void
recoup_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_ReservePublicKeyP *reserve_pub)
const struct TALER_EXCHANGE_RecoupResponse *rr)
{
struct RecoupState *ps = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &rr->hr;
struct TALER_TESTING_Interpreter *is = ps->is;
struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
const struct TALER_TESTING_Command *reserve_cmd;
@ -135,12 +134,6 @@ recoup_cb (void *cls,
{
const struct TALER_ReservePrivateKeyP *reserve_priv;
if (NULL == reserve_pub)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
if (GNUNET_OK !=
TALER_TESTING_get_trait_reserve_priv (reserve_cmd,
&reserve_priv))
@ -151,7 +144,7 @@ recoup_cb (void *cls,
}
GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
&ps->reserve_pub.eddsa_pub);
if (0 != GNUNET_memcmp (reserve_pub,
if (0 != GNUNET_memcmp (&rr->details.ok.reserve_pub,
&ps->reserve_pub))
{
GNUNET_break (0);

View File

@ -73,15 +73,14 @@ struct RecoupRefreshState
* was paid back belonged to the right old coin.
*
* @param cls closure
* @param hr HTTP response details
* @param old_coin_pub public key of the dirty coin
* @param rrr response details
*/
static void
recoup_refresh_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_CoinSpendPublicKeyP *old_coin_pub)
const struct TALER_EXCHANGE_RecoupRefreshResponse *rrr)
{
struct RecoupRefreshState *rrs = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &rrr->hr;
struct TALER_TESTING_Interpreter *is = rrs->is;
struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
char *cref;
@ -150,7 +149,7 @@ recoup_refresh_cb (void *cls,
GNUNET_CRYPTO_eddsa_key_get_public (&dirty_priv->eddsa_priv,
&oc.eddsa_pub);
if (0 != GNUNET_memcmp (&oc,
old_coin_pub))
&rrr->details.ok.old_coin_pub))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);

View File

@ -411,7 +411,7 @@ reveal_cb (void *cls,
switch (hr->http_status)
{
case MHD_HTTP_OK:
rrs->num_fresh_coins = rr->details.success.num_coins;
rrs->num_fresh_coins = rr->details.ok.num_coins;
rrs->psa = GNUNET_new_array (rrs->num_fresh_coins,
struct TALER_PlanchetMasterSecretP);
rrs->fresh_coins = GNUNET_new_array (rrs->num_fresh_coins,
@ -419,7 +419,7 @@ reveal_cb (void *cls,
for (unsigned int i = 0; i<rrs->num_fresh_coins; i++)
{
const struct TALER_EXCHANGE_RevealedCoinInfo *coin
= &rr->details.success.coins[i];
= &rr->details.ok.coins[i];
struct TALER_TESTING_FreshCoinData *fc = &rrs->fresh_coins[i];
rrs->psa[i] = coin->ps;
@ -675,11 +675,11 @@ link_cb (void *cls,
TALER_TESTING_interpreter_fail (rls->is);
return;
}
if (lr->details.success.num_coins != *num_fresh_coins)
if (lr->details.ok.num_coins != *num_fresh_coins)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected number of fresh coins: %d vs %d in %s:%u\n",
lr->details.success.num_coins,
lr->details.ok.num_coins,
*num_fresh_coins,
__FILE__,
__LINE__);
@ -687,11 +687,11 @@ link_cb (void *cls,
return;
}
/* check that the coins match */
for (unsigned int i = 0; i<lr->details.success.num_coins; i++)
for (unsigned int j = i + 1; j<lr->details.success.num_coins; j++)
for (unsigned int i = 0; i<lr->details.ok.num_coins; i++)
for (unsigned int j = i + 1; j<lr->details.ok.num_coins; j++)
if (0 ==
GNUNET_memcmp (&lr->details.success.coins[i].coin_priv,
&lr->details.success.coins[j].coin_priv))
GNUNET_memcmp (&lr->details.ok.coins[i].coin_priv,
&lr->details.ok.coins[j].coin_priv))
GNUNET_break (0);
/* Note: coins might be legitimately permutated in here... */
found = 0;
@ -709,12 +709,12 @@ link_cb (void *cls,
return;
}
for (unsigned int i = 0; i<lr->details.success.num_coins; i++)
for (unsigned int i = 0; i<lr->details.ok.num_coins; i++)
{
const struct TALER_EXCHANGE_LinkedCoinInfo *lci_i
= &lr->details.success.coins[i];
= &lr->details.ok.coins[i];
for (unsigned int j = 0; j<lr->details.success.num_coins; j++)
for (unsigned int j = 0; j<lr->details.ok.num_coins; j++)
{
const struct TALER_TESTING_FreshCoinData *fcj
= &(*fc)[j];
@ -735,12 +735,12 @@ link_cb (void *cls,
} /* for j*/
} /* for i */
}
if (found != lr->details.success.num_coins)
if (found != lr->details.ok.num_coins)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Only %u/%u coins match expectations\n",
found,
lr->details.success.num_coins);
lr->details.ok.num_coins);
GNUNET_break (0);
TALER_TESTING_interpreter_fail (rls->is);
return;
@ -952,16 +952,16 @@ melt_cb (void *cls,
}
if (MHD_HTTP_OK == hr->http_status)
{
rms->noreveal_index = mr->details.success.noreveal_index;
if (mr->details.success.num_mbds != rms->num_fresh_coins)
rms->noreveal_index = mr->details.ok.noreveal_index;
if (mr->details.ok.num_mbds != rms->num_fresh_coins)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (rms->is);
return;
}
GNUNET_free (rms->mbds);
rms->mbds = GNUNET_memdup (mr->details.success.mbds,
mr->details.success.num_mbds
rms->mbds = GNUNET_memdup (mr->details.ok.mbds,
mr->details.ok.num_mbds
* sizeof (struct
TALER_EXCHANGE_MeltBlindingDetail));
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2020 Taler Systems SA
Copyright (C) 2014-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
@ -75,19 +75,14 @@ struct RefundState
* response code is acceptable.
*
* @param cls closure
* @param hr HTTP response details
* @param exchange_pub public key the exchange
* used for signing @a obj.
* @param exchange_sig actual signature confirming the refund
* @param rr response details
*/
static void
refund_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_ExchangePublicKeyP *exchange_pub,
const struct TALER_ExchangeSignatureP *exchange_sig)
const struct TALER_EXCHANGE_RefundResponse *rr)
{
struct RefundState *rs = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &rr->hr;
struct TALER_TESTING_Command *refund_cmd;
refund_cmd = &rs->is->commands[rs->is->ip];

View File

@ -65,14 +65,15 @@ struct RevokeState
* Function called with information about the post revocation operation result.
*
* @param cls closure with a `struct RevokeState *`
* @param hr HTTP response data
* @param rdr response data
*/
static void
success_cb (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementRevokeDenominationResponse *rdr)
{
struct RevokeState *rs = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &rdr->hr;
rs->kh = NULL;
if (rs->expected_response_code != hr->http_status)

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2020 Taler Systems SA
Copyright (C) 2014-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
@ -65,14 +65,15 @@ struct RevokeState
* Function called with information about the post revocation operation result.
*
* @param cls closure with a `struct RevokeState *`
* @param hr HTTP response data
* @param rsr response data
*/
static void
success_cb (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementRevokeSigningKeyResponse *rsr)
{
struct RevokeState *rs = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &rsr->hr;
rs->kh = NULL;
if (rs->expected_response_code != hr->http_status)

View File

@ -84,13 +84,15 @@ struct SetOfficerState
* if the response code is acceptable.
*
* @param cls closure.
* @param hr HTTP response details
* @param ar response details
*/
static void
set_officer_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct
TALER_EXCHANGE_ManagementUpdateAmlOfficerResponse *ar)
{
struct SetOfficerState *ds = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &ar->hr;
ds->dh = NULL;
if (MHD_HTTP_NO_CONTENT != hr->http_status)

View File

@ -115,15 +115,14 @@ track_transfer_cleanup (void *cls,
* wire fees and hashed wire details as well.
*
* @param cls closure.
* @param hr HTTP response details
* @param ta transfer data returned by the exchange
* @param tgr response details
*/
static void
track_transfer_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_EXCHANGE_TransferData *ta)
const struct TALER_EXCHANGE_TransfersGetResponse *tgr)
{
struct TrackTransferState *tts = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &tgr->hr;
struct TALER_TESTING_Interpreter *is = tts->is;
struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
struct TALER_Amount expected_amount;
@ -148,6 +147,10 @@ track_transfer_cb (void *cls,
switch (hr->http_status)
{
case MHD_HTTP_OK:
{
const struct TALER_EXCHANGE_TransferData *ta
= &tgr->details.ok.td;
if (NULL == tts->expected_total_amount)
{
GNUNET_break (0);
@ -223,7 +226,8 @@ track_transfer_cb (void *cls,
wire_details_cmd
= TALER_TESTING_interpreter_lookup_command (is,
tts->wire_details_reference);
tts->
wire_details_reference);
if (NULL == wire_details_cmd)
{
GNUNET_break (0);
@ -260,7 +264,8 @@ track_transfer_cb (void *cls,
total_amount_cmd
= TALER_TESTING_interpreter_lookup_command (is,
tts->total_amount_reference);
tts->
total_amount_reference);
if (NULL == total_amount_cmd)
{
GNUNET_break (0);
@ -288,7 +293,9 @@ track_transfer_cb (void *cls,
return;
}
}
}
break;
} /* case OK */
} /* switch on status */
TALER_TESTING_interpreter_next (is);
}

View File

@ -72,18 +72,14 @@ struct WireState
* that the wire fee is acceptable too.
*
* @param cls closure.
* @param hr HTTP response details
* @param accounts_len length of the @a accounts array.
* @param accounts list of wire accounts of the exchange,
* NULL on error.
* @param wr response details
*/
static void
wire_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
unsigned int accounts_len,
const struct TALER_EXCHANGE_WireAccount *accounts)
const struct TALER_EXCHANGE_WireResponse *wr)
{
struct WireState *ws = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &wr->hr;
struct TALER_TESTING_Command *cmd = &ws->is->commands[ws->is->ip];
struct TALER_Amount expected_fee;
@ -100,6 +96,15 @@ wire_cb (void *cls,
if (MHD_HTTP_OK == hr->http_status)
{
unsigned int accounts_len
= wr->details.ok.accounts_len;
unsigned int fees_len
= wr->details.ok.fees_len;
const struct TALER_EXCHANGE_WireAccount *accounts
= wr->details.ok.accounts;
const struct TALER_EXCHANGE_WireFeesByMethod *fees
= wr->details.ok.fees;
for (unsigned int i = 0; i<accounts_len; i++)
{
char *method;
@ -115,13 +120,23 @@ wire_cb (void *cls,
method))
{
ws->method_found = GNUNET_OK;
}
GNUNET_free (method);
}
if (NULL != ws->expected_fee)
{
bool fee_found = false;
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (ws->expected_fee,
&expected_fee));
for (unsigned int i = 0; i<fees_len; i++)
{
if (0 != strcmp (fees[i].method,
ws->expected_method))
continue;
for (const struct TALER_EXCHANGE_WireAggregateFees *waf
= accounts[i].fees;
= fees[i].fees_head;
NULL != waf;
waf = waf->next)
{
@ -132,15 +147,19 @@ wire_cb (void *cls,
"Wire fee mismatch to command %s\n",
cmd->label);
TALER_TESTING_interpreter_fail (ws->is);
GNUNET_free (method);
return;
}
fee_found = true;
}
}
if (! fee_found)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"/wire does not contain expected fee '%s'\n",
ws->expected_fee);
TALER_TESTING_interpreter_fail (ws->is);
return;
}
TALER_LOG_DEBUG ("Freeing method '%s'\n",
method);
GNUNET_free (method);
}
if (GNUNET_OK != ws->method_found)
{

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2020 Taler Systems SA
Copyright (C) 2020-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
@ -67,13 +67,14 @@ struct WireAddState
* if the response code is acceptable.
*
* @param cls closure.
* @param hr HTTP response details
* @param wer response details
*/
static void
wire_add_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementWireEnableResponse *wer)
{
struct WireAddState *ds = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &wer->hr;
ds->dh = NULL;
if (ds->expected_response_code != hr->http_status)
@ -110,10 +111,14 @@ wire_add_run (void *cls,
struct TALER_MasterSignatureP master_sig1;
struct TALER_MasterSignatureP master_sig2;
struct GNUNET_TIME_Timestamp now;
json_t *credit_rest;
json_t *debit_rest;
(void) cmd;
now = GNUNET_TIME_timestamp_get ();
ds->is = is;
debit_rest = json_array ();
credit_rest = json_array ();
if (ds->bad_sig)
{
memset (&master_sig1,
@ -126,10 +131,16 @@ wire_add_run (void *cls,
else
{
TALER_exchange_offline_wire_add_sign (ds->payto_uri,
NULL,
debit_rest,
credit_rest,
now,
&is->master_priv,
&master_sig1);
TALER_exchange_wire_signature_make (ds->payto_uri,
NULL,
debit_rest,
credit_rest,
&is->master_priv,
&master_sig2);
}
@ -137,11 +148,16 @@ wire_add_run (void *cls,
is->ctx,
is->exchange_url,
ds->payto_uri,
NULL,
debit_rest,
credit_rest,
now,
&master_sig1,
&master_sig2,
&wire_add_cb,
ds);
json_decref (debit_rest);
json_decref (credit_rest);
if (NULL == ds->dh)
{
GNUNET_break (0);

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2020 Taler Systems SA
Copyright (C) 2020, 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
@ -67,13 +67,14 @@ struct WireDelState
* if the response code is acceptable.
*
* @param cls closure.
* @param hr HTTP response details
* @param wdr response details
*/
static void
wire_del_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr)
const struct TALER_EXCHANGE_ManagementWireDisableResponse *wdr)
{
struct WireDelState *ds = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &wdr->hr;
ds->dh = NULL;
if (ds->expected_response_code != hr->http_status)

View File

@ -297,10 +297,10 @@ reserve_withdraw_cb (void *cls,
{
case MHD_HTTP_OK:
TALER_denom_sig_deep_copy (&ws->sig,
&wr->details.success.sig);
ws->coin_priv = wr->details.success.coin_priv;
ws->bks = wr->details.success.bks;
ws->exchange_vals = wr->details.success.exchange_vals;
&wr->details.ok.sig);
ws->coin_priv = wr->details.ok.coin_priv;
ws->bks = wr->details.ok.bks;
ws->exchange_vals = wr->details.ok.exchange_vals;
if (0 != ws->total_backoff.rel_value_us)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,

View File

@ -526,20 +526,28 @@ sighandler_child_death (void)
void
TALER_TESTING_cert_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_EXCHANGE_Keys *keys,
enum TALER_EXCHANGE_VersionCompatibility compat)
const struct TALER_EXCHANGE_KeysResponse *kr)
{
const struct TALER_EXCHANGE_HttpResponse *hr = &kr->hr;
struct MainContext *main_ctx = cls;
struct TALER_TESTING_Interpreter *is = main_ctx->is;
(void) compat;
if (NULL == keys)
switch (hr->http_status)
{
if (GNUNET_NO == is->working)
case MHD_HTTP_OK:
/* dealt with below */
break;
default:
if (GNUNET_YES == is->working)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Got NULL response for /keys during execution (%u/%d)!\n",
hr->http_status,
(int) hr->ec);
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Got NULL response for /keys during startup (%u/%d), retrying!\n",
"Got failure response for /keys during startup (%u/%d), retrying!\n",
hr->http_status,
(int) hr->ec);
TALER_EXCHANGE_disconnect (is->exchange);
@ -552,23 +560,12 @@ TALER_TESTING_cert_cb (void *cls,
TALER_EXCHANGE_OPTION_END)));
return;
}
else
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Got NULL response for /keys during execution (%u/%d)!\n",
hr->http_status,
(int) hr->ec);
}
}
else
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Got %d DK from /keys in generation %u\n",
keys->num_denom_keys,
kr->details.ok.keys->num_denom_keys,
is->key_generation + 1);
}
is->key_generation++;
is->keys = keys;
is->keys = kr->details.ok.keys;
/* /keys has been called for some reason and
* the interpreter is already running. */

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2020-2022 Taler Systems SA
Copyright (C) 2020-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
@ -677,6 +677,22 @@ struct TALER_MasterAddWirePS
* Hash over the exchange's payto URI.
*/
struct TALER_PaytoHashP 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
@ -685,6 +701,9 @@ GNUNET_NETWORK_STRUCT_END
void
TALER_exchange_offline_wire_add_sign (
const char *payto_uri,
const char *conversion_url,
const json_t *debit_restrictions,
const json_t *credit_restrictions,
struct GNUNET_TIME_Timestamp now,
const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig)
@ -697,6 +716,14 @@ TALER_exchange_offline_wire_add_sign (
TALER_payto_hash (payto_uri,
&kv.h_payto);
if (NULL != conversion_url)
GNUNET_CRYPTO_hash (conversion_url,
strlen (conversion_url),
&kv.h_conversion_url);
TALER_json_hash (debit_restrictions,
&kv.h_debit_restrictions);
TALER_json_hash (credit_restrictions,
&kv.h_credit_restrictions);
GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv,
&kv,
&master_sig->eddsa_signature);
@ -706,6 +733,9 @@ TALER_exchange_offline_wire_add_sign (
enum GNUNET_GenericReturnValue
TALER_exchange_offline_wire_add_verify (
const char *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)
@ -718,6 +748,14 @@ TALER_exchange_offline_wire_add_verify (
TALER_payto_hash (payto_uri,
&aw.h_payto);
if (NULL != conversion_url)
GNUNET_CRYPTO_hash (conversion_url,
strlen (conversion_url),
&aw.h_conversion_url);
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,
@ -1095,6 +1133,22 @@ struct TALER_MasterWireDetailsPS
*/
struct TALER_PaytoHashP 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;
/**
* Hash over the credit restrictions.
*/
struct GNUNET_HashCode h_credit_restrictions;
};
GNUNET_NETWORK_STRUCT_END
@ -1103,6 +1157,9 @@ GNUNET_NETWORK_STRUCT_END
enum GNUNET_GenericReturnValue
TALER_exchange_wire_signature_check (
const char *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)
{
@ -1113,6 +1170,14 @@ TALER_exchange_wire_signature_check (
TALER_payto_hash (payto_uri,
&wd.h_wire_details);
if (NULL != conversion_url)
GNUNET_CRYPTO_hash (conversion_url,
strlen (conversion_url),
&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,
@ -1123,6 +1188,9 @@ TALER_exchange_wire_signature_check (
void
TALER_exchange_wire_signature_make (
const char *payto_uri,
const char *conversion_url,
const json_t *debit_restrictions,
const json_t *credit_restrictions,
const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig)
{
@ -1133,6 +1201,14 @@ TALER_exchange_wire_signature_make (
TALER_payto_hash (payto_uri,
&wd.h_wire_details);
if (NULL != conversion_url)
GNUNET_CRYPTO_hash (conversion_url,
strlen (conversion_url),
&wd.h_conversion_url);
TALER_json_hash (debit_restrictions,
&wd.h_debit_restrictions);
TALER_json_hash (credit_restrictions,
&wd.h_credit_restrictions);
GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv,
&wd,
&master_sig->eddsa_signature);