work on keys serialization/deserialization

This commit is contained in:
Christian Grothoff 2023-07-06 00:08:00 +02:00
parent 11ea6fcfce
commit c02d88c8e3
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
20 changed files with 443 additions and 708 deletions

View File

@ -2223,10 +2223,13 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
.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 */
GNUNET_CRYPTO_hash (&meta, sizeof(meta), &key);
GNUNET_CRYPTO_hash (&meta,
sizeof(meta),
&key);
group =
(struct groupData *) GNUNET_CONTAINER_multihashmap_get (
@ -2237,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 */
bool age_restricted = meta.age_mask.bits != 0;
char *cipher;
const char *cipher;
group = GNUNET_new (struct groupData);
memset (group, 0, sizeof(*group));
@ -2296,17 +2299,16 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
{
case TALER_DENOMINATION_RSA:
key_spec =
GNUNET_JSON_pack_rsa_public_key ("rsa_pub",
dk->denom_pub.details.
rsa_public_key);
GNUNET_JSON_pack_rsa_public_key (
"rsa_pub",
dk->denom_pub.details.rsa_public_key);
break;
case TALER_DENOMINATION_CS:
key_spec =
GNUNET_JSON_pack_data_varsize ("cs_pub",
&dk->denom_pub.details.
cs_public_key,
sizeof (dk->denom_pub.details.
cs_public_key));
GNUNET_JSON_pack_data_varsize (
"cs_pub",
&dk->denom_pub.details.cs_public_key,
sizeof (dk->denom_pub.details.cs_public_key));
break;
default:
GNUNET_assert (false);
@ -2546,9 +2548,9 @@ build_key_state (struct HelperState *hs,
ksh->helpers = hs;
}
ksh->denomkey_map = GNUNET_CONTAINER_multihashmap_create (1024,
GNUNET_YES);
true);
ksh->signkey_map = GNUNET_CONTAINER_multipeermap_create (32,
GNUNET_NO /* MUST be NO! */);
false /* MUST be false! */);
ksh->auditors = json_array ();
GNUNET_assert (NULL != ksh->auditors);
/* 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;
/**
* Signature over extension configuration data, if any.
*/
struct TALER_MasterSignatureP extensions_sig;
/**
* Array of the exchange's online signing keys.
*/
@ -259,6 +264,11 @@ struct TALER_EXCHANGE_Keys
*/
struct TALER_EXCHANGE_GlobalFee *global_fees;
/**
* Configuration data for extensions.
*/
json_t *extensions;
/**
* Supported Taler protocol version by the exchange.
* String in the format current:revision:age using the

View File

@ -623,6 +623,7 @@ TALER_TESTING_cmd_system_start (
*
* @param label command label
* @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 load_private_key obtain private key from file indicated in @a cfg
* @return the command.
@ -631,6 +632,7 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_get_exchange (
const char *label,
const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *last_keys_ref,
bool wait_for_keys,
bool load_private_key);
@ -1786,34 +1788,6 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_wait_service (const char *label,
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
* end_CMD-terminated array of CMDs and executed them.
@ -1872,31 +1846,6 @@ TALER_TESTING_cmd_batch_set_current (const struct TALER_TESTING_Command *cmd,
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.
*
@ -2671,7 +2620,6 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
op (bank_auth_data, const struct TALER_BANK_AuthenticationData) \
op (contract_terms, const json_t) \
op (wire_details, const json_t) \
op (exchange_keys, const json_t) \
op (exchange_url, const char) \
op (auditor_url, const char) \
op (exchange_bank_account_url, const char) \

View File

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

View File

@ -534,7 +534,6 @@ decode_keys_json (const json_t *resp_obj,
const json_t *denominations_by_group;
const json_t *auditors_array;
const json_t *recoup_array = NULL;
struct TALER_MasterSignatureP extensions_sig = {0};
const json_t *manifests = NULL;
bool no_extensions = false;
bool no_signature = false;
@ -650,7 +649,7 @@ decode_keys_json (const json_t *resp_obj,
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto (
"extensions_sig",
&extensions_sig),
&key_data->extensions_sig),
&no_signature),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_array_const (
@ -666,6 +665,8 @@ decode_keys_json (const json_t *resp_obj,
NULL, NULL));
key_data->currency = GNUNET_strdup (currency);
key_data->asset_type = GNUNET_strdup (asset_type);
if (! no_extensions)
key_data->extensions = json_incref ((json_t *) manifests);
}
/* parse the global fees */
@ -750,7 +751,7 @@ decode_keys_json (const json_t *resp_obj,
EXITIF (GNUNET_OK !=
TALER_extensions_verify_manifests_signature (
manifests,
&extensions_sig,
&key_data->extensions_sig,
&key_data->master_pub));
/* Parse and set the the configuration of the extensions accordingly */
@ -826,7 +827,7 @@ decode_keys_json (const json_t *resp_obj,
/* 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,
&hc);
@ -1550,6 +1551,7 @@ TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys)
GNUNET_array_grow (keys->auditors,
keys->auditors_size,
0);
json_decref (keys->extensions);
GNUNET_free (keys->wallet_balance_limit_without_kyc);
GNUNET_free (keys->version);
GNUNET_free (keys->currency);
@ -1571,8 +1573,8 @@ TALER_EXCHANGE_keys_from_json (const json_t *j)
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_uint32 ("version",
&version),
GNUNET_JSON_spec_array_const ("keys",
&jkeys),
GNUNET_JSON_spec_object_const ("keys",
&jkeys),
GNUNET_JSON_spec_string ("exchange_url",
&url),
GNUNET_JSON_spec_mark_optional (
@ -1615,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 *
TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
{
struct GNUNET_TIME_Timestamp now;
json_t *keys;
json_t *signkeys;
json_t *denoms;
json_t *denominations_by_group;
json_t *auditors;
json_t *recoup;
json_t *global_fees;
json_t *wblwk = NULL;
now = GNUNET_TIME_timestamp_get ();
signkeys = json_array ();
@ -1665,43 +1751,113 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
return NULL;
}
}
denoms = json_array ();
if (NULL == denoms)
denominations_by_group = json_array ();
if (NULL == denominations_by_group)
{
GNUNET_break (0);
json_decref (signkeys);
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];
json_t *denom;
struct GNUNET_CONTAINER_MultiHashMap *dbg;
if (GNUNET_TIME_timestamp_cmp (now,
>,
dk->expire_deposit))
continue; /* skip keys that have expired */
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),
TALER_JSON_pack_denom_pub ("denom_pub",
&dk->key));
GNUNET_assert (0 ==
json_array_append_new (denoms,
denom));
dbg = GNUNET_CONTAINER_multihashmap_create (128,
false);
for (unsigned int i = 0; i<kd->num_denom_keys; i++)
{
const struct TALER_EXCHANGE_DenomPublicKey *dk = &kd->denom_keys[i];
struct TALER_DenominationGroup meta = {
.cipher = dk->key.cipher,
.value = dk->value,
.fees = dk->fees,
.age_mask = kd->age_mask
};
struct GNUNET_HashCode key;
struct GroupData *gd;
json_t *denom;
struct GNUNET_JSON_PackSpec key_spec;
if (GNUNET_TIME_timestamp_cmp (now,
>,
dk->expire_deposit))
continue; /* skip keys that have expired */
GNUNET_CRYPTO_hash (&meta,
sizeof(meta),
&key);
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 ();
GNUNET_assert (NULL != auditors);
for (unsigned int i = 0; i<kd->num_auditors; i++)
@ -1711,14 +1867,7 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
json_t *adenoms;
adenoms = json_array ();
if (NULL == adenoms)
{
GNUNET_break (0);
json_decref (denoms);
json_decref (signkeys);
json_decref (auditors);
return NULL;
}
GNUNET_assert (NULL != adenoms);
for (unsigned int j = 0; j<ai->num_denom_keys; j++)
{
const struct TALER_EXCHANGE_AuditorDenominationInfo *adi =
@ -1753,6 +1902,63 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
json_array_append_new (auditors,
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 (
GNUNET_JSON_pack_string ("version",
kd->version),
@ -1766,12 +1972,33 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
kd->reserve_closing_delay),
GNUNET_JSON_pack_timestamp ("list_issue_date",
kd->list_issue_date),
GNUNET_JSON_pack_array_steal ("global_fees",
global_fees),
GNUNET_JSON_pack_array_steal ("signkeys",
signkeys),
GNUNET_JSON_pack_array_steal ("denoms",
denoms),
GNUNET_JSON_pack_array_steal ("denominations",
denominations_by_group),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_array_steal ("recoup",
recoup)),
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 (
GNUNET_JSON_pack_uint64 ("version",
EXCHANGE_SERIALIZATION_FORMAT_VERSION),

View File

@ -59,9 +59,7 @@ libtalertesting_la_SOURCES = \
testing_api_cmd_batch_withdraw.c \
testing_api_cmd_check_aml_decision.c \
testing_api_cmd_check_aml_decisions.c \
testing_api_cmd_check_keys.c \
testing_api_cmd_common.c \
testing_api_cmd_connect_with_state.c \
testing_api_cmd_contract_get.c \
testing_api_cmd_deposit.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_sign_key.c \
testing_api_cmd_run_fakebank.c \
testing_api_cmd_serialize_keys.c \
testing_api_cmd_set_officer.c \
testing_api_cmd_set_wire_fee.c \
testing_api_cmd_signal.c \

View File

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

View File

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

View File

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

View File

@ -69,13 +69,19 @@ run (void *cls,
NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange",
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),
// 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 ()
};

View File

@ -67,20 +67,9 @@ run (void *cls,
NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg,
NULL,
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
* config.

View File

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

View File

@ -59,6 +59,7 @@ run (void *cls,
NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg,
NULL,
true,
true),
TALER_TESTING_cmd_get_auditor ("get-auditor",
@ -145,7 +146,16 @@ run (void *cls,
false),
TALER_TESTING_cmd_exec_offline_sign_keys ("download-future-keys",
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 ()
};

View File

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

View File

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

View File

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

View File

@ -1,202 +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);
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;
/**
* 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?
*/
@ -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
cert_cb (void *cls,
const struct TALER_EXCHANGE_KeysResponse *kr,
@ -90,6 +109,7 @@ cert_cb (void *cls,
TALER_TESTING_interpreter_next (is);
return;
}
ges->my_denom_date = kr->details.ok.keys->last_denom_issue_date;
return;
default:
GNUNET_break (0);
@ -120,6 +140,7 @@ get_exchange_run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
struct GetExchangeState *ges = cls;
struct TALER_EXCHANGE_Keys *xkeys = NULL;
(void) cmd;
if (NULL == ges->exchange_url)
@ -128,6 +149,72 @@ get_exchange_run (void *cls,
TALER_TESTING_interpreter_fail (is);
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 (GNUNET_SYSERR ==
@ -136,6 +223,7 @@ get_exchange_run (void *cls,
&ges->master_priv.eddsa_priv))
{
GNUNET_break (0);
TALER_EXCHANGE_keys_decref (xkeys);
TALER_TESTING_interpreter_fail (is);
return;
}
@ -144,9 +232,10 @@ get_exchange_run (void *cls,
ges->exchange
= TALER_EXCHANGE_get_keys (TALER_TESTING_interpreter_get_context (is),
ges->exchange_url,
NULL,
xkeys,
&cert_cb,
ges);
TALER_EXCHANGE_keys_decref (xkeys);
if (NULL == ges->exchange)
{
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_keys (ges->keys),
TALER_TESTING_make_trait_exchange_url (ges->exchange_url),
TALER_TESTING_make_trait_timestamp (0,
&ges->my_denom_date),
TALER_TESTING_trait_end ()
};
@ -221,6 +312,8 @@ get_exchange_traits (void *cls,
struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_master_priv (&ges->master_priv),
TALER_TESTING_make_trait_exchange_url (ges->exchange_url),
TALER_TESTING_make_trait_timestamp (0,
&ges->my_denom_date),
TALER_TESTING_trait_end ()
};
@ -291,6 +384,7 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_get_exchange (
const char *label,
const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *last_keys_ref,
bool wait_for_keys,
bool load_private_key)
{
@ -298,6 +392,7 @@ TALER_TESTING_cmd_get_exchange (
ges = GNUNET_new (struct GetExchangeState);
ges->exchange_url = get_exchange_base_url (cfg);
ges->last_keys_ref = last_keys_ref;
if (load_private_key)
ges->master_priv_file = get_exchange_master_priv_file (cfg);
ges->wait_for_keys = wait_for_keys;

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;
}
}