Merge branch 'master' of ssh://git.taler.net/exchange

This commit is contained in:
Özgür Kesim 2023-07-10 10:25:29 +02:00
commit 6107e99559
Signed by: oec
GPG Key ID: 3D76A56D79EDD9D7
24 changed files with 484 additions and 719 deletions

View File

@ -182,8 +182,7 @@ kyc_aml_finished (void *cls,
kat->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR; kat->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
kat->response = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED, kat->response = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED,
"do_insert_kyc_attributes"); "do_insert_kyc_attributes");
/* Continued below to return the response */
/* FIXME-Christian: shouldn't we return in the error case? */
} }
/* Finally, return result to main handler */ /* Finally, return result to main handler */
kat->cb (kat->cb_cls, kat->cb (kat->cb_cls,

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER 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 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 terms of the GNU Affero General Public License as published by the Free Software
@ -1701,8 +1701,10 @@ setup_general_response_headers (struct TEH_KeyStateHandle *ksh,
TALER_MHD_get_date_string (m.abs_time, TALER_MHD_get_date_string (m.abs_time,
dat); dat);
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Setting /keys 'Expires' header to '%s'\n", "Setting /keys 'Expires' header to '%s' (rekey frequency is %s)\n",
dat); dat,
GNUNET_TIME_relative2s (ksh->rekey_frequency,
false));
GNUNET_break (MHD_YES == GNUNET_break (MHD_YES ==
MHD_add_response_header (response, MHD_add_response_header (response,
MHD_HTTP_HEADER_EXPIRES, MHD_HTTP_HEADER_EXPIRES,
@ -2221,10 +2223,13 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
.age_mask = dk->meta.age_mask, .age_mask = dk->meta.age_mask,
}; };
memset (&meta.hash, 0, sizeof(meta.hash)); memset (&meta.hash,
0,
sizeof(meta.hash));
/* Search the group/JSON-blob for the key */ /* Search the group/JSON-blob for the key */
GNUNET_CRYPTO_hash (&meta, sizeof(meta), &key); GNUNET_CRYPTO_hash (&meta,
sizeof(meta),
&key);
group = group =
(struct groupData *) GNUNET_CONTAINER_multihashmap_get ( (struct groupData *) GNUNET_CONTAINER_multihashmap_get (
@ -2235,7 +2240,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
{ {
/* There is no group for this meta-data yet, so we create a new group */ /* There is no group for this meta-data yet, so we create a new group */
bool age_restricted = meta.age_mask.bits != 0; bool age_restricted = meta.age_mask.bits != 0;
char *cipher; const char *cipher;
group = GNUNET_new (struct groupData); group = GNUNET_new (struct groupData);
memset (group, 0, sizeof(*group)); memset (group, 0, sizeof(*group));
@ -2294,17 +2299,16 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
{ {
case TALER_DENOMINATION_RSA: case TALER_DENOMINATION_RSA:
key_spec = key_spec =
GNUNET_JSON_pack_rsa_public_key ("rsa_pub", GNUNET_JSON_pack_rsa_public_key (
dk->denom_pub.details. "rsa_pub",
rsa_public_key); dk->denom_pub.details.rsa_public_key);
break; break;
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
key_spec = key_spec =
GNUNET_JSON_pack_data_varsize ("cs_pub", GNUNET_JSON_pack_data_varsize (
&dk->denom_pub.details. "cs_pub",
cs_public_key, &dk->denom_pub.details.cs_public_key,
sizeof (dk->denom_pub.details. sizeof (dk->denom_pub.details.cs_public_key));
cs_public_key));
break; break;
default: default:
GNUNET_assert (false); GNUNET_assert (false);
@ -2544,9 +2548,9 @@ build_key_state (struct HelperState *hs,
ksh->helpers = hs; ksh->helpers = hs;
} }
ksh->denomkey_map = GNUNET_CONTAINER_multihashmap_create (1024, ksh->denomkey_map = GNUNET_CONTAINER_multihashmap_create (1024,
GNUNET_YES); true);
ksh->signkey_map = GNUNET_CONTAINER_multipeermap_create (32, ksh->signkey_map = GNUNET_CONTAINER_multipeermap_create (32,
GNUNET_NO /* MUST be NO! */); false /* MUST be false! */);
ksh->auditors = json_array (); ksh->auditors = json_array ();
GNUNET_assert (NULL != ksh->auditors); GNUNET_assert (NULL != ksh->auditors);
/* NOTE: fetches master-signed signkeys, but ALSO those that were revoked! */ /* NOTE: fetches master-signed signkeys, but ALSO those that were revoked! */

View File

@ -239,6 +239,11 @@ struct TALER_EXCHANGE_Keys
*/ */
struct TALER_MasterPublicKeyP master_pub; struct TALER_MasterPublicKeyP master_pub;
/**
* Signature over extension configuration data, if any.
*/
struct TALER_MasterSignatureP extensions_sig;
/** /**
* Array of the exchange's online signing keys. * Array of the exchange's online signing keys.
*/ */
@ -259,6 +264,11 @@ struct TALER_EXCHANGE_Keys
*/ */
struct TALER_EXCHANGE_GlobalFee *global_fees; struct TALER_EXCHANGE_GlobalFee *global_fees;
/**
* Configuration data for extensions.
*/
json_t *extensions;
/** /**
* Supported Taler protocol version by the exchange. * Supported Taler protocol version by the exchange.
* String in the format current:revision:age using the * String in the format current:revision:age using the

View File

@ -649,6 +649,7 @@ TALER_TESTING_cmd_system_start (
* *
* @param label command label * @param label command label
* @param cfg configuration to use * @param cfg configuration to use
* @param last_keys_ref reference to command with prior /keys response, NULL for none
* @param wait_for_keys block until we got /keys * @param wait_for_keys block until we got /keys
* @param load_private_key obtain private key from file indicated in @a cfg * @param load_private_key obtain private key from file indicated in @a cfg
* @return the command. * @return the command.
@ -657,6 +658,7 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_get_exchange ( TALER_TESTING_cmd_get_exchange (
const char *label, const char *label,
const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *last_keys_ref,
bool wait_for_keys, bool wait_for_keys,
bool load_private_key); bool load_private_key);
@ -1812,34 +1814,6 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_wait_service (const char *label, TALER_TESTING_cmd_wait_service (const char *label,
const char *url); const char *url);
/**
* Make a "check keys" command.
*
* @param label command label
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_check_keys (const char *label);
/**
* Make a "check keys" command. It lets the user set a last denom issue date to be
* used in the request for /keys.
*
* @param label command label
* @param last_denom_date_ref previous /keys command to use to
* obtain the "last_denom_date" value from; "zero" can be used
* as a special value to force an absolute time of zero to be
* given to as an argument
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_check_keys_with_last_denom (
const char *label,
const char *last_denom_date_ref);
/** /**
* Create a "batch" command. Such command takes a * Create a "batch" command. Such command takes a
* end_CMD-terminated array of CMDs and executed them. * end_CMD-terminated array of CMDs and executed them.
@ -1898,31 +1872,6 @@ TALER_TESTING_cmd_batch_set_current (const struct TALER_TESTING_Command *cmd,
unsigned int new_ip); unsigned int new_ip);
/**
* Make a serialize-keys CMD.
*
* @param label CMD label
* @return the CMD.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_serialize_keys (const char *label);
/**
* Make a connect-with-state CMD. This command
* will use a serialized key state to reconnect
* to the exchange.
*
* @param label command label
* @param state_reference label of a CMD offering
* a serialized key state.
* @return the CMD.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_connect_with_state (const char *label,
const char *state_reference);
/** /**
* Make the "insert-deposit" CMD. * Make the "insert-deposit" CMD.
* *
@ -2697,7 +2646,6 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
op (bank_auth_data, const struct TALER_BANK_AuthenticationData) \ op (bank_auth_data, const struct TALER_BANK_AuthenticationData) \
op (contract_terms, const json_t) \ op (contract_terms, const json_t) \
op (wire_details, const json_t) \ op (wire_details, const json_t) \
op (exchange_keys, const json_t) \
op (exchange_url, const char) \ op (exchange_url, const char) \
op (auditor_url, const char) \ op (auditor_url, const char) \
op (exchange_bank_account_url, const char) \ op (exchange_bank_account_url, const char) \

View File

@ -279,6 +279,11 @@ parse_denomination_group (void *cls,
&emsg, &emsg,
&eline)) &eline))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to parse %s at %u: %s\n",
spec[eline].field,
eline,
emsg);
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }

View File

@ -69,6 +69,13 @@
*/ */
#define DEFAULT_EXPIRATION GNUNET_TIME_UNIT_HOURS #define DEFAULT_EXPIRATION GNUNET_TIME_UNIT_HOURS
/**
* If the "Expire" cache control header is missing, for
* how long do we assume the reply to be valid at least?
*/
#define MINIMUM_EXPIRATION GNUNET_TIME_relative_multiply ( \
GNUNET_TIME_UNIT_MINUTES, 2)
/** /**
* Handle for a GET /keys request. * Handle for a GET /keys request.
@ -527,7 +534,6 @@ decode_keys_json (const json_t *resp_obj,
const json_t *denominations_by_group; const json_t *denominations_by_group;
const json_t *auditors_array; const json_t *auditors_array;
const json_t *recoup_array = NULL; const json_t *recoup_array = NULL;
struct TALER_MasterSignatureP extensions_sig = {0};
const json_t *manifests = NULL; const json_t *manifests = NULL;
bool no_extensions = false; bool no_extensions = false;
bool no_signature = false; bool no_signature = false;
@ -643,7 +649,7 @@ decode_keys_json (const json_t *resp_obj,
GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ( GNUNET_JSON_spec_fixed_auto (
"extensions_sig", "extensions_sig",
&extensions_sig), &key_data->extensions_sig),
&no_signature), &no_signature),
GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_array_const ( GNUNET_JSON_spec_array_const (
@ -659,6 +665,8 @@ decode_keys_json (const json_t *resp_obj,
NULL, NULL)); NULL, NULL));
key_data->currency = GNUNET_strdup (currency); key_data->currency = GNUNET_strdup (currency);
key_data->asset_type = GNUNET_strdup (asset_type); key_data->asset_type = GNUNET_strdup (asset_type);
if (! no_extensions)
key_data->extensions = json_incref ((json_t *) manifests);
} }
/* parse the global fees */ /* parse the global fees */
@ -743,7 +751,7 @@ decode_keys_json (const json_t *resp_obj,
EXITIF (GNUNET_OK != EXITIF (GNUNET_OK !=
TALER_extensions_verify_manifests_signature ( TALER_extensions_verify_manifests_signature (
manifests, manifests,
&extensions_sig, &key_data->extensions_sig,
&key_data->master_pub)); &key_data->master_pub));
/* Parse and set the the configuration of the extensions accordingly */ /* Parse and set the the configuration of the extensions accordingly */
@ -819,7 +827,7 @@ decode_keys_json (const json_t *resp_obj,
/* Build the running xor of the SHA512-hash of the public keys */ /* Build the running xor of the SHA512-hash of the public keys */
{ {
struct TALER_DenominationHashP hc = {0}; struct TALER_DenominationHashP hc;
TALER_denom_pub_hash (&dk.key, TALER_denom_pub_hash (&dk.key,
&hc); &hc);
@ -1109,6 +1117,20 @@ keys_completed_cb (void *cls,
break; break;
} }
kd->rc = 1; kd->rc = 1;
kd->key_data_expiration = gkh->expire;
if (GNUNET_TIME_relative_cmp (
GNUNET_TIME_absolute_get_remaining (gkh->expire.abs_time),
<,
MINIMUM_EXPIRATION))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Exchange returned keys with expiration time below %s. Compensating.\n",
GNUNET_TIME_relative2s (MINIMUM_EXPIRATION,
true));
kd->key_data_expiration
= GNUNET_TIME_relative_to_timestamp (MINIMUM_EXPIRATION);
}
kresp.details.ok.keys = kd; kresp.details.ok.keys = kd;
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
@ -1529,6 +1551,7 @@ TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys)
GNUNET_array_grow (keys->auditors, GNUNET_array_grow (keys->auditors,
keys->auditors_size, keys->auditors_size,
0); 0);
json_decref (keys->extensions);
GNUNET_free (keys->wallet_balance_limit_without_kyc); GNUNET_free (keys->wallet_balance_limit_without_kyc);
GNUNET_free (keys->version); GNUNET_free (keys->version);
GNUNET_free (keys->currency); GNUNET_free (keys->currency);
@ -1550,8 +1573,8 @@ TALER_EXCHANGE_keys_from_json (const json_t *j)
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_uint32 ("version", GNUNET_JSON_spec_uint32 ("version",
&version), &version),
GNUNET_JSON_spec_array_const ("keys", GNUNET_JSON_spec_object_const ("keys",
&jkeys), &jkeys),
GNUNET_JSON_spec_string ("exchange_url", GNUNET_JSON_spec_string ("exchange_url",
&url), &url),
GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_mark_optional (
@ -1594,14 +1617,98 @@ TALER_EXCHANGE_keys_from_json (const json_t *j)
} }
/**
* Data we track per denomination group.
*/
struct GroupData
{
/**
* The json blob with the group meta-data and list of denominations
*/
json_t *json;
/**
* xor of all hashes of denominations in that group
*/
struct GNUNET_HashCode hash_xor;
/**
* Meta data for this group.
*/
struct TALER_DenominationGroup meta;
};
/**
* Add denomination group represented by @a value
* to list of denominations in @a cls. Also frees
* the @a value.
*
* @param[in,out] cls a `json_t *` with an array to build
* @param key unused
* @param value a `struct GroupData *`
* @return #GNUNET_OK (continue to iterate)
*/
static enum GNUNET_GenericReturnValue
add_grp (void *cls,
const struct GNUNET_HashCode *key,
void *value)
{
json_t *denominations_by_group = cls;
struct GroupData *gd = value;
const char *cipher;
json_t *ge;
bool age_restricted = gd->meta.age_mask.bits != 0;
(void) key;
switch (gd->meta.cipher)
{
case TALER_DENOMINATION_RSA:
cipher = age_restricted ? "RSA+age_restricted" : "RSA";
break;
case TALER_DENOMINATION_CS:
cipher = age_restricted ? "CS+age_restricted" : "CS";
break;
default:
GNUNET_assert (false);
}
ge = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("hash",
&gd->hash_xor),
GNUNET_JSON_pack_string ("cipher",
cipher),
GNUNET_JSON_pack_array_steal ("denoms",
gd->json),
TALER_JSON_PACK_DENOM_FEES ("fee",
&gd->meta.fees),
GNUNET_JSON_pack_allow_null (
age_restricted
? GNUNET_JSON_pack_uint64 ("age_mask",
gd->meta.age_mask.bits)
: GNUNET_JSON_pack_string ("dummy",
NULL)),
TALER_JSON_pack_amount ("value",
&gd->meta.value));
GNUNET_assert (0 ==
json_array_append_new (denominations_by_group,
ge));
GNUNET_free (gd);
return GNUNET_OK;
}
json_t * json_t *
TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
{ {
struct GNUNET_TIME_Timestamp now; struct GNUNET_TIME_Timestamp now;
json_t *keys; json_t *keys;
json_t *signkeys; json_t *signkeys;
json_t *denoms; json_t *denominations_by_group;
json_t *auditors; json_t *auditors;
json_t *recoup;
json_t *global_fees;
json_t *wblwk = NULL;
now = GNUNET_TIME_timestamp_get (); now = GNUNET_TIME_timestamp_get ();
signkeys = json_array (); signkeys = json_array ();
@ -1644,43 +1751,113 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
return NULL; return NULL;
} }
} }
denoms = json_array (); denominations_by_group = json_array ();
if (NULL == denoms) if (NULL == denominations_by_group)
{ {
GNUNET_break (0); GNUNET_break (0);
json_decref (signkeys); json_decref (signkeys);
return NULL; return NULL;
} }
for (unsigned int i = 0; i<kd->num_denom_keys; i++) // FIXME: construct denominations_by_group analogous
// to taler-exchange-httpd_keys!
{ {
const struct TALER_EXCHANGE_DenomPublicKey *dk = &kd->denom_keys[i]; struct GNUNET_CONTAINER_MultiHashMap *dbg;
json_t *denom;
if (GNUNET_TIME_timestamp_cmp (now, dbg = GNUNET_CONTAINER_multihashmap_create (128,
>, false);
dk->expire_deposit)) for (unsigned int i = 0; i<kd->num_denom_keys; i++)
continue; /* skip keys that have expired */ {
denom = GNUNET_JSON_PACK ( const struct TALER_EXCHANGE_DenomPublicKey *dk = &kd->denom_keys[i];
GNUNET_JSON_pack_timestamp ("stamp_expire_deposit", struct TALER_DenominationGroup meta = {
dk->expire_deposit), .cipher = dk->key.cipher,
GNUNET_JSON_pack_timestamp ("stamp_expire_withdraw", .value = dk->value,
dk->withdraw_valid_until), .fees = dk->fees,
GNUNET_JSON_pack_timestamp ("stamp_start", .age_mask = kd->age_mask
dk->valid_from), };
GNUNET_JSON_pack_timestamp ("stamp_expire_legal", struct GNUNET_HashCode key;
dk->expire_legal), struct GroupData *gd;
TALER_JSON_pack_amount ("value", json_t *denom;
&dk->value), struct GNUNET_JSON_PackSpec key_spec;
TALER_JSON_PACK_DENOM_FEES ("fee",
&dk->fees), if (GNUNET_TIME_timestamp_cmp (now,
GNUNET_JSON_pack_data_auto ("master_sig", >,
&dk->master_sig), dk->expire_deposit))
TALER_JSON_pack_denom_pub ("denom_pub", continue; /* skip keys that have expired */
&dk->key)); GNUNET_CRYPTO_hash (&meta,
GNUNET_assert (0 == sizeof(meta),
json_array_append_new (denoms, &key);
denom)); gd = GNUNET_CONTAINER_multihashmap_get (dbg,
&key);
if (NULL == gd)
{
gd = GNUNET_new (struct GroupData);
gd->meta = meta;
gd->json = json_array ();
GNUNET_assert (NULL != gd->json);
GNUNET_assert (
GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_put (dbg,
&key,
gd,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
/* Build the running xor of the SHA512-hash of the public keys */
}
{
struct TALER_DenominationHashP hc;
TALER_denom_pub_hash (&dk->key,
&hc);
GNUNET_CRYPTO_hash_xor (&hc.hash,
&gd->hash_xor,
&gd->hash_xor);
}
switch (meta.cipher)
{
case TALER_DENOMINATION_RSA:
key_spec =
GNUNET_JSON_pack_rsa_public_key (
"rsa_pub",
dk->key.details.rsa_public_key);
break;
case TALER_DENOMINATION_CS:
key_spec =
GNUNET_JSON_pack_data_varsize (
"cs_pub",
&dk->key.details.cs_public_key,
sizeof (dk->key.details.cs_public_key));
break;
default:
GNUNET_assert (false);
}
denom = GNUNET_JSON_PACK (
GNUNET_JSON_pack_timestamp ("stamp_expire_deposit",
dk->expire_deposit),
GNUNET_JSON_pack_timestamp ("stamp_expire_withdraw",
dk->withdraw_valid_until),
GNUNET_JSON_pack_timestamp ("stamp_start",
dk->valid_from),
GNUNET_JSON_pack_timestamp ("stamp_expire_legal",
dk->expire_legal),
TALER_JSON_pack_amount ("value",
&dk->value),
TALER_JSON_PACK_DENOM_FEES ("fee",
&dk->fees),
GNUNET_JSON_pack_data_auto ("master_sig",
&dk->master_sig),
key_spec
);
GNUNET_assert (0 ==
json_array_append_new (gd->json,
denom));
}
GNUNET_CONTAINER_multihashmap_iterate (dbg,
&add_grp,
denominations_by_group);
GNUNET_CONTAINER_multihashmap_destroy (dbg);
} }
auditors = json_array (); auditors = json_array ();
GNUNET_assert (NULL != auditors); GNUNET_assert (NULL != auditors);
for (unsigned int i = 0; i<kd->num_auditors; i++) for (unsigned int i = 0; i<kd->num_auditors; i++)
@ -1690,14 +1867,7 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
json_t *adenoms; json_t *adenoms;
adenoms = json_array (); adenoms = json_array ();
if (NULL == adenoms) GNUNET_assert (NULL != adenoms);
{
GNUNET_break (0);
json_decref (denoms);
json_decref (signkeys);
json_decref (auditors);
return NULL;
}
for (unsigned int j = 0; j<ai->num_denom_keys; j++) for (unsigned int j = 0; j<ai->num_denom_keys; j++)
{ {
const struct TALER_EXCHANGE_AuditorDenominationInfo *adi = const struct TALER_EXCHANGE_AuditorDenominationInfo *adi =
@ -1732,6 +1902,63 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
json_array_append_new (auditors, json_array_append_new (auditors,
a)); a));
} }
global_fees = json_array ();
GNUNET_assert (NULL != global_fees);
for (unsigned int i = 0; i<kd->num_global_fees; i++)
{
const struct TALER_EXCHANGE_GlobalFee *gf
= &kd->global_fees[i];
if (GNUNET_TIME_absolute_is_past (gf->end_date.abs_time))
continue;
GNUNET_assert (
0 ==
json_array_append_new (
global_fees,
GNUNET_JSON_PACK (
GNUNET_JSON_pack_timestamp ("start_date",
gf->start_date),
GNUNET_JSON_pack_timestamp ("end_date",
gf->end_date),
TALER_JSON_PACK_GLOBAL_FEES (&gf->fees),
GNUNET_JSON_pack_time_rel ("history_expiration",
gf->history_expiration),
GNUNET_JSON_pack_time_rel ("purse_timeout",
gf->purse_timeout),
GNUNET_JSON_pack_uint64 ("purse_account_limit",
gf->purse_account_limit),
GNUNET_JSON_pack_data_auto ("master_sig",
&gf->master_sig))));
}
recoup = json_array ();
GNUNET_assert (NULL != recoup);
for (unsigned int i = 0; i<kd->num_denom_keys; i++)
{
const struct TALER_EXCHANGE_DenomPublicKey *dk
= &kd->denom_keys[i];
if (! dk->revoked)
continue;
GNUNET_assert (0 ==
json_array_append_new (
recoup,
GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("h_denom_pub",
&dk->h_key))));
}
wblwk = json_array ();
GNUNET_assert (NULL != wblwk);
for (unsigned int i = 0; i<kd->wblwk_length; i++)
{
const struct TALER_Amount *a = &kd->wallet_balance_limit_without_kyc[i];
GNUNET_assert (0 ==
json_array_append_new (
wblwk,
TALER_JSON_from_amount (a)));
}
keys = GNUNET_JSON_PACK ( keys = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("version", GNUNET_JSON_pack_string ("version",
kd->version), kd->version),
@ -1745,12 +1972,33 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
kd->reserve_closing_delay), kd->reserve_closing_delay),
GNUNET_JSON_pack_timestamp ("list_issue_date", GNUNET_JSON_pack_timestamp ("list_issue_date",
kd->list_issue_date), kd->list_issue_date),
GNUNET_JSON_pack_array_steal ("global_fees",
global_fees),
GNUNET_JSON_pack_array_steal ("signkeys", GNUNET_JSON_pack_array_steal ("signkeys",
signkeys), signkeys),
GNUNET_JSON_pack_array_steal ("denoms", GNUNET_JSON_pack_array_steal ("denominations",
denoms), denominations_by_group),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_array_steal ("recoup",
recoup)),
GNUNET_JSON_pack_array_steal ("auditors", GNUNET_JSON_pack_array_steal ("auditors",
auditors)); auditors),
GNUNET_JSON_pack_bool ("tipping_allowed",
kd->tipping_allowed),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_object_incref ("extensions",
kd->extensions)),
GNUNET_JSON_pack_allow_null (
GNUNET_is_zero (&kd->extensions_sig)
? GNUNET_JSON_pack_string ("dummy",
NULL)
: GNUNET_JSON_pack_data_auto ("extensions_sig",
&kd->extensions_sig)),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_array_steal ("wallet_balance_limit_without_kyc",
wblwk))
);
return GNUNET_JSON_PACK ( return GNUNET_JSON_PACK (
GNUNET_JSON_pack_uint64 ("version", GNUNET_JSON_pack_uint64 ("version",
EXCHANGE_SERIALIZATION_FORMAT_VERSION), EXCHANGE_SERIALIZATION_FORMAT_VERSION),

View File

@ -126,10 +126,17 @@ mime_matches (const char *accept_pattern,
{ {
const char *da = strchr (accept_pattern, '/'); const char *da = strchr (accept_pattern, '/');
const char *dm = strchr (mime, '/'); const char *dm = strchr (mime, '/');
const char *end;
if ( (NULL == da) || if ( (NULL == da) ||
(NULL == dm) ) (NULL == dm) )
return (0 == strcmp ("*", accept_pattern)); return (0 == strcmp ("*", accept_pattern));
/* FIXME: eventually, we might want to parse the "q=$FLOAT"
part after the ';' and figure out which one is the
best/preferred match instead of returning a boolean... */
end = strchr (da, ';');
if (NULL == end)
end = &da[strlen (da)];
return return
( ( (1 == da - accept_pattern) && ( ( (1 == da - accept_pattern) &&
('*' == *accept_pattern) ) || ('*' == *accept_pattern) ) ||
@ -138,8 +145,9 @@ mime_matches (const char *accept_pattern,
mime, mime,
da - accept_pattern)) ) ) && da - accept_pattern)) ) ) &&
( (0 == strcmp (da, "/*")) || ( (0 == strcmp (da, "/*")) ||
(0 == strcasecmp (da, (0 == strncasecmp (da,
dm)) ); dm,
end - da)) );
} }
@ -150,9 +158,9 @@ TALER_MHD_xmime_matches (const char *accept_pattern,
char *ap = GNUNET_strdup (accept_pattern); char *ap = GNUNET_strdup (accept_pattern);
char *sptr; char *sptr;
for (const char *tok = strtok_r (ap, ";", &sptr); for (const char *tok = strtok_r (ap, ",", &sptr);
NULL != tok; NULL != tok;
tok = strtok_r (NULL, ";", &sptr)) tok = strtok_r (NULL, ",", &sptr))
{ {
if (mime_matches (tok, if (mime_matches (tok,
mime)) mime))

View File

@ -59,9 +59,7 @@ libtalertesting_la_SOURCES = \
testing_api_cmd_batch_withdraw.c \ testing_api_cmd_batch_withdraw.c \
testing_api_cmd_check_aml_decision.c \ testing_api_cmd_check_aml_decision.c \
testing_api_cmd_check_aml_decisions.c \ testing_api_cmd_check_aml_decisions.c \
testing_api_cmd_check_keys.c \
testing_api_cmd_common.c \ testing_api_cmd_common.c \
testing_api_cmd_connect_with_state.c \
testing_api_cmd_contract_get.c \ testing_api_cmd_contract_get.c \
testing_api_cmd_deposit.c \ testing_api_cmd_deposit.c \
testing_api_cmd_deposits_get.c \ testing_api_cmd_deposits_get.c \
@ -106,7 +104,6 @@ libtalertesting_la_SOURCES = \
testing_api_cmd_revoke_denom_key.c \ testing_api_cmd_revoke_denom_key.c \
testing_api_cmd_revoke_sign_key.c \ testing_api_cmd_revoke_sign_key.c \
testing_api_cmd_run_fakebank.c \ testing_api_cmd_run_fakebank.c \
testing_api_cmd_serialize_keys.c \
testing_api_cmd_set_officer.c \ testing_api_cmd_set_officer.c \
testing_api_cmd_set_wire_fee.c \ testing_api_cmd_set_wire_fee.c \
testing_api_cmd_signal.c \ testing_api_cmd_signal.c \

View File

@ -653,12 +653,12 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_get_auditor ("get-auditor", TALER_TESTING_cmd_get_auditor ("get-auditor",
cred.cfg, cred.cfg,
true), true),
// FIXME: TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_exec_auditor_offline ("auditor-offline", TALER_TESTING_cmd_exec_auditor_offline ("auditor-offline",
config_file), config_file),
CMD_RUN_AUDITOR ("virgin-auditor"), CMD_RUN_AUDITOR ("virgin-auditor"),

View File

@ -1235,9 +1235,9 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
// FIXME: TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_batch ("wire", TALER_TESTING_cmd_batch ("wire",
wire), wire),
TALER_TESTING_cmd_batch ("withdraw", TALER_TESTING_cmd_batch ("withdraw",

View File

@ -21,7 +21,7 @@ CONFIG = "postgres:///talercheck"
HTTP_PORT = 8082 HTTP_PORT = 8082
[exchange] [exchange]
TERMS_ETAG = 0 TERMS_ETAG = tos
PRIVACY_ETAG = 0 PRIVACY_ETAG = 0
AML_THRESHOLD = EUR:1000000 AML_THRESHOLD = EUR:1000000
PORT = 8081 PORT = 8081

View File

@ -65,22 +65,21 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
// FIXME: TALER_TESTING_cmd_check_keys_pull_all_keys ("initial-/keys"),
TALER_TESTING_cmd_sleep ("sleep", TALER_TESTING_cmd_sleep ("sleep",
6 /* seconds */), 6 /* seconds */),
TALER_TESTING_cmd_check_keys ("check-keys-1"), TALER_TESTING_cmd_get_exchange ("get-exchange-1",
TALER_TESTING_cmd_check_keys_with_last_denom ("check-keys-2", cred.cfg,
"check-keys-1"), "get-exchange",
TALER_TESTING_cmd_serialize_keys ("serialize-keys"), true,
TALER_TESTING_cmd_connect_with_state ("reconnect-with-state", true),
"serialize-keys"), TALER_TESTING_cmd_get_exchange ("get-exchange-2",
/** cred.cfg,
* Make sure we have the same keys situation as "get-exchange-1",
* it was before the serialization. true,
*/ true),
TALER_TESTING_cmd_check_keys ("check-keys-after-deserialization"),
/** /**
* Use one of the deserialized keys. * Use one of the deserialized keys.
*/ */

View File

@ -69,13 +69,19 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true,
true),
TALER_TESTING_cmd_get_exchange ("get-exchange-1",
cred.cfg,
"get-exchange",
true,
true),
TALER_TESTING_cmd_get_exchange ("get-exchange-2",
cred.cfg,
NULL,
true, true,
true), true),
// FIXME: TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_check_keys ("first-download"),
/* Causes GET /keys?last_denom_issue=0 */
TALER_TESTING_cmd_check_keys_with_last_denom ("second-download",
"zero"),
TALER_TESTING_cmd_end () TALER_TESTING_cmd_end ()
}; };

View File

@ -67,20 +67,9 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
#if 0
TALER_TESTING_cmd_auditor_add ("add-auditor-OK",
MHD_HTTP_NO_CONTENT,
false),
TALER_TESTING_cmd_wire_add ("add-wire-account",
"payto://x-taler-bank/localhost/2?receiver-name=2",
MHD_HTTP_NO_CONTENT,
false),
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
config_file),
#endif
// FIXME: TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
/** /**
* Fill reserve with EUR:10.02, as withdraw fee is 1 ct per * Fill reserve with EUR:10.02, as withdraw fee is 1 ct per
* config. * config.

View File

@ -255,6 +255,7 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_batch ( TALER_TESTING_cmd_batch (

View File

@ -59,6 +59,7 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_get_auditor ("get-auditor", TALER_TESTING_cmd_get_auditor ("get-auditor",
@ -145,7 +146,16 @@ run (void *cls,
false), false),
TALER_TESTING_cmd_exec_offline_sign_keys ("download-future-keys", TALER_TESTING_cmd_exec_offline_sign_keys ("download-future-keys",
config_file), config_file),
// FIXME: TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"), TALER_TESTING_cmd_get_exchange ("get-exchange-1",
cred.cfg,
"get-exchange",
true,
true),
TALER_TESTING_cmd_get_exchange ("get-exchange-2",
cred.cfg,
NULL,
true,
true),
TALER_TESTING_cmd_end () TALER_TESTING_cmd_end ()
}; };

View File

@ -504,9 +504,9 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
// FIXME: TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_batch ("withdraw", TALER_TESTING_cmd_batch ("withdraw",
withdraw), withdraw),
TALER_TESTING_cmd_batch ("push", TALER_TESTING_cmd_batch ("push",

View File

@ -523,9 +523,9 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
// FIXME: TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_batch ("withdraw", TALER_TESTING_cmd_batch ("withdraw",
withdraw), withdraw),
TALER_TESTING_cmd_batch ("spend", TALER_TESTING_cmd_batch ("spend",

View File

@ -87,9 +87,9 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
// FIXME: TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-on-start"), TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-on-start"),
CMD_EXEC_AGGREGATOR ("run-aggregator-on-empty"), CMD_EXEC_AGGREGATOR ("run-aggregator-on-empty"),
TALER_TESTING_cmd_exec_wirewatch ("run-wirewatch-on-empty", TALER_TESTING_cmd_exec_wirewatch ("run-wirewatch-on-empty",

View File

@ -1,203 +0,0 @@
/*
This file is part of TALER
(C) 2018, 2020, 2021 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 testing/testing_api_cmd_check_keys.c
* @brief Implementation of "check keys" test command.
* @author Marcello Stanisci
* @author Christian Grothoff
*/
#include "platform.h"
#include "taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
#include "taler_testing_lib.h"
// FIXME: duplicated with testing_api_cmd_connect_with_state
// FIXME: this is now duplicated with testing_api_cmd_get_exchange!
/**
* State for a "check keys" CMD.
*/
struct CheckKeysState
{
/**
* Label of a command to use to derive the "last_denom_issue" date to use.
* FIXME: actually use this!
*/
const char *last_denom_date_ref;
/**
* Our interpreter state.
*/
struct TALER_TESTING_Interpreter *is;
/**
* Our get keys operation.
*/
struct TALER_EXCHANGE_GetKeysHandle *gkh;
/**
* Last denomination date we received when doing this request.
*/
struct GNUNET_TIME_Timestamp my_denom_date;
};
/**
* Function called with information about who is auditing
* a particular exchange and what keys the exchange is using.
*
* @param cls closure
* @param kr response from /keys
*/
static void
keys_cb (void *cls,
const struct TALER_EXCHANGE_KeysResponse *kr,
struct TALER_EXCHANGE_Keys *keys)
{
struct CheckKeysState *cks = cls;
cks->gkh = NULL;
if (MHD_HTTP_OK != kr->hr.http_status)
{
TALER_TESTING_unexpected_status (cks->is,
kr->hr.http_status,
MHD_HTTP_OK);
return;
}
cks->my_denom_date = kr->details.ok.keys->last_denom_issue_date;
/* FIXME: expose keys (and exchange_url) via trait! */
TALER_EXCHANGE_keys_decref (keys);
TALER_TESTING_interpreter_next (cks->is);
}
/**
* Run the "check keys" command.
*
* @param cls closure.
* @param cmd the command currently being executed.
* @param is the interpreter state.
*/
static void
check_keys_run (void *cls,
const struct TALER_TESTING_Command *cmd,
struct TALER_TESTING_Interpreter *is)
{
struct CheckKeysState *cks = cls;
const char *exchange_url
= TALER_TESTING_get_exchange_url (is);
cks->is = is;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Triggering GET /keys, cmd `%s'\n",
cmd->label);
cks->gkh = TALER_EXCHANGE_get_keys (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
NULL, /* FIXME: get form last_denom_date_ref! */
&keys_cb,
cks);
}
/**
* Cleanup the state.
*
* @param cls closure.
* @param cmd the command which is being cleaned up.
*/
static void
check_keys_cleanup (void *cls,
const struct TALER_TESTING_Command *cmd)
{
struct CheckKeysState *cks = cls;
(void) cmd;
if (NULL != cks->gkh)
{
TALER_EXCHANGE_get_keys_cancel (cks->gkh);
cks->gkh = NULL;
}
GNUNET_free (cks);
}
/**
* Offer internal data to a "check_keys" CMD state to other
* commands.
*
* @param cls closure
* @param[out] ret result (could be anything)
* @param trait name of the trait
* @param index index number of the object to offer.
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
check_keys_traits (void *cls,
const void **ret,
const char *trait,
unsigned int index)
{
struct CheckKeysState *cks = cls;
struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_timestamp (0,
&cks->my_denom_date),
TALER_TESTING_trait_end ()
};
return TALER_TESTING_get_trait (traits,
ret,
trait,
index);
}
struct TALER_TESTING_Command
TALER_TESTING_cmd_check_keys (const char *label)
{
return TALER_TESTING_cmd_check_keys_with_last_denom (label,
NULL);
}
struct TALER_TESTING_Command
TALER_TESTING_cmd_check_keys_with_last_denom (
const char *label,
const char *last_denom_date_ref)
{
struct CheckKeysState *cks;
cks = GNUNET_new (struct CheckKeysState);
cks->last_denom_date_ref = last_denom_date_ref;
{
struct TALER_TESTING_Command cmd = {
.cls = cks,
.label = label,
.run = &check_keys_run,
.cleanup = &check_keys_cleanup,
.traits = &check_keys_traits
};
return cmd;
}
}
/* end of testing_api_cmd_check_keys.c */

View File

@ -1,208 +0,0 @@
/*
This file is part of TALER
(C) 2018-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3, or
(at your option) any later version.
TALER is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with TALER; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>
*/
/**
* @file testing/testing_api_cmd_connect_with_state.c
* @brief Lets tests use the keys deserialization API.
* @author Marcello Stanisci
*/
#include "platform.h"
#include <jansson.h>
#include "taler_testing_lib.h"
// FIXME: this is now duplicated with testing_api_cmd_check_keys!
// FIXME: this is now duplicated with testing_api_cmd_get_exchange!
/**
* Internal state for a connect-with-state CMD.
*/
struct ConnectWithStateState
{
/**
* Reference to a CMD that offers a serialized key-state
* that will be used in the reconnection.
*/
const char *state_reference;
/**
* Interpreter state.
*/
struct TALER_TESTING_Interpreter *is;
/**
* New exchange handle.
*/
struct TALER_EXCHANGE_GetKeysHandle *exchange;
/**
* Keys handle.
*/
struct TALER_EXCHANGE_Keys *keys;
};
static void
cert_cb (void *cls,
const struct TALER_EXCHANGE_KeysResponse *kr,
struct TALER_EXCHANGE_Keys *keys)
{
struct ConnectWithStateState *cwss = cls;
struct TALER_TESTING_Interpreter *is = cwss->is;
const struct TALER_EXCHANGE_HttpResponse *hr = &kr->hr;
cwss->exchange = NULL;
switch (hr->http_status)
{
case MHD_HTTP_OK:
/* dealt with below */
break;
default:
GNUNET_break (0);
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Got failure response %u/%d for /keys!\n",
hr->http_status,
(int) hr->ec);
TALER_TESTING_interpreter_fail (is);
return;
}
cwss->keys = keys;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Got %d DK from /keys\n",
kr->details.ok.keys->num_denom_keys);
TALER_TESTING_interpreter_next (is);
}
/**
* Run the command.
*
* @param cls closure.
* @param cmd the command to execute.
* @param is the interpreter state.
*/
static void
connect_with_state_run (void *cls,
const struct TALER_TESTING_Command *cmd,
struct TALER_TESTING_Interpreter *is)
{
struct ConnectWithStateState *cwss = cls;
const struct TALER_TESTING_Command *state_cmd;
const json_t *serialized_keys;
const char *exchange_url;
cwss->is = is;
state_cmd = TALER_TESTING_interpreter_lookup_command (is,
cwss->state_reference);
if (NULL == state_cmd)
{
/* Command providing serialized keys not found. */
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_exchange_keys (state_cmd,
&serialized_keys));
GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_exchange_url (state_cmd,
&exchange_url));
cwss->exchange
= TALER_EXCHANGE_get_keys (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
TALER_EXCHANGE_keys_from_json (serialized_keys),
&cert_cb,
cwss);
}
/**
* Offer exchange connection as trait.
*
* @param cls closure.
* @param[out] ret result.
* @param trait name of the trait.
* @param index index number of the object to offer.
* @return #GNUNET_OK on success.
*/
static enum GNUNET_GenericReturnValue
connect_with_state_traits (void *cls,
const void **ret,
const char *trait,
unsigned int index)
{
struct ConnectWithStateState *cwss = cls;
struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_keys (cwss->keys),
// FIXME: also expose exchange_url as trait
TALER_TESTING_trait_end ()
};
return TALER_TESTING_get_trait (traits,
ret,
trait,
index);
}
/**
* Cleanup the state of a "connect with state" CMD. Just
* a placeholder to avoid jumping on an invalid address.
*
* @param cls closure.
* @param cmd the command which is being cleaned up.
*/
static void
connect_with_state_cleanup (void *cls,
const struct TALER_TESTING_Command *cmd)
{
struct ConnectWithStateState *cwss = cls;
TALER_EXCHANGE_keys_decref (cwss->keys);
cwss->keys = NULL;
if (NULL != cwss->exchange)
{
TALER_EXCHANGE_get_keys_cancel (cwss->exchange);
cwss->exchange = NULL;
}
GNUNET_free (cwss);
}
struct TALER_TESTING_Command
TALER_TESTING_cmd_connect_with_state (const char *label,
const char *state_reference)
{
struct ConnectWithStateState *cwss;
cwss = GNUNET_new (struct ConnectWithStateState);
cwss->state_reference = state_reference;
{
struct TALER_TESTING_Command cmd = {
.cls = cwss,
.label = label,
.run = connect_with_state_run,
.cleanup = connect_with_state_cleanup,
.traits = connect_with_state_traits
};
return cmd;
}
}

View File

@ -63,6 +63,17 @@ struct GetExchangeState
*/ */
char *master_priv_file; char *master_priv_file;
/**
* Label of a command to use to obtain existing
* keys.
*/
const char *last_keys_ref;
/**
* Last denomination date we received when doing this request.
*/
struct GNUNET_TIME_Timestamp my_denom_date;
/** /**
* Are we waiting for /keys before continuing? * Are we waiting for /keys before continuing?
*/ */
@ -70,6 +81,14 @@ struct GetExchangeState
}; };
/**
* Function called with information about who is auditing
* a particular exchange and what keys the exchange is using.
*
* @param cls closure
* @param kr response from /keys
* @param[in] keys the keys of the exchange
*/
static void static void
cert_cb (void *cls, cert_cb (void *cls,
const struct TALER_EXCHANGE_KeysResponse *kr, const struct TALER_EXCHANGE_KeysResponse *kr,
@ -90,6 +109,7 @@ cert_cb (void *cls,
TALER_TESTING_interpreter_next (is); TALER_TESTING_interpreter_next (is);
return; return;
} }
ges->my_denom_date = kr->details.ok.keys->last_denom_issue_date;
return; return;
default: default:
GNUNET_break (0); GNUNET_break (0);
@ -120,6 +140,7 @@ get_exchange_run (void *cls,
struct TALER_TESTING_Interpreter *is) struct TALER_TESTING_Interpreter *is)
{ {
struct GetExchangeState *ges = cls; struct GetExchangeState *ges = cls;
struct TALER_EXCHANGE_Keys *xkeys = NULL;
(void) cmd; (void) cmd;
if (NULL == ges->exchange_url) if (NULL == ges->exchange_url)
@ -128,6 +149,72 @@ get_exchange_run (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
if (NULL != ges->last_keys_ref)
{
const struct TALER_TESTING_Command *state_cmd;
struct TALER_EXCHANGE_Keys *old_keys;
const char *exchange_url;
json_t *s_keys;
state_cmd
= TALER_TESTING_interpreter_lookup_command (is,
ges->last_keys_ref);
if (NULL == state_cmd)
{
/* Command providing serialized keys not found. */
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
if (GNUNET_OK !=
TALER_TESTING_get_trait_keys (state_cmd,
&old_keys))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
if (NULL == old_keys)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
if (GNUNET_OK !=
TALER_TESTING_get_trait_exchange_url (state_cmd,
&exchange_url))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
if (0 != strcmp (exchange_url,
ges->exchange_url))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
s_keys = TALER_EXCHANGE_keys_to_json (old_keys);
if (NULL == s_keys)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
xkeys = TALER_EXCHANGE_keys_from_json (s_keys);
if (NULL == xkeys)
{
GNUNET_break (0);
json_dumpf (s_keys,
stderr,
JSON_INDENT (2));
json_decref (s_keys);
TALER_TESTING_interpreter_fail (is);
return;
}
json_decref (s_keys);
}
if (NULL != ges->master_priv_file) if (NULL != ges->master_priv_file)
{ {
if (GNUNET_SYSERR == if (GNUNET_SYSERR ==
@ -136,6 +223,7 @@ get_exchange_run (void *cls,
&ges->master_priv.eddsa_priv)) &ges->master_priv.eddsa_priv))
{ {
GNUNET_break (0); GNUNET_break (0);
TALER_EXCHANGE_keys_decref (xkeys);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
@ -144,9 +232,10 @@ get_exchange_run (void *cls,
ges->exchange ges->exchange
= TALER_EXCHANGE_get_keys (TALER_TESTING_interpreter_get_context (is), = TALER_EXCHANGE_get_keys (TALER_TESTING_interpreter_get_context (is),
ges->exchange_url, ges->exchange_url,
NULL, xkeys,
&cert_cb, &cert_cb,
ges); ges);
TALER_EXCHANGE_keys_decref (xkeys);
if (NULL == ges->exchange) if (NULL == ges->exchange)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -208,6 +297,8 @@ get_exchange_traits (void *cls,
TALER_TESTING_make_trait_master_pub (&ges->keys->master_pub), TALER_TESTING_make_trait_master_pub (&ges->keys->master_pub),
TALER_TESTING_make_trait_keys (ges->keys), TALER_TESTING_make_trait_keys (ges->keys),
TALER_TESTING_make_trait_exchange_url (ges->exchange_url), TALER_TESTING_make_trait_exchange_url (ges->exchange_url),
TALER_TESTING_make_trait_timestamp (0,
&ges->my_denom_date),
TALER_TESTING_trait_end () TALER_TESTING_trait_end ()
}; };
@ -221,6 +312,8 @@ get_exchange_traits (void *cls,
struct TALER_TESTING_Trait traits[] = { struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_master_priv (&ges->master_priv), TALER_TESTING_make_trait_master_priv (&ges->master_priv),
TALER_TESTING_make_trait_exchange_url (ges->exchange_url), TALER_TESTING_make_trait_exchange_url (ges->exchange_url),
TALER_TESTING_make_trait_timestamp (0,
&ges->my_denom_date),
TALER_TESTING_trait_end () TALER_TESTING_trait_end ()
}; };
@ -291,6 +384,7 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_get_exchange ( TALER_TESTING_cmd_get_exchange (
const char *label, const char *label,
const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *last_keys_ref,
bool wait_for_keys, bool wait_for_keys,
bool load_private_key) bool load_private_key)
{ {
@ -298,6 +392,7 @@ TALER_TESTING_cmd_get_exchange (
ges = GNUNET_new (struct GetExchangeState); ges = GNUNET_new (struct GetExchangeState);
ges->exchange_url = get_exchange_base_url (cfg); ges->exchange_url = get_exchange_base_url (cfg);
ges->last_keys_ref = last_keys_ref;
if (load_private_key) if (load_private_key)
ges->master_priv_file = get_exchange_master_priv_file (cfg); ges->master_priv_file = get_exchange_master_priv_file (cfg);
ges->wait_for_keys = wait_for_keys; ges->wait_for_keys = wait_for_keys;

View File

@ -197,6 +197,7 @@ TALER_TESTING_cmd_run_fakebank (
GNUNET_free (exchange_xtalerbank_account); GNUNET_free (exchange_xtalerbank_account);
GNUNET_free (exchange_payto_uri); GNUNET_free (exchange_payto_uri);
} }
GNUNET_free (exchange_payto_uri);
rfs->ba.method = TALER_BANK_AUTH_NONE; rfs->ba.method = TALER_BANK_AUTH_NONE;
{ {
struct TALER_TESTING_Command cmd = { struct TALER_TESTING_Command cmd = {

View File

@ -1,144 +0,0 @@
/*
This file is part of TALER
(C) 2018-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3, or
(at your option) any later version.
TALER is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with TALER; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>
*/
/**
* @file testing/testing_api_cmd_serialize_keys.c
* @brief Lets tests use the keys serialization API.
* @author Marcello Stanisci
*/
#include "platform.h"
#include <jansson.h>
#include "taler_testing_lib.h"
/**
* Internal state for a serialize-keys CMD.
*/
struct SerializeKeysState
{
/**
* Serialized keys.
*/
json_t *keys;
/**
* Exchange URL. Needed because the exchange gets disconnected
* from, after keys serialization. This value is then needed by
* subsequent commands that have to reconnect to the exchange.
*/
char *exchange_url;
};
/**
* Run the command.
*
* @param cls closure.
* @param cmd the command to execute.
* @param is the interpreter state.
*/
static void
serialize_keys_run (void *cls,
const struct TALER_TESTING_Command *cmd,
struct TALER_TESTING_Interpreter *is)
{
struct SerializeKeysState *sks = cls;
struct TALER_EXCHANGE_Keys *keys
= TALER_TESTING_get_keys (is);
if (NULL == keys)
return;
sks->keys = TALER_EXCHANGE_keys_to_json (keys);
if (NULL == sks->keys)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
}
sks->exchange_url
= GNUNET_strdup (
TALER_TESTING_get_exchange_url (is));
TALER_TESTING_interpreter_next (is);
}
/**
* Cleanup the state of a "serialize keys" CMD.
*
* @param cls closure.
* @param cmd the command which is being cleaned up.
*/
static void
serialize_keys_cleanup (void *cls,
const struct TALER_TESTING_Command *cmd)
{
struct SerializeKeysState *sks = cls;
if (NULL != sks->keys)
json_decref (sks->keys);
GNUNET_free (sks->exchange_url);
GNUNET_free (sks);
}
/**
* Offer serialized keys as trait.
*
* @param cls closure.
* @param[out] ret result.
* @param trait name of the trait.
* @param index index number of the object to offer.
* @return #GNUNET_OK on success.
*/
static enum GNUNET_GenericReturnValue
serialize_keys_traits (void *cls,
const void **ret,
const char *trait,
unsigned int index)
{
struct SerializeKeysState *sks = cls;
struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_exchange_keys (sks->keys),
TALER_TESTING_make_trait_exchange_url (sks->exchange_url),
TALER_TESTING_trait_end ()
};
return TALER_TESTING_get_trait (traits,
ret,
trait,
index);
}
struct TALER_TESTING_Command
TALER_TESTING_cmd_serialize_keys (const char *label)
{
struct SerializeKeysState *sks;
sks = GNUNET_new (struct SerializeKeysState);
{
struct TALER_TESTING_Command cmd = {
.cls = sks,
.label = label,
.run = serialize_keys_run,
.cleanup = serialize_keys_cleanup,
.traits = serialize_keys_traits
};
return cmd;
}
}