Merge branch 'bug-7276'

This commit is contained in:
Christian Grothoff 2022-11-18 10:49:53 +01:00
commit 7d3ce9bb5d
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
12 changed files with 1094 additions and 1129 deletions

View File

@ -1469,65 +1469,43 @@ check_exchange_wire_out (struct WireAccount *wa)
* transactions).
*
* @param cls `struct WireAccount` with current wire account to process
* @param http_status_code http status of the request
* @param ec error code in case something went wrong
* @param row_off identification of the position at which we are querying
* @param details details about the wire transfer
* @param json original response in JSON format
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
* @param dhr HTTP response details
*/
static enum GNUNET_GenericReturnValue
static void
history_debit_cb (void *cls,
unsigned int http_status_code,
enum TALER_ErrorCode ec,
uint64_t row_off,
const struct TALER_BANK_DebitDetails *details,
const json_t *json)
const struct TALER_BANK_DebitHistoryResponse *dhr)
{
struct WireAccount *wa = cls;
struct ReserveOutInfo *roi;
size_t slen;
(void) json;
if (NULL == details)
{
wa->dhh = NULL;
if ( (TALER_EC_NONE != ec) &&
( (! ignore_account_404) ||
(MHD_HTTP_NOT_FOUND != http_status_code) ) )
switch (dhr->http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Error fetching debit history of account %s: %u/%u!\n",
wa->ai->section_name,
http_status_code,
(unsigned int) ec);
commit (GNUNET_DB_STATUS_HARD_ERROR);
global_ret = EXIT_FAILURE;
GNUNET_SCHEDULER_shutdown ();
return GNUNET_SYSERR;
}
check_exchange_wire_out (wa);
return GNUNET_OK;
}
case MHD_HTTP_OK:
for (unsigned int i = 0; i<dhr->details.success.details_length; i++)
{
const struct TALER_BANK_DebitDetails *dd
= &dhr->details.success.details[i];
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Analyzing bank DEBIT at %s of %s with WTID %s\n",
GNUNET_TIME_timestamp2s (details->execution_date),
TALER_amount2s (&details->amount),
TALER_B2S (&details->wtid));
GNUNET_TIME_timestamp2s (dd->execution_date),
TALER_amount2s (&dd->amount),
TALER_B2S (&dd->wtid));
/* Update offset */
wa->wire_off.out_wire_off = row_off;
slen = strlen (details->credit_account_uri) + 1;
wa->wire_off.out_wire_off = dd->serial_id;
slen = strlen (dd->credit_account_uri) + 1;
roi = GNUNET_malloc (sizeof (struct ReserveOutInfo)
+ slen);
GNUNET_CRYPTO_hash (&details->wtid,
sizeof (details->wtid),
GNUNET_CRYPTO_hash (&dd->wtid,
sizeof (dd->wtid),
&roi->subject_hash);
roi->details.amount = details->amount;
roi->details.execution_date = details->execution_date;
roi->details.wtid = details->wtid;
roi->details.amount = dd->amount;
roi->details.execution_date = dd->execution_date;
roi->details.wtid = dd->wtid;
roi->details.credit_account_uri = (const char *) &roi[1];
memcpy (&roi[1],
details->credit_account_uri,
dd->credit_account_uri,
slen);
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (out_map,
@ -1542,19 +1520,41 @@ history_debit_cb (void *cls,
TALER_B2S (&roi->subject_hash));
TALER_ARL_amount_add (&total_wire_format_amount,
&total_wire_format_amount,
&details->amount);
&dd->amount);
TALER_ARL_report (report_wire_format_inconsistencies,
GNUNET_JSON_PACK (
TALER_JSON_pack_amount ("amount",
&details->amount),
&dd->amount),
GNUNET_JSON_pack_uint64 ("wire_offset",
row_off),
dd->serial_id),
GNUNET_JSON_pack_string ("diagnostic",
diagnostic)));
GNUNET_free (diagnostic);
return GNUNET_OK;
}
return GNUNET_OK;
}
check_exchange_wire_out (wa);
return;
case MHD_HTTP_NO_CONTENT:
check_exchange_wire_out (wa);
return;
case MHD_HTTP_NOT_FOUND:
if (ignore_account_404)
{
check_exchange_wire_out (wa);
return;
}
break;
default:
break;
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Error fetching debit history of account %s: %u/%u!\n",
wa->ai->section_name,
dhr->http_status,
(unsigned int) dhr->ec);
commit (GNUNET_DB_STATUS_HARD_ERROR);
global_ret = EXIT_FAILURE;
GNUNET_SCHEDULER_shutdown ();
}
@ -1764,49 +1764,14 @@ process_credits (void *cls);
/**
* This function is called for all transactions that
* are credited to the exchange's account (incoming
* transactions).
* We got all of the incoming transactions for @a wa,
* finish processing the account.
*
* @param cls `struct WireAccount` we are processing
* @param http_status HTTP status returned by the bank
* @param ec error code in case something went wrong
* @param row_off identification of the position at which we are querying
* @param details details about the wire transfer
* @param json raw response
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
* @param[in,out] wa wire account to process
*/
static enum GNUNET_GenericReturnValue
history_credit_cb (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t row_off,
const struct TALER_BANK_CreditDetails *details,
const json_t *json)
static void
conclude_account (struct WireAccount *wa)
{
struct WireAccount *wa = cls;
struct ReserveInInfo *rii;
struct GNUNET_HashCode key;
(void) json;
if (NULL == details)
{
wa->chh = NULL;
if ( (TALER_EC_NONE != ec) &&
( (! ignore_account_404) ||
(MHD_HTTP_NOT_FOUND != http_status) ) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Error fetching credit history of account %s: %u/%s!\n",
wa->ai->section_name,
http_status,
TALER_ErrorCode_get_hint (ec));
commit (GNUNET_DB_STATUS_HARD_ERROR);
global_ret = EXIT_FAILURE;
GNUNET_SCHEDULER_shutdown ();
return GNUNET_SYSERR;
}
/* end of operation */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Reconciling CREDIT processing of account `%s'\n",
wa->ai->section_name);
@ -1818,15 +1783,30 @@ history_credit_cb (void *cls,
&free_rii,
NULL);
process_credits (wa->next);
return GNUNET_OK;
}
/**
* Analyze credit transation @a details into @a wa.
*
* @param[in,out] wa account that received the transfer
* @param details transfer details
* @return true on success, false to stop loop at this point
*/
static bool
analyze_credit (struct WireAccount *wa,
const struct TALER_BANK_CreditDetails *details)
{
struct ReserveInInfo *rii;
struct GNUNET_HashCode key;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Analyzing bank CREDIT at %s of %s with Reserve-pub %s\n",
GNUNET_TIME_timestamp2s (details->execution_date),
TALER_amount2s (&details->amount),
TALER_B2S (&details->reserve_pub));
GNUNET_CRYPTO_hash (&row_off,
sizeof (row_off),
GNUNET_CRYPTO_hash (&details->serial_id,
sizeof (details->serial_id),
&key);
rii = GNUNET_CONTAINER_multihashmap_get (in_map,
&key);
@ -1835,13 +1815,12 @@ history_credit_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Failed to find wire transfer at `%s' in exchange database. Audit ends at this point in time.\n",
GNUNET_TIME_timestamp2s (details->execution_date));
wa->chh = NULL;
process_credits (wa->next);
return GNUNET_SYSERR; /* not an error, just end of processing */
return false; /* not an error, just end of processing */
}
/* Update offset */
wa->wire_off.in_wire_off = row_off;
wa->wire_off.in_wire_off = details->serial_id;
/* compare records with expected data */
if (0 != GNUNET_memcmp (&details->reserve_pub,
&rii->details.reserve_pub))
@ -1852,7 +1831,7 @@ history_credit_cb (void *cls,
GNUNET_JSON_pack_uint64 ("row",
rii->rowid),
GNUNET_JSON_pack_uint64 ("bank_row",
row_off),
details->serial_id),
TALER_JSON_pack_amount ("amount_exchange_expected",
&rii->details.amount),
TALER_JSON_pack_amount ("amount_wired",
@ -1872,7 +1851,7 @@ history_credit_cb (void *cls,
GNUNET_JSON_pack_uint64 ("row",
rii->rowid),
GNUNET_JSON_pack_uint64 ("bank_row",
row_off),
details->serial_id),
TALER_JSON_pack_amount ("amount_exchange_expected",
&zero),
TALER_JSON_pack_amount ("amount_wired",
@ -1898,7 +1877,7 @@ history_credit_cb (void *cls,
GNUNET_JSON_pack_uint64 ("row",
rii->rowid),
GNUNET_JSON_pack_uint64 ("bank_row",
row_off),
details->serial_id),
TALER_JSON_pack_amount ("amount_exchange_expected",
&rii->details.amount),
TALER_JSON_pack_amount ("amount_wired",
@ -1946,7 +1925,7 @@ history_credit_cb (void *cls,
GNUNET_JSON_pack_uint64 ("row",
rii->rowid),
GNUNET_JSON_pack_uint64 ("bank_row",
row_off),
details->serial_id),
GNUNET_JSON_pack_data_auto (
"reserve_pub",
&rii->details.reserve_pub)));
@ -1965,7 +1944,7 @@ history_credit_cb (void *cls,
GNUNET_JSON_pack_uint64 ("row",
rii->rowid),
GNUNET_JSON_pack_uint64 ("bank_row",
row_off),
details->serial_id),
GNUNET_JSON_pack_string ("diagnostic",
"execution date mismatch")));
}
@ -1974,7 +1953,60 @@ cleanup:
free_rii (NULL,
&key,
rii));
return GNUNET_OK;
return true;
}
/**
* This function is called for all transactions that
* are credited to the exchange's account (incoming
* transactions).
*
* @param cls `struct WireAccount` we are processing
* @param chr HTTP response returned by the bank
*/
static void
history_credit_cb (void *cls,
const struct TALER_BANK_CreditHistoryResponse *chr)
{
struct WireAccount *wa = cls;
wa->chh = NULL;
switch (chr->http_status)
{
case MHD_HTTP_OK:
for (unsigned int i = 0; i<chr->details.success.details_length; i++)
{
const struct TALER_BANK_CreditDetails *cd
= &chr->details.success.details[i];
if (! analyze_credit (wa,
cd))
break;
}
conclude_account (wa);
return;
case MHD_HTTP_NO_CONTENT:
conclude_account (wa);
return;
case MHD_HTTP_NOT_FOUND:
if (ignore_account_404)
{
conclude_account (wa);
return;
}
break;
default:
break;
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Error fetching credit history of account %s: %u/%s!\n",
wa->ai->section_name,
chr->http_status,
TALER_ErrorCode_get_hint (chr->ec));
commit (GNUNET_DB_STATUS_HARD_ERROR);
global_ret = EXIT_FAILURE;
GNUNET_SCHEDULER_shutdown ();
}

View File

@ -77,6 +77,11 @@ static enum GNUNET_GenericReturnValue
parse_account_history (struct TALER_BANK_CreditHistoryHandle *hh,
const json_t *history)
{
struct TALER_BANK_CreditHistoryResponse chr = {
.http_status = MHD_HTTP_OK,
.ec = TALER_EC_NONE,
.response = history
};
json_t *history_array;
if (NULL == (history_array = json_object_get (history,
@ -90,23 +95,26 @@ parse_account_history (struct TALER_BANK_CreditHistoryHandle *hh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
{
size_t len = json_array_size (history_array);
struct TALER_BANK_CreditDetails cd[len];
for (unsigned int i = 0; i<json_array_size (history_array); i++)
{
struct TALER_BANK_CreditDetails td;
uint64_t row_id;
struct TALER_BANK_CreditDetails *td = &cd[i];
struct GNUNET_JSON_Specification hist_spec[] = {
TALER_JSON_spec_amount_any ("amount",
&td.amount),
&td->amount),
GNUNET_JSON_spec_timestamp ("date",
&td.execution_date),
&td->execution_date),
GNUNET_JSON_spec_uint64 ("row_id",
&row_id),
&td->serial_id),
GNUNET_JSON_spec_fixed_auto ("reserve_pub",
&td.reserve_pub),
&td->reserve_pub),
GNUNET_JSON_spec_string ("debit_account",
&td.debit_account_uri),
&td->debit_account_uri),
GNUNET_JSON_spec_string ("credit_account",
&td.credit_account_uri),
&td->credit_account_uri),
GNUNET_JSON_spec_end ()
};
json_t *transaction = json_array_get (history_array,
@ -115,24 +123,17 @@ parse_account_history (struct TALER_BANK_CreditHistoryHandle *hh,
if (GNUNET_OK !=
GNUNET_JSON_parse (transaction,
hist_spec,
NULL, NULL))
NULL,
NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
hh->hcb (hh->hcb_cls,
MHD_HTTP_OK,
TALER_EC_NONE,
row_id,
&td,
transaction))
{
hh->hcb = NULL;
GNUNET_JSON_parse_free (hist_spec);
return GNUNET_OK;
}
GNUNET_JSON_parse_free (hist_spec);
chr.details.success.details_length = len;
chr.details.success.details = cd;
hh->hcb (hh->hcb_cls,
&chr);
}
return GNUNET_OK;
}
@ -152,72 +153,67 @@ handle_credit_history_finished (void *cls,
const void *response)
{
struct TALER_BANK_CreditHistoryHandle *hh = cls;
const json_t *j = response;
enum TALER_ErrorCode ec;
struct TALER_BANK_CreditHistoryResponse chr = {
.http_status = MHD_HTTP_OK,
.response = response
};
hh->job = NULL;
switch (response_code)
{
case 0:
ec = TALER_EC_GENERIC_INVALID_RESPONSE;
chr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
parse_account_history (hh,
j))
chr.response))
{
GNUNET_break_op (0);
json_dumpf (j,
json_dumpf (chr.response,
stderr,
JSON_INDENT (2));
response_code = 0;
ec = TALER_EC_GENERIC_INVALID_RESPONSE;
chr.http_status = 0;
chr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
}
response_code = MHD_HTTP_NO_CONTENT; /* signal end of list */
ec = TALER_EC_NONE;
break;
TALER_BANK_credit_history_cancel (hh);
return;
case MHD_HTTP_NO_CONTENT:
ec = TALER_EC_NONE;
break;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the bank is buggy
(or API version conflict); just pass JSON reply to the application */
GNUNET_break_op (0);
ec = TALER_JSON_get_error_code (j);
chr.ec = TALER_JSON_get_error_code (chr.response);
break;
case MHD_HTTP_UNAUTHORIZED:
/* Nothing really to verify, bank says the HTTP Authentication
failed. May happen if HTTP authentication is used and the
user supplied a wrong username/password combination. */
ec = TALER_JSON_get_error_code (j);
chr.ec = TALER_JSON_get_error_code (chr.response);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify: the bank is either unaware
of the endpoint (not a bank), or of the account.
We should pass the JSON (?) reply to the application */
ec = TALER_JSON_get_error_code (j);
chr.ec = TALER_JSON_get_error_code (chr.response);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
ec = TALER_JSON_get_error_code (j);
chr.ec = TALER_JSON_get_error_code (chr.response);
break;
default:
/* unexpected response code */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n",
(unsigned int) response_code);
ec = TALER_JSON_get_error_code (j);
chr.ec = TALER_JSON_get_error_code (chr.response);
break;
}
if (NULL != hh->hcb)
hh->hcb (hh->hcb_cls,
response_code,
ec,
0LLU,
NULL,
j);
&chr);
TALER_BANK_credit_history_cancel (hh);
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2017--2021 Taler Systems SA
Copyright (C) 2017--2022 Taler Systems SA
TALER is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -77,6 +77,11 @@ static enum GNUNET_GenericReturnValue
parse_account_history (struct TALER_BANK_DebitHistoryHandle *hh,
const json_t *history)
{
struct TALER_BANK_DebitHistoryResponse dhr = {
.http_status = MHD_HTTP_OK,
.ec = TALER_EC_NONE,
.response = history
};
json_t *history_array;
if (NULL == (history_array = json_object_get (history,
@ -90,25 +95,28 @@ parse_account_history (struct TALER_BANK_DebitHistoryHandle *hh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
for (unsigned int i = 0; i<json_array_size (history_array); i++)
{
struct TALER_BANK_DebitDetails td;
uint64_t row_id;
size_t len = json_array_size (history_array);
struct TALER_BANK_DebitDetails dd[len];
for (unsigned int i = 0; i<len; i++)
{
struct TALER_BANK_DebitDetails *td = &dd[i];
struct GNUNET_JSON_Specification hist_spec[] = {
TALER_JSON_spec_amount_any ("amount",
&td.amount),
&td->amount),
GNUNET_JSON_spec_timestamp ("date",
&td.execution_date),
&td->execution_date),
GNUNET_JSON_spec_uint64 ("row_id",
&row_id),
&td->serial_id),
GNUNET_JSON_spec_fixed_auto ("wtid",
&td.wtid),
&td->wtid),
GNUNET_JSON_spec_string ("credit_account",
&td.credit_account_uri),
&td->credit_account_uri),
GNUNET_JSON_spec_string ("debit_account",
&td.debit_account_uri),
&td->debit_account_uri),
GNUNET_JSON_spec_string ("exchange_base_url",
&td.exchange_base_url),
&td->exchange_base_url),
GNUNET_JSON_spec_end ()
};
json_t *transaction = json_array_get (history_array,
@ -117,24 +125,17 @@ parse_account_history (struct TALER_BANK_DebitHistoryHandle *hh,
if (GNUNET_OK !=
GNUNET_JSON_parse (transaction,
hist_spec,
NULL, NULL))
NULL,
NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
hh->hcb (hh->hcb_cls,
MHD_HTTP_OK,
TALER_EC_NONE,
row_id,
&td,
transaction))
{
hh->hcb = NULL;
GNUNET_JSON_parse_free (hist_spec);
return GNUNET_OK;
}
GNUNET_JSON_parse_free (hist_spec);
dhr.details.success.details_length = len;
dhr.details.success.details = dd;
hh->hcb (hh->hcb_cls,
&dhr);
}
return GNUNET_OK;
}
@ -154,69 +155,64 @@ handle_debit_history_finished (void *cls,
const void *response)
{
struct TALER_BANK_DebitHistoryHandle *hh = cls;
const json_t *j = response;
enum TALER_ErrorCode ec;
struct TALER_BANK_DebitHistoryResponse dhr = {
.http_status = MHD_HTTP_OK,
.response = response
};
hh->job = NULL;
switch (response_code)
{
case 0:
ec = TALER_EC_GENERIC_INVALID_RESPONSE;
dhr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
parse_account_history (hh,
j))
dhr.response))
{
GNUNET_break_op (0);
response_code = 0;
ec = TALER_EC_GENERIC_INVALID_RESPONSE;
dhr.http_status = 0;
dhr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
}
response_code = MHD_HTTP_NO_CONTENT; /* signal end of list */
ec = TALER_EC_NONE;
break;
TALER_BANK_debit_history_cancel (hh);
return;
case MHD_HTTP_NO_CONTENT:
ec = TALER_EC_NONE;
break;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the bank is buggy
(or API version conflict); just pass JSON reply to the application */
GNUNET_break_op (0);
ec = TALER_JSON_get_error_code (j);
dhr.ec = TALER_JSON_get_error_code (dhr.response);
break;
case MHD_HTTP_UNAUTHORIZED:
/* Nothing really to verify, bank says the HTTP Authentication
failed. May happen if HTTP authentication is used and the
user supplied a wrong username/password combination. */
ec = TALER_JSON_get_error_code (j);
dhr.ec = TALER_JSON_get_error_code (dhr.response);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify: the bank is either unaware
of the endpoint (not a bank), or of the account.
We should pass the JSON (?) reply to the application */
ec = TALER_JSON_get_error_code (j);
dhr.ec = TALER_JSON_get_error_code (dhr.response);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
ec = TALER_JSON_get_error_code (j);
dhr.ec = TALER_JSON_get_error_code (dhr.response);
break;
default:
/* unexpected response code */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n",
(unsigned int) response_code);
ec = TALER_JSON_get_error_code (j);
dhr.ec = TALER_JSON_get_error_code (dhr.response);
break;
}
if (NULL != hh->hcb)
hh->hcb (hh->hcb_cls,
response_code,
ec,
0LLU,
NULL,
j);
&dhr);
TALER_BANK_debit_history_cancel (hh);
}

View File

@ -152,83 +152,72 @@ do_shutdown (void *cls)
/**
* Callback used to process ONE entry in the transaction
* Callback used to process the transaction
* history returned by the bank.
*
* @param cls closure
* @param http_status HTTP status code from server
* @param ec taler error code
* @param serial_id identification of the position at
* which we are returning data
* @param details details about the wire transfer
* @param json original full response from server
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to
* abort iteration
* @param reply response we got from the bank
*/
static enum GNUNET_GenericReturnValue
static void
credit_history_cb (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t serial_id,
const struct TALER_BANK_CreditDetails *details,
const json_t *json)
const struct TALER_BANK_CreditHistoryResponse *reply)
{
(void) cls;
chh = NULL;
if (MHD_HTTP_OK != http_status)
{
if ( (MHD_HTTP_NO_CONTENT != http_status) ||
(TALER_EC_NONE != ec) )
{
if (0 == http_status)
switch (reply->http_status)
{
case 0:
fprintf (stderr,
"Failed to obtain HTTP reply from `%s'\n",
auth.wire_gateway_url);
}
else
{
fprintf (stderr,
"Failed to obtain credit history from `%s': HTTP status %u (%s)\n",
auth.wire_gateway_url,
http_status,
TALER_ErrorCode_get_hint (ec));
}
if (NULL != json)
json_dumpf (json,
stderr,
JSON_INDENT (2));
global_ret = 2;
GNUNET_SCHEDULER_shutdown ();
return GNUNET_NO;
}
break;
case MHD_HTTP_NO_CONTENT:
fprintf (stdout,
"End of transactions list.\n");
"No transactions.\n");
global_ret = 0;
GNUNET_SCHEDULER_shutdown ();
return GNUNET_NO;
}
break;
case MHD_HTTP_OK:
for (unsigned int i = 0; i<reply->details.success.details_length; i++)
{
const struct TALER_BANK_CreditDetails *cd =
&reply->details.success.details[i];
/* If credit/debit accounts were specified, use as a filter */
if ( (NULL != credit_account) &&
(0 != strcasecmp (credit_account,
details->credit_account_uri) ) )
return GNUNET_OK;
cd->credit_account_uri) ) )
continue;
if ( (NULL != debit_account) &&
(0 != strcasecmp (debit_account,
details->debit_account_uri) ) )
return GNUNET_OK;
cd->debit_account_uri) ) )
continue;
fprintf (stdout,
"%llu: %s->%s (%s) over %s at %s\n",
(unsigned long long) serial_id,
details->debit_account_uri,
details->credit_account_uri,
TALER_B2S (&details->reserve_pub),
TALER_amount2s (&details->amount),
GNUNET_TIME_timestamp2s (details->execution_date));
return GNUNET_OK;
(unsigned long long) cd->serial_id,
cd->debit_account_uri,
cd->credit_account_uri,
TALER_B2S (&cd->reserve_pub),
TALER_amount2s (&cd->amount),
GNUNET_TIME_timestamp2s (cd->execution_date));
}
global_ret = 0;
break;
default:
fprintf (stderr,
"Failed to obtain credit history from `%s': HTTP status %u (%s)\n",
auth.wire_gateway_url,
reply->http_status,
TALER_ErrorCode_get_hint (reply->ec));
if (NULL != reply->response)
json_dumpf (reply->response,
stderr,
JSON_INDENT (2));
global_ret = 2;
break;
}
GNUNET_SCHEDULER_shutdown ();
}
@ -264,84 +253,71 @@ execute_credit_history (void)
/**
* Function with the debit debit transaction history.
* Function with the debit transaction history.
*
* @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
* 0 if the bank's reply is bogus (fails to follow the protocol),
* #MHD_HTTP_NO_CONTENT if there are no more results; on success the
* last callback is always of this status (even if `abs(num_results)` were
* already returned).
* @param ec detailed error code
* @param serial_id monotonically increasing counter corresponding to the transaction
* @param details details about the wire transfer
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
* @param reply response details
*/
static enum GNUNET_GenericReturnValue
static void
debit_history_cb (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t serial_id,
const struct TALER_BANK_DebitDetails *details,
const json_t *json)
const struct TALER_BANK_DebitHistoryResponse *reply)
{
(void) cls;
dhh = NULL;
if (MHD_HTTP_OK != http_status)
{
if ( (MHD_HTTP_NO_CONTENT != http_status) ||
(TALER_EC_NONE != ec) )
{
if (0 == http_status)
switch (reply->http_status)
{
case 0:
fprintf (stderr,
"Failed to obtain HTTP reply from `%s'\n",
auth.wire_gateway_url);
}
else
{
fprintf (stderr,
"Failed to obtain debit history from `%s': HTTP status %u (%s)\n",
auth.wire_gateway_url,
http_status,
TALER_ErrorCode_get_hint (ec));
}
if (NULL != json)
json_dumpf (json,
stderr,
JSON_INDENT (2));
global_ret = 2;
GNUNET_SCHEDULER_shutdown ();
return GNUNET_NO;
}
break;
case MHD_HTTP_NO_CONTENT:
fprintf (stdout,
"End of transactions list.\n");
"No transactions.\n");
global_ret = 0;
GNUNET_SCHEDULER_shutdown ();
return GNUNET_NO;
}
break;
case MHD_HTTP_OK:
for (unsigned int i = 0; i<reply->details.success.details_length; i++)
{
const struct TALER_BANK_DebitDetails *dd =
&reply->details.success.details[i];
/* If credit/debit accounts were specified, use as a filter */
if ( (NULL != credit_account) &&
(0 != strcasecmp (credit_account,
details->credit_account_uri) ) )
return GNUNET_OK;
dd->credit_account_uri) ) )
continue;
if ( (NULL != debit_account) &&
(0 != strcasecmp (debit_account,
details->debit_account_uri) ) )
return GNUNET_OK;
dd->debit_account_uri) ) )
continue;
fprintf (stdout,
"%llu: %s->%s (%s) over %s at %s\n",
(unsigned long long) serial_id,
details->debit_account_uri,
details->credit_account_uri,
TALER_B2S (&details->wtid),
TALER_amount2s (&details->amount),
GNUNET_TIME_timestamp2s (details->execution_date));
return GNUNET_OK;
(unsigned long long) dd->serial_id,
dd->debit_account_uri,
dd->credit_account_uri,
TALER_B2S (&dd->wtid),
TALER_amount2s (&dd->amount),
GNUNET_TIME_timestamp2s (dd->execution_date));
}
global_ret = 0;
break;
default:
fprintf (stderr,
"Failed to obtain debit history from `%s': HTTP status %u (%s)\n",
auth.wire_gateway_url,
reply->http_status,
TALER_ErrorCode_get_hint (reply->ec));
if (NULL != reply->response)
json_dumpf (reply->response,
stderr,
JSON_INDENT (2));
global_ret = 2;
break;
}
GNUNET_SCHEDULER_shutdown ();
}

View File

@ -290,7 +290,6 @@ batch_deposit_transaction (void *cls,
mhd_ret);
if (qs < 0)
return qs;
qs = TEH_plugin->do_deposit (
TEH_plugin->cls,
deposit,

View File

@ -74,8 +74,7 @@ reply_deposit_success (
struct TALER_ExchangeSignatureP sig;
enum TALER_ErrorCode ec;
if (TALER_EC_NONE !=
(ec = TALER_exchange_online_deposit_confirmation_sign (
ec = TALER_exchange_online_deposit_confirmation_sign (
&TEH_keys_exchange_sign_,
h_contract_terms,
h_wire,
@ -87,7 +86,8 @@ reply_deposit_success (
coin_pub,
merchant,
&pub,
&sig)))
&sig);
if (TALER_EC_NONE != ec)
{
return TALER_MHD_reply_with_ec (connection,
ec,
@ -187,8 +187,6 @@ deposit_transaction (void *cls,
mhd_ret);
if (qs < 0)
return qs;
/* If the deposit has a policy associated to it, persist it. This will
* insert or update the record. */
if (dc->has_policy)
@ -203,8 +201,6 @@ deposit_transaction (void *cls,
if (qs < 0)
return qs;
}
qs = TEH_plugin->do_deposit (
TEH_plugin->cls,
dc->deposit,

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,8 @@
#include "pg_helper.h"
#include "pg_setup_wire_target.h"
#include "pg_compute_shard.h"
enum GNUNET_DB_QueryStatus
TEH_PG_insert_deposit (void *cls,
struct GNUNET_TIME_Timestamp exchange_timestamp,

View File

@ -260,6 +260,11 @@ struct TALER_BANK_CreditHistoryHandle;
*/
struct TALER_BANK_CreditDetails
{
/**
* Serial ID of the wire transfer.
*/
uint64_t serial_id;
/**
* Amount that was transferred
*/
@ -271,49 +276,85 @@ struct TALER_BANK_CreditDetails
struct GNUNET_TIME_Timestamp execution_date;
/**
* Reserve public key encoded in the wire
* transfer subject.
* Reserve public key encoded in the wire transfer subject.
*/
struct TALER_ReservePublicKeyP reserve_pub;
/**
* payto://-URL of the source account that
* send the funds.
* payto://-URL of the source account that send the funds.
*/
const char *debit_account_uri;
/**
* payto://-URL of the target account that
* received the funds.
* payto://-URL of the target account that received the funds.
*/
const char *credit_account_uri;
};
/**
* Response details for a history request.
*/
struct TALER_BANK_CreditHistoryResponse
{
/**
* HTTP status. Note that #MHD_HTTP_OK and #MHD_HTTP_NO_CONTENT are both
* successful replies, but @e details will only contain @e success information
* if this is set to #MHD_HTTP_OK.
*/
unsigned int http_status;
/**
* Taler error code, #TALER_EC_NONE on success.
*/
enum TALER_ErrorCode ec;
/**
* Full response, NULL if body was not in JSON format.
*/
const json_t *response;
/**
* Details returned depending on the @e http_status.
*/
union
{
/**
* Details if status was #MHD_HTTP_OK
*/
struct
{
/**
* Array of transactions recevied.
*/
const struct TALER_BANK_CreditDetails *details;
/**
* Length of the @e details array.
*/
unsigned int details_length;
} success;
} details;
};
/**
* Callbacks of this type are used to serve the result of asking
* the bank for the credit transaction history.
*
* @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
* 0 if the bank's reply is bogus (fails to follow the protocol),
* #MHD_HTTP_NO_CONTENT if there are no more results; on success the
* last callback is always of this status (even if `abs(num_results)` were
* already returned).
* @param ec detailed error code
* @param serial_id monotonically increasing counter corresponding to the transaction
* @param details details about the wire transfer
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
* @param reply details about the response
*/
typedef enum GNUNET_GenericReturnValue
typedef void
(*TALER_BANK_CreditHistoryCallback)(
void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t serial_id,
const struct TALER_BANK_CreditDetails *details,
const json_t *json);
const struct TALER_BANK_CreditHistoryResponse *reply);
/**
@ -369,6 +410,11 @@ struct TALER_BANK_DebitHistoryHandle;
*/
struct TALER_BANK_DebitDetails
{
/**
* Serial ID of the wire transfer.
*/
uint64_t serial_id;
/**
* Amount that was transferred
*/
@ -390,44 +436,81 @@ struct TALER_BANK_DebitDetails
const char *exchange_base_url;
/**
* payto://-URI of the source account that
* send the funds.
* payto://-URI of the source account that send the funds.
*/
const char *debit_account_uri;
/**
* payto://-URI of the target account that
* received the funds.
* payto://-URI of the target account that received the funds.
*/
const char *credit_account_uri;
};
/**
* Response details for a history request.
*/
struct TALER_BANK_DebitHistoryResponse
{
/**
* HTTP status. Note that #MHD_HTTP_OK and #MHD_HTTP_NO_CONTENT are both
* successful replies, but @e details will only contain @e success information
* if this is set to #MHD_HTTP_OK.
*/
unsigned int http_status;
/**
* Taler error code, #TALER_EC_NONE on success.
*/
enum TALER_ErrorCode ec;
/**
* Full response, NULL if body was not in JSON format.
*/
const json_t *response;
/**
* Details returned depending on the @e http_status.
*/
union
{
/**
* Details if status was #MHD_HTTP_OK
*/
struct
{
/**
* Array of transactions initiated.
*/
const struct TALER_BANK_DebitDetails *details;
/**
* Length of the @e details array.
*/
unsigned int details_length;
} success;
} details;
};
/**
* Callbacks of this type are used to serve the result of asking
* the bank for the debit transaction history.
*
* @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
* 0 if the bank's reply is bogus (fails to follow the protocol),
* #MHD_HTTP_NO_CONTENT if there are no more results; on success the
* last callback is always of this status (even if `abs(num_results)` were
* already returned).
* @param ec detailed error code
* @param serial_id monotonically increasing counter corresponding to the transaction
* @param details details about the wire transfer
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
* @param reply details about the response
*/
typedef enum GNUNET_GenericReturnValue
typedef void
(*TALER_BANK_DebitHistoryCallback)(
void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t serial_id,
const struct TALER_BANK_DebitDetails *details,
const json_t *json);
const struct TALER_BANK_DebitHistoryResponse *reply);
/**

View File

@ -370,99 +370,86 @@ check_result (struct History *h,
* finally check it against what the bank returned.
*
* @param cls closure.
* @param http_status HTTP response code, #MHD_HTTP_OK (200)
* for successful status request 0 if the bank's reply is
* bogus (fails to follow the protocol),
* #MHD_HTTP_NO_CONTENT if there are no more results; on
* success the last callback is always of this status
* (even if `abs(num_results)` were already returned).
* @param ec taler status code.
* @param row_id monotonically increasing counter corresponding to
* the transaction.
* @param details details about the wire transfer.
* @param json detailed response from the HTTPD, or NULL if
* reply was not in JSON.
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
* @param chr http response details
*/
static enum GNUNET_GenericReturnValue
static void
history_cb (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t row_id,
const struct TALER_BANK_CreditDetails *details,
const json_t *json)
const struct TALER_BANK_CreditHistoryResponse *chr)
{
struct TALER_TESTING_Interpreter *is = cls;
struct HistoryState *hs = is->commands[is->ip].cls;
(void) row_id;
if (NULL == details)
{
hs->hh = NULL;
if ( (MHD_HTTP_NOT_FOUND == http_status) &&
(0 == hs->total) )
{
/* not found is OK for empty history */
TALER_TESTING_interpreter_next (is);
return GNUNET_OK;
}
if ( (hs->results_obtained != hs->total) ||
(hs->failed) ||
(MHD_HTTP_NO_CONTENT != http_status) )
switch (chr->http_status)
{
case 0:
GNUNET_break (0);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Expected history of length %u, got %llu;"
" HTTP status code: %u/%d, failed: %d\n",
hs->total,
(unsigned long long) hs->results_obtained,
http_status,
(int) ec,
hs->failed ? 1 : 0);
print_expected (hs->h,
hs->total,
UINT_MAX);
TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR;
}
TALER_TESTING_interpreter_next (is);
return GNUNET_OK;
}
if (MHD_HTTP_OK != http_status)
goto error;
case MHD_HTTP_OK:
for (unsigned int i = 0; i<chr->details.success.details_length; i++)
{
hs->hh = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unwanted response code from /history/incoming: %u\n",
http_status);
TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR;
}
const struct TALER_BANK_CreditDetails *cd =
&chr->details.success.details[i];
/* check current element */
if (GNUNET_OK !=
check_result (hs->h,
hs->total,
hs->results_obtained,
details))
cd))
{
char *acc;
GNUNET_break (0);
acc = json_dumps (json,
json_dumpf (chr->response,
stderr,
JSON_COMPACT);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Result %u was `%s'\n",
(unsigned int) hs->results_obtained++,
acc);
if (NULL != acc)
free (acc);
hs->failed = true;
hs->hh = NULL;
TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR;
return;
}
hs->results_obtained++;
return GNUNET_OK;
}
TALER_TESTING_interpreter_next (is);
return;
case MHD_HTTP_NO_CONTENT:
if (0 == hs->total)
{
/* not found is OK for empty history */
TALER_TESTING_interpreter_next (is);
return;
}
GNUNET_break (0);
goto error;
case MHD_HTTP_NOT_FOUND:
if (0 == hs->total)
{
/* not found is OK for empty history */
TALER_TESTING_interpreter_next (is);
return;
}
GNUNET_break (0);
goto error;
default:
hs->hh = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unwanted response code from /history/incoming: %u\n",
chr->http_status);
TALER_TESTING_interpreter_fail (is);
return;
}
error:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Expected history of length %u, got %llu;"
" HTTP status code: %u/%d, failed: %d\n",
hs->total,
(unsigned long long) hs->results_obtained,
chr->http_status,
(int) chr->ec,
hs->failed ? 1 : 0);
print_expected (hs->h,
hs->total,
UINT_MAX);
TALER_TESTING_interpreter_fail (is);
}

View File

@ -362,99 +362,86 @@ check_result (struct History *h,
* finally check it against what the bank returned.
*
* @param cls closure.
* @param http_status HTTP response code, #MHD_HTTP_OK (200)
* for successful status request 0 if the bank's reply is
* bogus (fails to follow the protocol),
* #MHD_HTTP_NO_CONTENT if there are no more results; on
* success the last callback is always of this status
* (even if `abs(num_results)` were already returned).
* @param ec taler status code.
* @param row_id monotonically increasing counter corresponding to
* the transaction.
* @param details details about the wire transfer.
* @param json detailed response from the HTTPD, or NULL if
* reply was not in JSON.
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
* @param dhr http response details
*/
static enum GNUNET_GenericReturnValue
static void
history_cb (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t row_id,
const struct TALER_BANK_DebitDetails *details,
const json_t *json)
const struct TALER_BANK_DebitHistoryResponse *dhr)
{
struct TALER_TESTING_Interpreter *is = cls;
struct HistoryState *hs = is->commands[is->ip].cls;
(void) row_id;
if (NULL == details)
{
hs->hh = NULL;
if ( (MHD_HTTP_NOT_FOUND == http_status) &&
(0 == hs->total) )
{
/* not found is OK for empty history */
TALER_TESTING_interpreter_next (is);
return GNUNET_OK;
}
if ( (hs->results_obtained != hs->total) ||
(GNUNET_YES == hs->failed) ||
(MHD_HTTP_NO_CONTENT != http_status) )
switch (dhr->http_status)
{
case 0:
GNUNET_break (0);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Expected history of length %u, got %llu;"
" HTTP status code: %u/%d, failed: %d\n",
hs->total,
(unsigned long long) hs->results_obtained,
http_status,
(int) ec,
hs->failed);
print_expected (hs->h,
hs->total,
UINT_MAX);
TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR;
}
TALER_TESTING_interpreter_next (is);
return GNUNET_OK;
}
if (MHD_HTTP_OK != http_status)
goto error;
case MHD_HTTP_OK:
for (unsigned int i = 0; i<dhr->details.success.details_length; i++)
{
hs->hh = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unwanted response code from /history/outgoing: %u\n",
http_status);
TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR;
}
const struct TALER_BANK_DebitDetails *dd =
&dhr->details.success.details[i];
/* check current element */
if (GNUNET_OK !=
check_result (hs->h,
hs->total,
hs->results_obtained,
details))
dd))
{
char *acc;
GNUNET_break (0);
acc = json_dumps (json,
json_dumpf (dhr->response,
stderr,
JSON_COMPACT);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Result %u was `%s'\n",
(unsigned int) hs->results_obtained++,
acc);
if (NULL != acc)
free (acc);
hs->failed = GNUNET_YES;
hs->failed = true;
hs->hh = NULL;
TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR;
return;
}
hs->results_obtained++;
return GNUNET_OK;
}
TALER_TESTING_interpreter_next (is);
return;
case MHD_HTTP_NO_CONTENT:
if (0 == hs->total)
{
/* not found is OK for empty history */
TALER_TESTING_interpreter_next (is);
return;
}
GNUNET_break (0);
goto error;
case MHD_HTTP_NOT_FOUND:
if (0 == hs->total)
{
/* not found is OK for empty history */
TALER_TESTING_interpreter_next (is);
return;
}
GNUNET_break (0);
goto error;
default:
hs->hh = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unwanted response code from /history/incoming: %u\n",
dhr->http_status);
TALER_TESTING_interpreter_fail (is);
return;
}
error:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Expected history of length %u, got %llu;"
" HTTP status code: %u/%d, failed: %d\n",
hs->total,
(unsigned long long) hs->results_obtained,
dhr->http_status,
(int) dhr->ec,
hs->failed ? 1 : 0);
print_expected (hs->h,
hs->total,
UINT_MAX);
TALER_TESTING_interpreter_fail (is);
}

View File

@ -71,6 +71,7 @@ wirewatch_run (void *cls,
"-S", "1",
"-w", "0",
"-t", /* exit when done */
"-L", "DEBUG",
NULL);
if (NULL == ws->wirewatch_proc)
{