summaryrefslogtreecommitdiff
path: root/src/exchange-tools/taler-exchange-offline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange-tools/taler-exchange-offline.c')
-rw-r--r--src/exchange-tools/taler-exchange-offline.c1251
1 files changed, 1077 insertions, 174 deletions
diff --git a/src/exchange-tools/taler-exchange-offline.c b/src/exchange-tools/taler-exchange-offline.c
index a8a25bd3c..1f10c55e3 100644
--- a/src/exchange-tools/taler-exchange-offline.c
+++ b/src/exchange-tools/taler-exchange-offline.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2020, 2021, 2022 Taler Systems SA
+ Copyright (C) 2020-2024 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
@@ -24,6 +24,8 @@
#include "taler_json_lib.h"
#include "taler_exchange_service.h"
#include "taler_extensions.h"
+#include <regex.h>
+
/**
* Name of the input for the 'sign' and 'show' operation.
@@ -113,6 +115,16 @@
#define OP_DRAIN_PROFITS "exchange-drain-profits-0"
/**
+ * Setup AML staff.
+ */
+#define OP_UPDATE_AML_STAFF "exchange-add-aml-staff-0"
+
+/**
+ * Setup partner exchange for wad transfers.
+ */
+#define OP_ADD_PARTNER "exchange-add-partner-0"
+
+/**
* Our private key, initialized in #load_offline_key().
*/
static struct TALER_MasterPrivateKeyP master_priv;
@@ -499,6 +511,62 @@ struct UploadExtensionsRequest
/**
+ * Data structure for AML staff requests.
+ */
+struct AmlStaffRequest
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct AmlStaffRequest *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct AmlStaffRequest *prev;
+
+ /**
+ * Operation handle.
+ */
+ struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *h;
+
+ /**
+ * Array index of the associated command.
+ */
+ size_t idx;
+};
+
+
+/**
+ * Data structure for partner add requests.
+ */
+struct PartnerAddRequest
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct PartnerAddRequest *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct PartnerAddRequest *prev;
+
+ /**
+ * Operation handle.
+ */
+ struct TALER_EXCHANGE_ManagementAddPartner *h;
+
+ /**
+ * Array index of the associated command.
+ */
+ size_t idx;
+};
+
+
+/**
* Next work item to perform.
*/
static struct GNUNET_SCHEDULER_Task *nxt;
@@ -508,6 +576,27 @@ static struct GNUNET_SCHEDULER_Task *nxt;
*/
static struct TALER_EXCHANGE_ManagementGetKeysHandle *mgkh;
+
+/**
+ * Active AML staff change requests.
+ */
+static struct AmlStaffRequest *asr_head;
+
+/**
+ * Active AML staff change requests.
+ */
+static struct AmlStaffRequest *asr_tail;
+
+/**
+ * Active partner add requests.
+ */
+static struct PartnerAddRequest *par_head;
+
+/**
+ * Active partner add requests.
+ */
+static struct PartnerAddRequest *par_tail;
+
/**
* Active denomiantion revocation requests.
*/
@@ -630,6 +719,36 @@ do_shutdown (void *cls)
(void) cls;
{
+ struct AmlStaffRequest *asr;
+
+ while (NULL != (asr = asr_head))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Aborting incomplete AML staff update #%u\n",
+ (unsigned int) asr->idx);
+ TALER_EXCHANGE_management_update_aml_officer_cancel (asr->h);
+ GNUNET_CONTAINER_DLL_remove (asr_head,
+ asr_tail,
+ asr);
+ GNUNET_free (asr);
+ }
+ }
+ {
+ struct PartnerAddRequest *par;
+
+ while (NULL != (par = par_head))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Aborting incomplete partner add request #%u\n",
+ (unsigned int) par->idx);
+ TALER_EXCHANGE_management_add_partner_cancel (par->h);
+ GNUNET_CONTAINER_DLL_remove (par_head,
+ par_tail,
+ par);
+ GNUNET_free (par);
+ }
+ }
+ {
struct DenomRevocationRequest *drr;
while (NULL != (drr = drr_head))
@@ -799,9 +918,10 @@ do_shutdown (void *cls)
if (NULL != out)
{
- json_dumpf (out,
- stdout,
- JSON_INDENT (2));
+ if (EXIT_SUCCESS == global_ret)
+ json_dumpf (out,
+ stdout,
+ JSON_INDENT (2));
json_decref (out);
out = NULL;
}
@@ -842,6 +962,8 @@ static void
test_shutdown (void)
{
if ( (NULL == drr_head) &&
+ (NULL == par_head) &&
+ (NULL == asr_head) &&
(NULL == srr_head) &&
(NULL == aar_head) &&
(NULL == adr_head) &&
@@ -1000,14 +1122,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)
{
@@ -1067,7 +1190,7 @@ upload_denom_revocation (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
drr = GNUNET_new (struct DenomRevocationRequest);
@@ -1089,14 +1212,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)
{
@@ -1156,7 +1280,7 @@ upload_signkey_revocation (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
srr = GNUNET_new (struct SignkeyRevocationRequest);
@@ -1178,13 +1302,15 @@ upload_signkey_revocation (const char *exchange_url,
* Function called with information about the post auditor add operation result.
*
* @param cls closure with a `struct AuditorAddRequest`
- * @param hr HTTP response data
+ * @param mer response data
*/
static void
-auditor_add_cb (void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr)
+auditor_add_cb (
+ void *cls,
+ const struct TALER_EXCHANGE_ManagementAuditorEnableResponse *mer)
{
struct AuditorAddRequest *aar = cls;
+ const struct TALER_EXCHANGE_HttpResponse *hr = &mer->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@@ -1225,7 +1351,7 @@ upload_auditor_add (const char *exchange_url,
const char *err_name;
unsigned int err_line;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("auditor_url",
+ TALER_JSON_spec_web_url ("auditor_url",
&auditor_url),
GNUNET_JSON_spec_string ("auditor_name",
&auditor_name),
@@ -1253,7 +1379,7 @@ upload_auditor_add (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
aar = GNUNET_new (struct AuditorAddRequest);
@@ -1278,13 +1404,15 @@ upload_auditor_add (const char *exchange_url,
* Function called with information about the post auditor del operation result.
*
* @param cls closure with a `struct AuditorDelRequest`
- * @param hr HTTP response data
+ * @param mdr response data
*/
static void
auditor_del_cb (void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr)
+ const struct
+ TALER_EXCHANGE_ManagementAuditorDisableResponse *mdr)
{
struct AuditorDelRequest *adr = cls;
+ const struct TALER_EXCHANGE_HttpResponse *hr = &mdr->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@@ -1347,7 +1475,7 @@ upload_auditor_del (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
adr = GNUNET_new (struct AuditorDelRequest);
@@ -1370,13 +1498,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)
{
@@ -1414,10 +1543,29 @@ 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;
+ const char *bank_label = NULL;
+ int64_t priority = 0;
+ const json_t *debit_restrictions;
+ const json_t *credit_restrictions;
unsigned int err_line;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("payto_uri",
- &payto_uri),
+ TALER_JSON_spec_payto_uri ("payto_uri",
+ &payto_uri),
+ GNUNET_JSON_spec_mark_optional (
+ TALER_JSON_spec_web_url ("conversion_url",
+ &conversion_url),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("bank_label",
+ &bank_label),
+ NULL),
+ GNUNET_JSON_spec_int64 ("priority",
+ &priority),
+ GNUNET_JSON_spec_array_const ("debit_restrictions",
+ &debit_restrictions),
+ GNUNET_JSON_spec_array_const ("credit_restrictions",
+ &credit_restrictions),
GNUNET_JSON_spec_timestamp ("validity_start",
&start_time),
GNUNET_JSON_spec_fixed_auto ("master_sig_add",
@@ -1442,7 +1590,7 @@ upload_wire_add (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
{
@@ -1455,7 +1603,7 @@ upload_wire_add (const char *exchange_url,
"payto:// URI `%s' is malformed\n",
payto_uri);
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
GNUNET_free (wire_method);
@@ -1469,7 +1617,7 @@ upload_wire_add (const char *exchange_url,
"payto URI is malformed: %s\n",
msg);
GNUNET_free (msg);
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -1480,9 +1628,14 @@ 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,
+ bank_label,
+ priority,
&wire_add_cb,
war);
GNUNET_CONTAINER_DLL_insert (war_head,
@@ -1495,13 +1648,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)
{
@@ -1540,8 +1694,8 @@ upload_wire_del (const char *exchange_url,
const char *err_name;
unsigned int err_line;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("payto_uri",
- &payto_uri),
+ TALER_JSON_spec_payto_uri ("payto_uri",
+ &payto_uri),
GNUNET_JSON_spec_timestamp ("validity_end",
&end_time),
GNUNET_JSON_spec_fixed_auto ("master_sig",
@@ -1564,7 +1718,7 @@ upload_wire_del (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
wdr = GNUNET_new (struct WireDelRequest);
@@ -1587,14 +1741,15 @@ upload_wire_del (const char *exchange_url,
* Function called with information about the post wire fee operation result.
*
* @param cls closure with a `struct WireFeeRequest`
- * @param hr HTTP response data
+ * @param swr response data
*/
static void
wire_fee_cb (
void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr)
+ const struct TALER_EXCHANGE_ManagementSetWireFeeResponse *swr)
{
struct WireFeeRequest *wfr = cls;
+ const struct TALER_EXCHANGE_HttpResponse *hr = &swr->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@@ -1667,7 +1822,7 @@ upload_wire_fee (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
wfr = GNUNET_new (struct WireFeeRequest);
@@ -1692,14 +1847,15 @@ upload_wire_fee (const char *exchange_url,
* Function called with information about the post global fee operation result.
*
* @param cls closure with a `struct WireFeeRequest`
- * @param hr HTTP response data
+ * @param gr response data
*/
static void
global_fee_cb (
void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr)
+ const struct TALER_EXCHANGE_ManagementSetGlobalFeeResponse *gr)
{
struct GlobalFeeRequest *gfr = cls;
+ const struct TALER_EXCHANGE_HttpResponse *hr = &gr->hr;
if (MHD_HTTP_NO_CONTENT != hr->http_status)
{
@@ -1781,7 +1937,7 @@ upload_global_fee (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
gfr = GNUNET_new (struct GlobalFeeRequest);
@@ -1808,14 +1964,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)
{
@@ -1866,8 +2023,8 @@ upload_drain (const char *exchange_url,
&date),
GNUNET_JSON_spec_string ("account_section",
&account_section),
- GNUNET_JSON_spec_string ("payto_uri",
- &payto_uri),
+ TALER_JSON_spec_payto_uri ("payto_uri",
+ &payto_uri),
GNUNET_JSON_spec_fixed_auto ("master_sig",
&master_sig),
GNUNET_JSON_spec_end ()
@@ -1888,7 +2045,7 @@ upload_drain (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
dpr = GNUNET_new (struct DrainProfitsRequest);
@@ -1914,14 +2071,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)
{
@@ -1957,13 +2115,13 @@ upload_keys (const char *exchange_url,
struct UploadKeysRequest *ukr;
const char *err_name;
unsigned int err_line;
- json_t *denom_sigs;
- json_t *signkey_sigs;
+ const json_t *denom_sigs;
+ const json_t *signkey_sigs;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("denom_sigs",
- &denom_sigs),
- GNUNET_JSON_spec_json ("signkey_sigs",
- &signkey_sigs),
+ GNUNET_JSON_spec_array_const ("denom_sigs",
+ &denom_sigs),
+ GNUNET_JSON_spec_array_const ("signkey_sigs",
+ &signkey_sigs),
GNUNET_JSON_spec_end ()
};
bool ok = true;
@@ -1982,7 +2140,7 @@ upload_keys (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
pkd.num_sign_sigs = json_array_size (signkey_sigs);
@@ -2075,11 +2233,10 @@ upload_keys (const char *exchange_url,
else
{
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
}
GNUNET_free (pkd.sign_sigs);
GNUNET_free (pkd.denom_sigs);
- GNUNET_JSON_parse_free (spec);
}
@@ -2087,14 +2244,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)
{
@@ -2126,13 +2284,13 @@ upload_extensions (const char *exchange_url,
size_t idx,
const json_t *value)
{
- json_t *extensions;
+ const json_t *extensions;
struct TALER_MasterSignatureP sig;
const char *err_name;
unsigned int err_line;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("extensions",
- &extensions),
+ GNUNET_JSON_spec_object_const ("extensions",
+ &extensions),
GNUNET_JSON_spec_fixed_auto ("extensions_sig",
&sig),
GNUNET_JSON_spec_end ()
@@ -2154,7 +2312,7 @@ upload_extensions (const char *exchange_url,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
@@ -2163,13 +2321,13 @@ upload_extensions (const char *exchange_url,
struct TALER_ExtensionManifestsHashP h_manifests;
if (GNUNET_OK !=
- TALER_JSON_extensions_manifests_hash (extensions, &h_manifests))
+ TALER_JSON_extensions_manifests_hash (extensions,
+ &h_manifests))
{
- GNUNET_JSON_parse_free (spec);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"couldn't hash extensions' manifests\n");
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
@@ -2182,11 +2340,10 @@ upload_extensions (const char *exchange_url,
&master_pub,
&sig))
{
- GNUNET_JSON_parse_free (spec);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"invalid signature for extensions\n");
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
}
@@ -2197,8 +2354,9 @@ upload_extensions (const char *exchange_url,
.extensions = extensions,
.extensions_sig = sig,
};
- struct UploadExtensionsRequest *uer = GNUNET_new (struct
- UploadExtensionsRequest);
+ struct UploadExtensionsRequest *uer
+ = GNUNET_new (struct UploadExtensionsRequest);
+
uer->idx = idx;
uer->h = TALER_EXCHANGE_management_post_extensions (
ctx,
@@ -2210,7 +2368,223 @@ upload_extensions (const char *exchange_url,
uer_tail,
uer);
}
- GNUNET_JSON_parse_free (spec);
+}
+
+
+/**
+ * Function called with information about the add partner operation.
+ *
+ * @param cls closure with a `struct PartnerAddRequest`
+ * @param apr response data
+ */
+static void
+add_partner_cb (
+ void *cls,
+ const struct TALER_EXCHANGE_ManagementAddPartnerResponse *apr)
+{
+ struct PartnerAddRequest *par = cls;
+ const struct TALER_EXCHANGE_HttpResponse *hr = &apr->hr;
+
+ if (MHD_HTTP_NO_CONTENT != hr->http_status)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Upload failed for command %u with status %u: %s (%s)\n",
+ (unsigned int) par->idx,
+ hr->http_status,
+ TALER_ErrorCode_get_hint (hr->ec),
+ hr->hint);
+ global_ret = EXIT_FAILURE;
+ }
+ GNUNET_CONTAINER_DLL_remove (par_head,
+ par_tail,
+ par);
+ GNUNET_free (par);
+ test_shutdown ();
+}
+
+
+/**
+ * Add partner action.
+ *
+ * @param exchange_url base URL of the exchange
+ * @param idx index of the operation we are performing (for logging)
+ * @param value arguments for add partner
+ */
+static void
+add_partner (const char *exchange_url,
+ size_t idx,
+ const json_t *value)
+{
+ struct TALER_MasterPublicKeyP partner_pub;
+ struct GNUNET_TIME_Timestamp start_date;
+ struct GNUNET_TIME_Timestamp end_date;
+ struct GNUNET_TIME_Relative wad_frequency;
+ struct TALER_Amount wad_fee;
+ const char *partner_base_url;
+ struct TALER_MasterSignatureP master_sig;
+ struct PartnerAddRequest *par;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto ("partner_pub",
+ &partner_pub),
+ TALER_JSON_spec_amount ("wad_fee",
+ currency,
+ &wad_fee),
+ GNUNET_JSON_spec_relative_time ("wad_frequency",
+ &wad_frequency),
+ GNUNET_JSON_spec_timestamp ("start_date",
+ &start_date),
+ GNUNET_JSON_spec_timestamp ("end_date",
+ &end_date),
+ TALER_JSON_spec_web_url ("partner_base_url",
+ &partner_base_url),
+ GNUNET_JSON_spec_fixed_auto ("master_sig",
+ &master_sig),
+ GNUNET_JSON_spec_end ()
+ };
+ const char *err_name;
+ unsigned int err_line;
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (value,
+ spec,
+ &err_name,
+ &err_line))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid input to add partner: %s#%u at %u (skipping)\n",
+ err_name,
+ err_line,
+ (unsigned int) idx);
+ json_dumpf (value,
+ stderr,
+ JSON_INDENT (2));
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ par = GNUNET_new (struct PartnerAddRequest);
+ par->idx = idx;
+ par->h =
+ TALER_EXCHANGE_management_add_partner (ctx,
+ exchange_url,
+ &partner_pub,
+ start_date,
+ end_date,
+ wad_frequency,
+ &wad_fee,
+ partner_base_url,
+ &master_sig,
+ &add_partner_cb,
+ par);
+ GNUNET_CONTAINER_DLL_insert (par_head,
+ par_tail,
+ par);
+}
+
+
+/**
+ * Function called with information about the AML officer update operation.
+ *
+ * @param cls closure with a `struct AmlStaffRequest`
+ * @param ar response data
+ */
+static void
+update_aml_officer_cb (
+ void *cls,
+ 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)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Upload failed for command %u with status %u: %s (%s)\n",
+ (unsigned int) asr->idx,
+ hr->http_status,
+ TALER_ErrorCode_get_hint (hr->ec),
+ hr->hint);
+ global_ret = EXIT_FAILURE;
+ }
+ GNUNET_CONTAINER_DLL_remove (asr_head,
+ asr_tail,
+ asr);
+ GNUNET_free (asr);
+ test_shutdown ();
+}
+
+
+/**
+ * Upload AML staff action.
+ *
+ * @param exchange_url base URL of the exchange
+ * @param idx index of the operation we are performing (for logging)
+ * @param value arguments for AML staff change
+ */
+static void
+update_aml_staff (const char *exchange_url,
+ size_t idx,
+ const json_t *value)
+{
+ struct TALER_AmlOfficerPublicKeyP officer_pub;
+ const char *officer_name;
+ struct GNUNET_TIME_Timestamp change_date;
+ bool is_active;
+ bool read_only;
+ struct TALER_MasterSignatureP master_sig;
+ struct AmlStaffRequest *asr;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto ("officer_pub",
+ &officer_pub),
+ GNUNET_JSON_spec_timestamp ("change_date",
+ &change_date),
+ GNUNET_JSON_spec_bool ("is_active",
+ &is_active),
+ GNUNET_JSON_spec_bool ("read_only",
+ &read_only),
+ GNUNET_JSON_spec_string ("officer_name",
+ &officer_name),
+ GNUNET_JSON_spec_fixed_auto ("master_sig",
+ &master_sig),
+ GNUNET_JSON_spec_end ()
+ };
+ const char *err_name;
+ unsigned int err_line;
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (value,
+ spec,
+ &err_name,
+ &err_line))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid input to AML staff update: %s#%u at %u (skipping)\n",
+ err_name,
+ err_line,
+ (unsigned int) idx);
+ json_dumpf (value,
+ stderr,
+ JSON_INDENT (2));
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ asr = GNUNET_new (struct AmlStaffRequest);
+ asr->idx = idx;
+ asr->h =
+ TALER_EXCHANGE_management_update_aml_officer (ctx,
+ exchange_url,
+ &officer_pub,
+ officer_name,
+ change_date,
+ is_active,
+ read_only,
+ &master_sig,
+ &update_aml_officer_cb,
+ asr);
+ GNUNET_CONTAINER_DLL_insert (asr_head,
+ asr_tail,
+ asr);
}
@@ -2267,6 +2641,14 @@ trigger_upload (const char *exchange_url)
.key = OP_EXTENSIONS,
.cb = &upload_extensions
},
+ {
+ .key = OP_UPDATE_AML_STAFF,
+ .cb = &update_aml_staff
+ },
+ {
+ .key = OP_ADD_PARTNER,
+ .cb = &add_partner
+ },
/* array termination */
{
.key = NULL
@@ -2287,7 +2669,7 @@ trigger_upload (const char *exchange_url)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Malformed JSON input\n");
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
/* block of code that uses key and value */
@@ -2310,7 +2692,7 @@ trigger_upload (const char *exchange_url)
"Upload does not know how to handle `%s'\n",
key);
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
}
@@ -2330,7 +2712,7 @@ do_upload (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Downloaded data was not consumed, refusing upload\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2349,7 +2731,7 @@ do_upload (char *const *args)
err.line,
err.source,
err.position);
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2358,7 +2740,7 @@ do_upload (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Error: expected JSON array for `upload` command\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2373,7 +2755,7 @@ do_upload (char *const *args)
"exchange",
"BASE_URL");
global_ret = EXIT_NOTCONFIGURED;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
trigger_upload (CFG_exchange_url);
@@ -2398,7 +2780,7 @@ do_revoke_denomination_key (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Downloaded data was not consumed, refusing revocation\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2411,7 +2793,7 @@ do_revoke_denomination_key (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"You must specify a denomination key with this subcommand\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2447,7 +2829,7 @@ do_revoke_signkey (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Downloaded data was not consumed, refusing revocation\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2460,7 +2842,7 @@ do_revoke_signkey (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"You must specify an exchange signing key with this subcommand\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2498,7 +2880,7 @@ do_add_auditor (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Downloaded data was not consumed, not adding auditor\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2511,7 +2893,7 @@ do_add_auditor (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"You must specify an auditor public key as first argument for this subcommand\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2524,7 +2906,7 @@ do_add_auditor (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"You must specify an auditor URI and auditor name as 2nd and 3rd arguments to this subcommand\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2570,7 +2952,7 @@ do_del_auditor (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Downloaded data was not consumed, not deleting auditor account\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2583,7 +2965,7 @@ do_del_auditor (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"You must specify an auditor public key as first argument for this subcommand\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2608,6 +2990,96 @@ do_del_auditor (char *const *args)
/**
+ * Parse account restriction.
+ *
+ * @param args the array of command-line arguments to process next
+ * @param[in,out] restrictions JSON array to update
+ * @return -1 on error, otherwise number of arguments from @a args that were used
+ */
+static int
+parse_restriction (char *const *args,
+ json_t *restrictions)
+{
+ if (NULL == args[0])
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Restriction TYPE argument missing\n");
+ return -1;
+ }
+ if (0 == strcmp (args[0],
+ "deny"))
+ {
+ GNUNET_assert (0 ==
+ json_array_append_new (
+ restrictions,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "deny"))));
+ return 1;
+ }
+ if (0 == strcmp (args[0],
+ "regex"))
+ {
+ json_t *i18n;
+ json_error_t err;
+
+ if ( (NULL == args[1]) ||
+ (NULL == args[2]) ||
+ (NULL == args[3]) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Mandatory arguments for restriction of type `regex' missing (REGEX, HINT, HINT-I18 required)\n");
+ return -1;
+ }
+ {
+ regex_t ex;
+
+ if (0 != regcomp (&ex,
+ args[1],
+ REG_NOSUB | REG_EXTENDED))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid regular expression `%s'\n",
+ args[1]);
+ return -1;
+ }
+ regfree (&ex);
+ }
+
+ i18n = json_loads (args[3],
+ JSON_REJECT_DUPLICATES,
+ &err);
+ if (NULL == i18n)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid JSON for restriction of type `regex': `%s` at %d\n",
+ args[3],
+ err.position);
+ return -1;
+ }
+ GNUNET_assert (0 ==
+ json_array_append_new (
+ restrictions,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "regex"),
+ GNUNET_JSON_pack_string ("payto_regex",
+ args[1]),
+ GNUNET_JSON_pack_string ("human_hint",
+ args[2]),
+ GNUNET_JSON_pack_object_steal ("human_hint_i18n",
+ i18n)
+ )));
+ return 4;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Restriction TYPE `%s' unsupported\n",
+ args[0]);
+ return -1;
+}
+
+
+/**
* Add wire account.
*
* @param args the array of command-line arguments to process next;
@@ -2619,12 +3091,18 @@ 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;
+ const char *bank_label = NULL;
+ int64_t priority = 0;
+ json_t *debit_restrictions;
+ json_t *credit_restrictions;
+ unsigned int num_args = 1;
if (NULL != in)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Downloaded data was not consumed, not adding wire account\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2632,7 +3110,7 @@ do_add_wire (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"You must specify a payto://-URI with this subcommand\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2648,7 +3126,7 @@ do_add_wire (char *const *args)
"payto URI is malformed: %s\n",
msg);
GNUNET_free (msg);
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2664,29 +3142,160 @@ do_add_wire (char *const *args)
"payto:// URI `%s' is malformed\n",
args[0]);
global_ret = EXIT_INVALIDARGUMENT;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return;
}
GNUNET_free (wire_method);
}
+ debit_restrictions = json_array ();
+ GNUNET_assert (NULL != debit_restrictions);
+ credit_restrictions = json_array ();
+ GNUNET_assert (NULL != credit_restrictions);
+ while (NULL != args[num_args])
+ {
+ if (0 == strcmp (args[num_args],
+ "conversion-url"))
+ {
+ num_args++;
+ conversion_url = args[num_args];
+ if (NULL == conversion_url)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "'conversion-url' requires an argument\n");
+ global_ret = EXIT_INVALIDARGUMENT;
+ GNUNET_SCHEDULER_shutdown ();
+ json_decref (debit_restrictions);
+ json_decref (credit_restrictions);
+ return;
+ }
+ if (! TALER_is_web_url (conversion_url))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "'conversion-url' must refer to HTTP(S) endpoint, `%s' is invalid\n",
+ conversion_url);
+ global_ret = EXIT_INVALIDARGUMENT;
+ GNUNET_SCHEDULER_shutdown ();
+ json_decref (debit_restrictions);
+ json_decref (credit_restrictions);
+ return;
+ }
+ num_args++;
+ continue;
+ }
+ if (0 == strcmp (args[num_args],
+ "credit-restriction"))
+ {
+ int iret;
+
+ num_args++;
+ iret = parse_restriction (&args[num_args],
+ credit_restrictions);
+ if (iret <= 0)
+ {
+ global_ret = EXIT_INVALIDARGUMENT;
+ GNUNET_SCHEDULER_shutdown ();
+ json_decref (debit_restrictions);
+ json_decref (credit_restrictions);
+ return;
+ }
+ num_args += iret;
+ continue;
+ }
+ if (0 == strcmp (args[num_args],
+ "debit-restriction"))
+ {
+ int iret;
+
+ num_args++;
+ iret = parse_restriction (&args[num_args],
+ debit_restrictions);
+ if (iret <= 0)
+ {
+ global_ret = EXIT_INVALIDARGUMENT;
+ GNUNET_SCHEDULER_shutdown ();
+ json_decref (debit_restrictions);
+ json_decref (credit_restrictions);
+ return;
+ }
+ num_args += iret;
+ continue;
+ }
+ if (0 == strcmp (args[num_args],
+ "display-hint"))
+ {
+ long long p;
+ char dummy;
+
+ num_args++;
+ if ( (NULL == args[num_args]) ||
+ (NULL == args[num_args + 1]) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "'display-hint' requires at least two arguments (priority and label)\n");
+ global_ret = EXIT_INVALIDARGUMENT;
+ GNUNET_SCHEDULER_shutdown ();
+ json_decref (debit_restrictions);
+ json_decref (credit_restrictions);
+ return;
+ }
+ if (1 != sscanf (args[num_args],
+ "%lld%c",
+ &p,
+ &dummy))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Priority argument `%s' is not a number\n",
+ args[num_args]);
+ global_ret = EXIT_INVALIDARGUMENT;
+ GNUNET_SCHEDULER_shutdown ();
+ json_decref (debit_restrictions);
+ json_decref (credit_restrictions);
+ return;
+ }
+ priority = (int64_t) p;
+ num_args++;
+ bank_label = args[num_args];
+ num_args++;
+ continue;
+ }
+ break;
+ }
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_allow_null (
+ GNUNET_JSON_pack_string ("bank_label",
+ bank_label)),
+ GNUNET_JSON_pack_int64 ("priority",
+ priority),
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);
}
@@ -2706,7 +3315,7 @@ do_del_wire (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Downloaded data was not consumed, not deleting wire account\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2714,7 +3323,7 @@ do_del_wire (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"You must specify a payto://-URI with this subcommand\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2759,7 +3368,7 @@ do_set_wire_fee (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Downloaded data was not consumed, not setting wire fee\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2782,7 +3391,7 @@ do_set_wire_fee (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"You must use YEAR, METHOD, WIRE-FEE, and CLOSING-FEE as arguments for this subcommand\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2846,7 +3455,7 @@ do_set_global_fee (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Downloaded data was not consumed, not setting global fee\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2856,14 +3465,28 @@ do_set_global_fee (char *const *args)
(NULL == args[3]) ||
(NULL == args[4]) ||
(NULL == args[5]) ||
- (NULL == args[6]) ||
- ( (1 != sscanf (args[0],
- "%u%c",
- &year,
- &dummy)) &&
- (0 != strcasecmp ("now",
- args[0])) ) ||
- (GNUNET_OK !=
+ (NULL == args[6]) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "You must use YEAR, HISTORY-FEE, ACCOUNT-FEE, PURSE-FEE, PURSE-TIMEOUT, HISTORY-EXPIRATION and PURSE-ACCOUNT-LIMIT as arguments for this subcommand\n");
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ if ( (1 != sscanf (args[0],
+ "%u%c",
+ &year,
+ &dummy)) &&
+ (0 != strcasecmp ("now",
+ args[0])) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid YEAR given for 'global-fee' subcommand\n");
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ if ( (GNUNET_OK !=
TALER_string_to_amount (args[1],
&fees.history)) ||
(GNUNET_OK !=
@@ -2871,21 +3494,35 @@ do_set_global_fee (char *const *args)
&fees.account)) ||
(GNUNET_OK !=
TALER_string_to_amount (args[3],
- &fees.purse)) ||
- (GNUNET_OK !=
+ &fees.purse)) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid amount given for 'global-fee' subcommand\n");
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ if ( (GNUNET_OK !=
GNUNET_STRINGS_fancy_time_to_relative (args[4],
&purse_timeout)) ||
(GNUNET_OK !=
GNUNET_STRINGS_fancy_time_to_relative (args[5],
- &history_expiration)) ||
- (1 != sscanf (args[6],
- "%u%c",
- &purse_account_limit,
- &dummy)) )
+ &history_expiration)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "You must use YEAR, HISTORY-FEE, ACCOUNT-FEE, PURSE-FEE, PURSE-TIMEOUT, HISTORY-EXPIRATION and PURSE-ACCOUNT-LIMIT as arguments for this subcommand\n");
- test_shutdown ();
+ "Invalid delay given for 'global-fee' subcommand\n");
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ if (1 != sscanf (args[6],
+ "%u%c",
+ &purse_account_limit,
+ &dummy))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid purse account limit given for 'global-fee' subcommand\n");
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2956,7 +3593,7 @@ do_drain (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Downloaded data was not consumed, refusing drain\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -2969,7 +3606,7 @@ do_drain (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Drain requires an amount, section name and target payto://-URI as arguments\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2979,7 +3616,7 @@ do_drain (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Drain requires an amount, section name and target payto://-URI as arguments\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -2990,7 +3627,7 @@ do_drain (char *const *args)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Invalid amount `%s' specified for drain\n",
args[0]);
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -3004,7 +3641,7 @@ do_drain (char *const *args)
payto_uri,
err);
GNUNET_free (err);
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -3041,23 +3678,275 @@ do_drain (char *const *args)
/**
+ * Add partner.
+ *
+ * @param args the array of command-line arguments to process next;
+ * args[0] must be the partner's master public key, args[1] the partner's
+ * API base URL, args[2] the wad fee, args[3] the wad frequency, and
+ * args[4] the year (including possibly 'now')
+ */
+static void
+do_add_partner (char *const *args)
+{
+ struct TALER_MasterPublicKeyP partner_pub;
+ struct GNUNET_TIME_Timestamp start_date;
+ struct GNUNET_TIME_Timestamp end_date;
+ struct GNUNET_TIME_Relative wad_frequency;
+ struct TALER_Amount wad_fee;
+ const char *partner_base_url;
+ struct TALER_MasterSignatureP master_sig;
+ char dummy;
+ unsigned int year;
+
+ if (NULL != in)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Downloaded data was not consumed, not adding partner\n");
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if ( (NULL == args[0]) ||
+ (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[0],
+ strlen (args[0]),
+ &partner_pub,
+ sizeof (partner_pub))) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "You must specify the partner master public key as first argument for this subcommand\n");
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ if ( (NULL == args[1]) ||
+ (0 != strncmp ("http",
+ args[1],
+ strlen ("http"))) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "You must specify the partner's base URL as the 2nd argument to this subcommand\n");
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ partner_base_url = args[1];
+ if ( (NULL == args[2]) ||
+ (GNUNET_OK !=
+ TALER_string_to_amount (args[2],
+ &wad_fee)) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid amount `%s' specified for wad fee of partner\n",
+ args[2]);
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ if ( (NULL == args[3]) ||
+ (GNUNET_OK !=
+ GNUNET_STRINGS_fancy_time_to_relative (args[3],
+ &wad_frequency)) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid wad frequency `%s' specified for add partner\n",
+ args[3]);
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ if ( (NULL == args[4]) ||
+ ( (1 != sscanf (args[4],
+ "%u%c",
+ &year,
+ &dummy)) &&
+ (0 != strcasecmp ("now",
+ args[4])) ) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid year `%s' specified for add partner\n",
+ args[4]);
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ if (0 == strcasecmp ("now",
+ args[4]))
+ year = GNUNET_TIME_get_current_year ();
+ start_date = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_year_to_time (year));
+ end_date = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_year_to_time (year + 1));
+
+ if (GNUNET_OK !=
+ load_offline_key (GNUNET_NO))
+ return;
+ TALER_exchange_offline_partner_details_sign (&partner_pub,
+ start_date,
+ end_date,
+ wad_frequency,
+ &wad_fee,
+ partner_base_url,
+ &master_priv,
+ &master_sig);
+ output_operation (OP_ADD_PARTNER,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("partner_base_url",
+ partner_base_url),
+ GNUNET_JSON_pack_time_rel ("wad_frequency",
+ wad_frequency),
+ GNUNET_JSON_pack_timestamp ("start_date",
+ start_date),
+ GNUNET_JSON_pack_timestamp ("end_date",
+ end_date),
+ GNUNET_JSON_pack_data_auto ("partner_pub",
+ &partner_pub),
+ GNUNET_JSON_pack_data_auto ("master_sig",
+ &master_sig)));
+ next (args + 5);
+}
+
+
+/**
+ * Enable or disable AML staff.
+ *
+ * @param is_active true to enable, false to disable
+ * @param args the array of command-line arguments to process next; args[0] must be the AML staff's public key, args[1] the AML staff's legal name, and if @a is_active then args[2] rw (read write) or ro (read only)
+ */
+static void
+do_set_aml_staff (bool is_active,
+ char *const *args)
+{
+ struct TALER_AmlOfficerPublicKeyP officer_pub;
+ const char *officer_name;
+ bool read_only;
+ struct TALER_MasterSignatureP master_sig;
+ struct GNUNET_TIME_Timestamp now
+ = GNUNET_TIME_timestamp_get ();
+
+ if (NULL != in)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Downloaded data was not consumed, not updating AML staff status\n");
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if ( (NULL == args[0]) ||
+ (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[0],
+ strlen (args[0]),
+ &officer_pub,
+ sizeof (officer_pub))) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "You must specify the AML officer's public key as first argument for this subcommand\n");
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ if (NULL == args[1])
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "You must specify the officer's legal name as the 2nd argument to this subcommand\n");
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ officer_name = args[1];
+ if (is_active)
+ {
+ if ( (NULL == args[2]) ||
+ ( (0 != strcmp (args[2],
+ "ro")) &&
+ (0 != strcmp (args[2],
+ "rw")) ) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "You must specify 'ro' or 'rw' (and not `%s') for the access level\n",
+ args[2]);
+ GNUNET_SCHEDULER_shutdown ();
+ global_ret = EXIT_INVALIDARGUMENT;
+ return;
+ }
+ read_only = (0 == strcmp (args[2],
+ "ro"));
+ }
+ else
+ {
+ read_only = true;
+ }
+ if (GNUNET_OK !=
+ load_offline_key (GNUNET_NO))
+ return;
+ TALER_exchange_offline_aml_officer_status_sign (&officer_pub,
+ officer_name,
+ now,
+ is_active,
+ read_only,
+ &master_priv,
+ &master_sig);
+ output_operation (OP_UPDATE_AML_STAFF,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("officer_name",
+ officer_name),
+ GNUNET_JSON_pack_timestamp ("change_date",
+ now),
+ GNUNET_JSON_pack_bool ("is_active",
+ is_active),
+ GNUNET_JSON_pack_bool ("read_only",
+ read_only),
+ GNUNET_JSON_pack_data_auto ("officer_pub",
+ &officer_pub),
+ GNUNET_JSON_pack_data_auto ("master_sig",
+ &master_sig)));
+ next (args + (is_active ? 3 : 2));
+}
+
+
+/**
+ * Disable AML staff.
+ *
+ * @param args the array of command-line arguments to process next;
+ * args[0] must be the AML staff's public key, args[1] the AML staff's legal name, args[2] rw (read write) or ro (read only)
+ */
+static void
+disable_aml_staff (char *const *args)
+{
+ do_set_aml_staff (false,
+ args);
+}
+
+
+/**
+ * Enable AML staff.
+ *
+ * @param args the array of command-line arguments to process next;
+ * args[0] must be the AML staff's public key, args[1] the AML staff's legal name, args[2] rw (read write) or ro (read only)
+ */
+static void
+enable_aml_staff (char *const *args)
+{
+ do_set_aml_staff (true,
+ args);
+}
+
+
+/**
* Function called with information about future keys. Dumps the JSON output
* (on success), either into an internal buffer or to stdout (depending on
* 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)
{
@@ -3075,7 +3964,7 @@ download_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to download keys from `%s' (no HTTP response)\n",
CFG_exchange_url);
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_FAILURE;
return;
}
@@ -3114,7 +4003,7 @@ do_download (char *const *args)
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchange",
"BASE_URL");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_NOTCONFIGURED;
return;
}
@@ -3322,7 +4211,7 @@ tofu_check (const struct TALER_SecurityModulePublicKeySetP *secmset)
* @param signkeys keys to output
* @return #GNUNET_OK on success
*/
-static int
+static enum GNUNET_GenericReturnValue
show_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
const json_t *signkeys)
{
@@ -3367,7 +4256,7 @@ show_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return GNUNET_SYSERR;
}
duration = GNUNET_TIME_absolute_get_difference (start_time.abs_time,
@@ -3383,7 +4272,7 @@ show_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
"Invalid security module signature for signing key %s (aborting)\n",
TALER_B2S (&exchange_pub));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return GNUNET_SYSERR;
}
{
@@ -3475,7 +4364,7 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
JSON_INDENT (2));
GNUNET_JSON_parse_free (spec);
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return GNUNET_SYSERR;
}
duration = GNUNET_TIME_absolute_get_difference (
@@ -3483,13 +4372,13 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
stamp_expire_withdraw.abs_time);
TALER_denom_pub_hash (&denom_pub,
&h_denom_pub);
- switch (denom_pub.cipher)
+ switch (denom_pub.bsign_pub_key->cipher)
{
- case TALER_DENOMINATION_RSA:
+ case GNUNET_CRYPTO_BSA_RSA:
{
struct TALER_RsaPubHashP h_rsa;
- TALER_rsa_pub_hash (denom_pub.details.rsa_public_key,
+ TALER_rsa_pub_hash (denom_pub.bsign_pub_key->details.rsa_public_key,
&h_rsa);
ok = TALER_exchange_secmod_rsa_verify (&h_rsa,
section_name,
@@ -3499,11 +4388,11 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
&secm_sig);
}
break;
- case TALER_DENOMINATION_CS:
+ case GNUNET_CRYPTO_BSA_CS:
{
struct TALER_CsPubHashP h_cs;
- TALER_cs_pub_hash (&denom_pub.details.cs_public_key,
+ TALER_cs_pub_hash (&denom_pub.bsign_pub_key->details.cs_public_key,
&h_cs);
ok = TALER_exchange_secmod_cs_verify (&h_cs,
section_name,
@@ -3524,7 +4413,7 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
"Invalid security module signature for denomination key %s (aborting)\n",
GNUNET_h2s (&h_denom_pub.hash));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return GNUNET_SYSERR;
}
@@ -3611,7 +4500,7 @@ parse_keys_input (const char *command_name)
err.source,
err.position);
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return NULL;
}
}
@@ -3630,7 +4519,7 @@ parse_keys_input (const char *command_name)
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return NULL;
}
if (0 != strcmp (op_str,
@@ -3661,15 +4550,15 @@ do_show (char *const *args)
json_t *keys;
const char *err_name;
unsigned int err_line;
- json_t *denomkeys;
- json_t *signkeys;
+ const json_t *denomkeys;
+ const json_t *signkeys;
struct TALER_MasterPublicKeyP mpub;
struct TALER_SecurityModulePublicKeySetP secmset;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("future_denoms",
- &denomkeys),
- GNUNET_JSON_spec_json ("future_signkeys",
- &signkeys),
+ GNUNET_JSON_spec_array_const ("future_denoms",
+ &denomkeys),
+ GNUNET_JSON_spec_array_const ("future_signkeys",
+ &signkeys),
GNUNET_JSON_spec_fixed_auto ("master_pub",
&mpub),
GNUNET_JSON_spec_fixed_auto ("denom_secmod_public_key",
@@ -3702,7 +4591,7 @@ do_show (char *const *args)
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
json_decref (keys);
return;
}
@@ -3713,8 +4602,7 @@ do_show (char *const *args)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Fatal: exchange uses different master key!\n");
global_ret = EXIT_FAILURE;
- test_shutdown ();
- GNUNET_JSON_parse_free (spec);
+ GNUNET_SCHEDULER_shutdown ();
json_decref (keys);
return;
}
@@ -3722,8 +4610,7 @@ do_show (char *const *args)
tofu_check (&secmset))
{
global_ret = EXIT_FAILURE;
- test_shutdown ();
- GNUNET_JSON_parse_free (spec);
+ GNUNET_SCHEDULER_shutdown ();
json_decref (keys);
return;
}
@@ -3736,13 +4623,11 @@ do_show (char *const *args)
denomkeys)) )
{
global_ret = EXIT_FAILURE;
- test_shutdown ();
- GNUNET_JSON_parse_free (spec);
+ GNUNET_SCHEDULER_shutdown ();
json_decref (keys);
return;
}
json_decref (keys);
- GNUNET_JSON_parse_free (spec);
next (args);
}
@@ -3801,7 +4686,7 @@ sign_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return GNUNET_SYSERR;
}
@@ -3818,7 +4703,7 @@ sign_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
"Invalid security module signature for signing key %s (aborting)\n",
TALER_B2S (&exchange_pub));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
@@ -3955,7 +4840,7 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
JSON_INDENT (2));
GNUNET_JSON_parse_free (spec);
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
return GNUNET_SYSERR;
}
duration = GNUNET_TIME_absolute_get_difference (
@@ -3967,13 +4852,14 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
TALER_denom_pub_hash (&denom_pub,
&h_denom_pub);
- switch (denom_pub.cipher)
+
+ switch (denom_pub.bsign_pub_key->cipher)
{
- case TALER_DENOMINATION_RSA:
+ case GNUNET_CRYPTO_BSA_RSA:
{
struct TALER_RsaPubHashP h_rsa;
- TALER_rsa_pub_hash (denom_pub.details.rsa_public_key,
+ TALER_rsa_pub_hash (denom_pub.bsign_pub_key->details.rsa_public_key,
&h_rsa);
if (GNUNET_OK !=
TALER_exchange_secmod_rsa_verify (&h_rsa,
@@ -3987,17 +4873,17 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
"Invalid security module signature for denomination key %s (aborting)\n",
GNUNET_h2s (&h_denom_pub.hash));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
}
break;
- case TALER_DENOMINATION_CS:
+ case GNUNET_CRYPTO_BSA_CS:
{
struct TALER_CsPubHashP h_cs;
- TALER_cs_pub_hash (&denom_pub.details.cs_public_key,
+ TALER_cs_pub_hash (&denom_pub.bsign_pub_key->details.cs_public_key,
&h_cs);
if (GNUNET_OK !=
TALER_exchange_secmod_cs_verify (&h_cs,
@@ -4011,7 +4897,7 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
"Invalid security module signature for denomination key %s (aborting)\n",
GNUNET_h2s (&h_denom_pub.hash));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
@@ -4019,7 +4905,7 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
break;
default:
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
@@ -4062,15 +4948,15 @@ do_sign (char *const *args)
json_t *keys;
const char *err_name;
unsigned int err_line;
- json_t *denomkeys;
- json_t *signkeys;
+ const json_t *denomkeys;
+ const json_t *signkeys;
struct TALER_MasterPublicKeyP mpub;
struct TALER_SecurityModulePublicKeySetP secmset;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("future_denoms",
- &denomkeys),
- GNUNET_JSON_spec_json ("future_signkeys",
- &signkeys),
+ GNUNET_JSON_spec_array_const ("future_denoms",
+ &denomkeys),
+ GNUNET_JSON_spec_array_const ("future_signkeys",
+ &signkeys),
GNUNET_JSON_spec_fixed_auto ("master_pub",
&mpub),
GNUNET_JSON_spec_fixed_auto ("denom_secmod_public_key",
@@ -4105,7 +4991,7 @@ do_sign (char *const *args)
stderr,
JSON_INDENT (2));
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
json_decref (keys);
return;
}
@@ -4116,8 +5002,7 @@ do_sign (char *const *args)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Fatal: exchange uses different master key!\n");
global_ret = EXIT_FAILURE;
- test_shutdown ();
- GNUNET_JSON_parse_free (spec);
+ GNUNET_SCHEDULER_shutdown ();
json_decref (keys);
return;
}
@@ -4127,8 +5012,7 @@ do_sign (char *const *args)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Fatal: security module keys changed!\n");
global_ret = EXIT_FAILURE;
- test_shutdown ();
- GNUNET_JSON_parse_free (spec);
+ GNUNET_SCHEDULER_shutdown ();
json_decref (keys);
return;
}
@@ -4149,10 +5033,9 @@ do_sign (char *const *args)
denomkey_sig_array)) )
{
global_ret = EXIT_FAILURE;
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
json_decref (signkey_sig_array);
json_decref (denomkey_sig_array);
- GNUNET_JSON_parse_free (spec);
json_decref (keys);
return;
}
@@ -4164,7 +5047,6 @@ do_sign (char *const *args)
GNUNET_JSON_pack_array_steal ("signkey_sigs",
signkey_sig_array)));
}
- GNUNET_JSON_parse_free (spec);
json_decref (keys);
next (args);
}
@@ -4353,6 +5235,9 @@ cmd_handler (char *const *args,
cmds[i].name,
cmds[i].help);
}
+ json_decref (out);
+ out = NULL;
+ GNUNET_SCHEDULER_shutdown ();
}
@@ -4381,7 +5266,7 @@ do_work_extensions (char *const *args)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"You must provide a subcommand: `show` or `sign`.\n");
- test_shutdown ();
+ GNUNET_SCHEDULER_shutdown ();
global_ret = EXIT_INVALIDARGUMENT;
return;
}
@@ -4445,7 +5330,7 @@ work (void *cls)
{
.name = "enable-account",
.help =
- "enable wire account of the exchange (payto-URI must be given as argument)",
+ "enable wire account of the exchange (payto-URI must be given as argument; for optional arguments see man page)",
.cb = &do_add_wire
},
{
@@ -4473,6 +5358,24 @@ work (void *cls)
.cb = &do_drain
},
{
+ .name = "add-partner",
+ .help =
+ "add partner exchange for P2P wad transfers (partner master public key, partner base URL, wad fee, wad frequency and validity year must be given as arguments)",
+ .cb = &do_add_partner
+ },
+ {
+ .name = "aml-enable",
+ .help =
+ "enable AML staff member (staff member public key, legal name and rw (read write) or ro (read only) must be given as arguments)",
+ .cb = &enable_aml_staff
+ },
+ {
+ .name = "aml-disable",
+ .help =
+ "disable AML staff member (staff member public key and legal name must be given as arguments)",
+ .cb = &disable_aml_staff
+ },
+ {
.name = "upload",
.help =
"upload operation result to exchange (to be performed online!)",