implement fakebank support (incl. tests) for #5005/#4964/4959

This commit is contained in:
Christian Grothoff 2017-05-07 21:11:56 +02:00
parent 56786aea5a
commit 18a020dd02
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
9 changed files with 461 additions and 40 deletions

View File

@ -57,7 +57,9 @@ check_PROGRAMS = \
test_bank_api_with_fakebank test_bank_api_with_fakebank
TESTS = \ TESTS = \
$(check_PROGRAMS) test_bank_api_with_fakebank
# For now, test_bank_api is known NOT to work (#5005, #4964, etc.)
# $(check_PROGRAMS)
test_bank_api_SOURCES = \ test_bank_api_SOURCES = \
test_bank_interpreter.c test_bank_interpreter.h \ test_bank_interpreter.c test_bank_interpreter.h \

View File

@ -78,6 +78,7 @@ handle_admin_add_incoming_finished (void *cls,
const json_t *json) const json_t *json)
{ {
struct TALER_BANK_AdminAddIncomingHandle *aai = cls; struct TALER_BANK_AdminAddIncomingHandle *aai = cls;
uint64_t serial_id = UINT64_MAX;
aai->job = NULL; aai->job = NULL;
switch (response_code) switch (response_code)
@ -85,6 +86,23 @@ handle_admin_add_incoming_finished (void *cls,
case 0: case 0:
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
{
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_uint64 ("serial_id",
&serial_id),
GNUNET_JSON_spec_end()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
response_code = 0;
break;
}
}
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the bank is buggy /* This should never happen, either us or the bank is buggy
@ -117,6 +135,7 @@ handle_admin_add_incoming_finished (void *cls,
} }
aai->cb (aai->cb_cls, aai->cb (aai->cb_cls,
response_code, response_code,
serial_id,
json); json);
TALER_BANK_admin_add_incoming_cancel (aai); TALER_BANK_admin_add_incoming_cancel (aai);
} }

View File

@ -94,7 +94,7 @@ parse_account_history (struct TALER_BANK_HistoryHandle *hh,
GNUNET_JSON_spec_uint64 ("row_id", GNUNET_JSON_spec_uint64 ("row_id",
&serial_id), &serial_id),
GNUNET_JSON_spec_string ("wt_subject", GNUNET_JSON_spec_string ("wt_subject",
&td.wire_transfer_subject), (const char **) &td.wire_transfer_subject),
GNUNET_JSON_spec_uint64 ("counterpart", GNUNET_JSON_spec_uint64 ("counterpart",
&other_account), &other_account),
GNUNET_JSON_spec_end() GNUNET_JSON_spec_end()

View File

@ -80,7 +80,7 @@ struct Transaction
/** /**
* Number of this transaction. * Number of this transaction.
*/ */
unsigned long long serial_id; uint64_t serial_id;
}; };
@ -112,7 +112,7 @@ struct TALER_FAKEBANK_Handle
/** /**
* Number of transactions. * Number of transactions.
*/ */
unsigned long long serial_counter; uint64_t serial_counter;
}; };
@ -337,12 +337,12 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
return MHD_NO; return MHD_NO;
} }
t->exchange_base_url = GNUNET_strdup (base_url); t->exchange_base_url = GNUNET_strdup (base_url);
t->serial_id = h->serial_counter++; t->serial_id = ++h->serial_counter;
t->date = GNUNET_TIME_absolute_get (); t->date = GNUNET_TIME_absolute_get ();
GNUNET_TIME_round_abs (&t->date); GNUNET_TIME_round_abs (&t->date);
GNUNET_CONTAINER_DLL_insert (h->transactions_head, GNUNET_CONTAINER_DLL_insert_tail (h->transactions_head,
h->transactions_tail, h->transactions_tail,
t); t);
} }
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Receiving incoming wire transfer: %llu->%llu from %s\n", "Receiving incoming wire transfer: %llu->%llu from %s\n",
@ -350,7 +350,36 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
(unsigned long long) t->credit_account, (unsigned long long) t->credit_account,
t->exchange_base_url); t->exchange_base_url);
json_decref (json); json_decref (json);
resp = MHD_create_response_from_buffer (0, "", MHD_RESPMEM_PERSISTENT);
/* Finally build response object */
{
void *json_str;
size_t json_len;
json = json_pack ("{s:I}",
"serial_id",
(json_int_t) t->serial_id);
json_str = json_dumps (json,
JSON_INDENT(2));
if (NULL == json_str)
{
GNUNET_break (0);
return MHD_NO;
}
json_len = strlen (json_str);
resp = MHD_create_response_from_buffer (json_len,
json_str,
MHD_RESPMEM_MUST_FREE);
if (NULL == resp)
{
GNUNET_break (0);
free (json_str);
return MHD_NO;
}
(void) MHD_add_response_header (resp,
MHD_HTTP_HEADER_CONTENT_TYPE,
"application/json");
}
ret = MHD_queue_response (connection, ret = MHD_queue_response (connection,
MHD_HTTP_OK, MHD_HTTP_OK,
resp); resp);
@ -395,7 +424,7 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
"direction"); "direction");
start = MHD_lookup_connection_value (connection, start = MHD_lookup_connection_value (connection,
MHD_GET_ARGUMENT_KIND, MHD_GET_ARGUMENT_KIND,
"start"); "start_row");
acc = MHD_lookup_connection_value (connection, acc = MHD_lookup_connection_value (connection,
MHD_GET_ARGUMENT_KIND, MHD_GET_ARGUMENT_KIND,
"account_number"); "account_number");
@ -433,31 +462,40 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
} }
if (NULL == dir) if (NULL == dir)
direction = TALER_BANK_DIRECTION_BOTH; direction = TALER_BANK_DIRECTION_BOTH;
else if (0 == strcasecmp (dir, "CREDIT")) else if (0 == strcasecmp (dir,
"CREDIT"))
direction = TALER_BANK_DIRECTION_CREDIT; direction = TALER_BANK_DIRECTION_CREDIT;
else else
direction = TALER_BANK_DIRECTION_DEBIT; direction = TALER_BANK_DIRECTION_DEBIT;
if (NULL == start) if (NULL == start)
start_number = (count > 0) ? 0 : UINT64_MAX;
if (UINT64_MAX == start_number)
{ {
pos = h->transactions_tail; if (count > 0)
pos = h->transactions_head;
else
pos = h->transactions_tail;
} }
else else
{ {
unsigned long long off = 0; if (NULL == h->transactions_head)
{
GNUNET_break (0);
return MHD_NO;
}
for (pos = h->transactions_head; for (pos = h->transactions_head;
off < start_number; pos->serial_id != start_number;
off++) pos = pos->next)
{ {
if (NULL == pos) if (NULL == pos)
{ {
GNUNET_break (0); GNUNET_break (0);
return MHD_NO; return MHD_NO;
} }
pos = pos->next;
} }
/* range is exclusive, skip the matching entry */
if (count > 0)
pos = pos->next;
if (count < 0)
pos = pos->prev;
} }
history = json_array (); history = json_array ();
while ( (NULL != pos) && while ( (NULL != pos) &&
@ -542,6 +580,9 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
free (json_str); free (json_str);
return MHD_NO; return MHD_NO;
} }
(void) MHD_add_response_header (resp,
MHD_HTTP_HEADER_CONTENT_TYPE,
"application/json");
ret = MHD_queue_response (connection, ret = MHD_queue_response (connection,
MHD_HTTP_OK, MHD_HTTP_OK,
resp); resp);

View File

@ -44,7 +44,7 @@ run (void *cls)
.label = "history-0", .label = "history-0",
.details.history.account_number = 1, .details.history.account_number = 1,
.details.history.direction = TALER_BANK_DIRECTION_BOTH, .details.history.direction = TALER_BANK_DIRECTION_BOTH,
.details.history.start_row = 0, .details.history.start_row_ref = NULL,
.details.history.num_results = 5 }, .details.history.num_results = 5 },
{ .oc = TBI_OC_ADMIN_ADD_INCOMING, { .oc = TBI_OC_ADMIN_ADD_INCOMING,
.label = "deposit-1", .label = "deposit-1",
@ -64,25 +64,25 @@ run (void *cls)
.label = "history-1c", .label = "history-1c",
.details.history.account_number = 1, .details.history.account_number = 1,
.details.history.direction = TALER_BANK_DIRECTION_CREDIT, .details.history.direction = TALER_BANK_DIRECTION_CREDIT,
.details.history.start_row = 0, .details.history.start_row_ref = NULL,
.details.history.num_results = 5 }, .details.history.num_results = 5 },
{ .oc = TBI_OC_HISTORY, { .oc = TBI_OC_HISTORY,
.label = "history-2d", .label = "history-2d",
.details.history.account_number = 2, .details.history.account_number = 2,
.details.history.direction = TALER_BANK_DIRECTION_DEBIT, .details.history.direction = TALER_BANK_DIRECTION_DEBIT,
.details.history.start_row = 0, .details.history.start_row_ref = NULL,
.details.history.num_results = 5 }, .details.history.num_results = 5 },
{ .oc = TBI_OC_HISTORY, { .oc = TBI_OC_HISTORY,
.label = "history-2dr", .label = "history-2dr",
.details.history.account_number = 2, .details.history.account_number = 2,
.details.history.direction = TALER_BANK_DIRECTION_DEBIT, .details.history.direction = TALER_BANK_DIRECTION_DEBIT,
.details.history.start_row = UINT64_MAX, .details.history.start_row_ref = NULL,
.details.history.num_results = -5 }, .details.history.num_results = -5 },
{ .oc = TBI_OC_HISTORY, { .oc = TBI_OC_HISTORY,
.label = "history-2fwd", .label = "history-2fwd",
.details.history.account_number = 2, .details.history.account_number = 2,
.details.history.direction = TALER_BANK_DIRECTION_DEBIT, .details.history.direction = TALER_BANK_DIRECTION_DEBIT,
.details.history.start_row = 1, .details.history.start_row_ref = "deposit-1",
.details.history.num_results = 5 }, .details.history.num_results = 5 },
{ .oc = TBI_OC_END } { .oc = TBI_OC_END }
}; };

View File

@ -43,7 +43,7 @@ run (void *cls)
.label = "history-0", .label = "history-0",
.details.history.account_number = 1, .details.history.account_number = 1,
.details.history.direction = TALER_BANK_DIRECTION_BOTH, .details.history.direction = TALER_BANK_DIRECTION_BOTH,
.details.history.start_row = 0, .details.history.start_row_ref = NULL,
.details.history.num_results = 1 }, .details.history.num_results = 1 },
/* Add EUR:5.01 to account 1 */ /* Add EUR:5.01 to account 1 */
{ .oc = TBI_OC_ADMIN_ADD_INCOMING, { .oc = TBI_OC_ADMIN_ADD_INCOMING,
@ -58,13 +58,13 @@ run (void *cls)
.label = "history-1c", .label = "history-1c",
.details.history.account_number = 1, .details.history.account_number = 1,
.details.history.direction = TALER_BANK_DIRECTION_CREDIT, .details.history.direction = TALER_BANK_DIRECTION_CREDIT,
.details.history.start_row = 0, .details.history.start_row_ref = NULL,
.details.history.num_results = 5 }, .details.history.num_results = 5 },
{ .oc = TBI_OC_HISTORY, { .oc = TBI_OC_HISTORY,
.label = "history-1d", .label = "history-1d",
.details.history.account_number = 1, .details.history.account_number = 1,
.details.history.direction = TALER_BANK_DIRECTION_DEBIT, .details.history.direction = TALER_BANK_DIRECTION_DEBIT,
.details.history.start_row = 0, .details.history.start_row_ref = NULL,
.details.history.num_results = 5 }, .details.history.num_results = 5 },
{ .oc = TBI_OC_ADMIN_ADD_INCOMING, { .oc = TBI_OC_ADMIN_ADD_INCOMING,
.label = "debit-2", .label = "debit-2",
@ -79,18 +79,18 @@ run (void *cls)
.details.admin_add_incoming.credit_account_no = 2, .details.admin_add_incoming.credit_account_no = 2,
.details.admin_add_incoming.debit_account_no = 3, .details.admin_add_incoming.debit_account_no = 3,
.details.admin_add_incoming.exchange_base_url = "https://exchange.org/", .details.admin_add_incoming.exchange_base_url = "https://exchange.org/",
.details.admin_add_incoming.amount = "PUDOS:3.21" }, .details.admin_add_incoming.amount = "PUDOS:3.22" },
{ .oc = TBI_OC_HISTORY, { .oc = TBI_OC_HISTORY,
.label = "history-2b", .label = "history-2b",
.details.history.account_number = 2, .details.history.account_number = 2,
.details.history.direction = TALER_BANK_DIRECTION_BOTH, .details.history.direction = TALER_BANK_DIRECTION_BOTH,
.details.history.start_row = 0, .details.history.start_row_ref = NULL,
.details.history.num_results = 5 }, .details.history.num_results = 5 },
{ .oc = TBI_OC_HISTORY, { .oc = TBI_OC_HISTORY,
.label = "history-2bi", .label = "history-2bi",
.details.history.account_number = 2, .details.history.account_number = 2,
.details.history.direction = TALER_BANK_DIRECTION_BOTH, .details.history.direction = TALER_BANK_DIRECTION_BOTH,
.details.history.start_row = 1, .details.history.start_row_ref = "debit-1",
.details.history.num_results = 5 }, .details.history.num_results = 5 },
/* check transfers arrived at fakebank */ /* check transfers arrived at fakebank */
{ .oc = TBI_OC_EXPECT_TRANSFER, { .oc = TBI_OC_EXPECT_TRANSFER,

View File

@ -92,6 +92,9 @@ static void
fail (struct InterpreterState *is) fail (struct InterpreterState *is)
{ {
*is->resultp = GNUNET_SYSERR; *is->resultp = GNUNET_SYSERR;
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Interpreter failed at command `%s'\n",
is->commands[is->ip].label);
GNUNET_SCHEDULER_shutdown (); GNUNET_SCHEDULER_shutdown ();
} }
@ -128,6 +131,307 @@ find_command (const struct InterpreterState *is,
} }
/**
* Item in the transaction history, as reconstructed from the
* command history.
*/
struct History
{
/**
* Wire details.
*/
struct TALER_BANK_TransferDetails details;
/**
* Serial ID of the wire transfer.
*/
uint64_t serial_id;
/**
* Direction of the transfer.
*/
enum TALER_BANK_Direction direction;
};
/**
* Build history of transactions matching the current
* command in @a is.
*
* @param is interpreter state
* @param[out] rh history array to initialize
* @return number of entries in @a rh
*/
static uint64_t
build_history (struct InterpreterState *is,
struct History **rh)
{
const struct TBI_Command *cmd = &is->commands[is->ip];
uint64_t total;
struct History *h;
const struct TBI_Command *ref;
int inc;
unsigned int start;
unsigned int end;
int ok;
GNUNET_assert (TBI_OC_HISTORY == cmd->oc);
if (NULL != cmd->details.history.start_row_ref)
{
ref = find_command (is,
cmd->details.history.start_row_ref);
GNUNET_assert (NULL != ref);
}
else
{
ref = NULL;
}
GNUNET_assert (0 != cmd->details.history.num_results);
if (0 == is->ip)
{
*rh = NULL;
return 0;
}
if (cmd->details.history.num_results > 0)
{
inc = 1;
start = 0;
end = is->ip - 1;
}
else
{
inc = -1;
start = is->ip - 1;
end = 0;
}
total = 0;
ok = GNUNET_NO;
if (NULL == ref)
ok = GNUNET_YES;
for (unsigned int off = start;off != end + inc; off += inc)
{
const struct TBI_Command *pos = &is->commands[off];
if (TBI_OC_ADMIN_ADD_INCOMING != pos->oc)
continue;
if ( (NULL != ref) &&
(ref->details.admin_add_incoming.serial_id ==
pos->details.admin_add_incoming.serial_id) )
{
total = 0;
ok = GNUNET_YES;
continue;
}
if (GNUNET_NO == ok)
continue; /* skip until we find the marker */
if (total >= cmd->details.history.num_results * inc)
break; /* hit limit specified by command */
if ( ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_CREDIT)) &&
(cmd->details.history.account_number ==
pos->details.admin_add_incoming.credit_account_no)) ||
( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_DEBIT)) &&
(cmd->details.history.account_number ==
pos->details.admin_add_incoming.debit_account_no)) )
total++; /* found matching record */
}
GNUNET_assert (GNUNET_YES == ok);
if (0 == total)
{
*rh = NULL;
return 0;
}
GNUNET_assert (total < UINT_MAX);
h = GNUNET_new_array ((unsigned int) total,
struct History);
total = 0;
ok = GNUNET_NO;
if (NULL == ref)
ok = GNUNET_YES;
for (unsigned int off = start;off != end + inc; off += inc)
{
const struct TBI_Command *pos = &is->commands[off];
if (TBI_OC_ADMIN_ADD_INCOMING != pos->oc)
continue;
if ( (NULL != ref) &&
(ref->details.admin_add_incoming.serial_id ==
pos->details.admin_add_incoming.serial_id) )
{
total = 0;
ok = GNUNET_YES;
continue;
}
if (GNUNET_NO == ok)
continue; /* skip until we find the marker */
if (total >= cmd->details.history.num_results * inc)
break; /* hit limit specified by command */
if ( ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_CREDIT)) &&
(cmd->details.history.account_number ==
pos->details.admin_add_incoming.credit_account_no)) &&
( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_DEBIT)) &&
(cmd->details.history.account_number ==
pos->details.admin_add_incoming.debit_account_no)) )
{
GNUNET_break (0);
continue;
}
if ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_CREDIT)) &&
(cmd->details.history.account_number ==
pos->details.admin_add_incoming.credit_account_no))
{
h[total].direction = TALER_BANK_DIRECTION_CREDIT;
h[total].details.account_details
= json_pack ("{s:s, s:s, s:I}",
"type",
"test",
"bank_uri",
"http://localhost:8081",
"account_number",
(json_int_t) pos->details.admin_add_incoming.debit_account_no);
GNUNET_assert (NULL != h[total].details.account_details);
}
if ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_DEBIT)) &&
(cmd->details.history.account_number ==
pos->details.admin_add_incoming.debit_account_no))
{
h[total].direction = TALER_BANK_DIRECTION_DEBIT;
h[total].details.account_details
= json_pack ("{s:s, s:s, s:I}",
"type",
"test",
"bank_uri",
"http://localhost:8081",
"account_number",
(json_int_t) pos->details.admin_add_incoming.credit_account_no);
GNUNET_assert (NULL != h[total].details.account_details);
}
if ( ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_CREDIT)) &&
(cmd->details.history.account_number ==
pos->details.admin_add_incoming.credit_account_no)) ||
( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_DEBIT)) &&
(cmd->details.history.account_number ==
pos->details.admin_add_incoming.debit_account_no)) )
{
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (pos->details.admin_add_incoming.amount,
&h[total].details.amount));
/* h[total].execution_date; // unknown here */
h[total].serial_id
= pos->details.admin_add_incoming.serial_id;
h[total].details.wire_transfer_subject
= GNUNET_STRINGS_data_to_string_alloc (&pos->details.admin_add_incoming.wtid,
sizeof (struct TALER_WireTransferIdentifierRawP));
total++;
}
}
*rh = h;
return total;
}
/**
* Free history @a h of length @a h_len.
*
* @param h history array to free
* @param h_len number of entries in @a h
*/
static void
free_history (struct History *h,
uint64_t h_len)
{
for (uint64_t off = 0;off<h_len;off++)
{
GNUNET_free (h[off].details.wire_transfer_subject);
json_decref (h[off].details.account_details);
}
GNUNET_free_non_null (h);
}
/**
* Compute how many results we expect to be returned for
* the history command at @a is.
*
* @param is the interpreter state to inspect
* @return number of results expected
*/
static uint64_t
compute_result_count (struct InterpreterState *is)
{
uint64_t total;
struct History *h;
total = build_history (is,
&h);
free_history (h,
total);
return total;
}
/**
* Check that @a dir and @a details are the transaction
* results we expect at offset @a off in the history of
* the current command executed by @a is
*
* @param is the interpreter state we are in
* @param off the offset of the result
* @param dir the direction of the transaction
* @param details the transaction details to check
* @return #GNUNET_OK if the transaction is what we expect
*/
static int
check_result (struct InterpreterState *is,
unsigned int off,
enum TALER_BANK_Direction dir,
const struct TALER_BANK_TransferDetails *details)
{
uint64_t total;
struct History *h;
total = build_history (is,
&h);
if (off >= total)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Test says history has at most %u results, but got result #%u to check\n",
(unsigned int) total,
off);
free_history (h,
total);
return GNUNET_SYSERR;
}
if (h[off].direction != dir)
{
GNUNET_break (0);
free_history (h,
total);
return GNUNET_SYSERR;
}
if ( (0 != strcmp (h[off].details.wire_transfer_subject,
details->wire_transfer_subject)) ||
(0 != TALER_amount_cmp (&h[off].details.amount,
&details->amount)) ||
(1 != json_equal (h[off].details.account_details,
details->account_details)) )
{
GNUNET_break (0);
free_history (h,
total);
return GNUNET_SYSERR;
}
free_history (h,
total);
return GNUNET_OK;
}
/** /**
* Run the main interpreter loop that performs bank operations. * Run the main interpreter loop that performs bank operations.
* *
@ -143,17 +447,20 @@ interpreter_run (void *cls);
* @param cls closure with the interpreter state * @param cls closure with the interpreter state
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * @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) * 0 if the bank's reply is bogus (fails to follow the protocol)
* @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON * @param json detailed response from the HTTPD, or NULL if reply was not in JSON
*/ */
static void static void
add_incoming_cb (void *cls, add_incoming_cb (void *cls,
unsigned int http_status, unsigned int http_status,
uint64_t serial_id,
const json_t *json) const json_t *json)
{ {
struct InterpreterState *is = cls; struct InterpreterState *is = cls;
struct TBI_Command *cmd = &is->commands[is->ip]; struct TBI_Command *cmd = &is->commands[is->ip];
cmd->details.admin_add_incoming.aih = NULL; cmd->details.admin_add_incoming.aih = NULL;
cmd->details.admin_add_incoming.serial_id = serial_id;
if (cmd->details.admin_add_incoming.expected_response_code != http_status) if (cmd->details.admin_add_incoming.expected_response_code != http_status)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -203,12 +510,31 @@ history_cb (void *cls,
if (MHD_HTTP_OK != http_status) if (MHD_HTTP_OK != http_status)
{ {
cmd->details.history.hh = NULL; cmd->details.history.hh = NULL;
if ( (cmd->details.history.results_obtained !=
compute_result_count (is)) ||
(GNUNET_YES ==
cmd->details.history.failed) )
{
GNUNET_break (0);
fail (is);
return;
}
is->ip++; is->ip++;
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
is); is);
return; return;
} }
/* FIXME: check history data is OK! (#4959) */ if (GNUNET_OK !=
check_result (is,
cmd->details.history.results_obtained,
dir,
details))
{
GNUNET_break (0);
cmd->details.history.failed = GNUNET_YES;
return;
}
cmd->details.history.results_obtained++;
} }
@ -227,6 +553,7 @@ interpreter_run (void *cls)
struct TALER_Amount amount; struct TALER_Amount amount;
const struct GNUNET_SCHEDULER_TaskContext *tc; const struct GNUNET_SCHEDULER_TaskContext *tc;
struct TALER_BANK_AuthenticationData auth; struct TALER_BANK_AuthenticationData auth;
uint64_t rowid;
is->task = NULL; is->task = NULL;
tc = GNUNET_SCHEDULER_get_task_context (); tc = GNUNET_SCHEDULER_get_task_context ();
@ -280,13 +607,27 @@ interpreter_run (void *cls)
} }
return; return;
case TBI_OC_HISTORY: case TBI_OC_HISTORY:
if (NULL != cmd->details.history.start_row_ref)
{
ref = find_command (is,
cmd->details.history.start_row_ref);
GNUNET_assert (NULL != ref);
}
else
{
ref = NULL;
}
if (NULL != ref)
rowid = ref->details.admin_add_incoming.serial_id;
else
rowid = UINT64_MAX;
cmd->details.history.hh cmd->details.history.hh
= TALER_BANK_history (is->ctx, = TALER_BANK_history (is->ctx,
"http://localhost:8081", "http://localhost:8081",
&auth, &auth,
cmd->details.history.account_number, cmd->details.history.account_number,
cmd->details.history.direction, cmd->details.history.direction,
cmd->details.history.start_row, rowid,
cmd->details.history.num_results, cmd->details.history.num_results,
&history_cb, &history_cb,
is); is);
@ -300,6 +641,7 @@ interpreter_run (void *cls)
case TBI_OC_EXPECT_TRANSFER: case TBI_OC_EXPECT_TRANSFER:
ref = find_command (is, ref = find_command (is,
cmd->details.expect_transfer.cmd_ref); cmd->details.expect_transfer.cmd_ref);
GNUNET_assert (NULL != ref);
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (ref->details.admin_add_incoming.amount, TALER_string_to_amount (ref->details.admin_add_incoming.amount,
&amount)); &amount));

View File

@ -125,6 +125,11 @@ struct TBI_Command
*/ */
struct TALER_BANK_AdminAddIncomingHandle *aih; struct TALER_BANK_AdminAddIncomingHandle *aih;
/**
* The serial ID for this record, as returned by the bank.
*/
uint64_t serial_id;
} admin_add_incoming; } admin_add_incoming;
struct { struct {
@ -140,10 +145,10 @@ struct TBI_Command
enum TALER_BANK_Direction direction; enum TALER_BANK_Direction direction;
/** /**
* At which offset do we start? * At which serial ID do we start? References the respective @e
* Use UINT64_MAX or 0 for the extremes. * admin_add_incoming command. Use NULL for the extremes.
*/ */
uint64_t start_row; const char *start_row_ref;
/** /**
* How many results should be returned (if available)? * How many results should be returned (if available)?
@ -155,6 +160,16 @@ struct TBI_Command
*/ */
struct TALER_BANK_HistoryHandle *hh; struct TALER_BANK_HistoryHandle *hh;
/**
* How many results did we actually get?
*/
uint64_t results_obtained;
/**
* Set to #GNUNET_YES if we encountered a problem.
*/
int failed;
} history; } history;
/** /**

View File

@ -98,11 +98,13 @@ struct TALER_BANK_AdminAddIncomingHandle;
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * @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) * 0 if the bank's reply is bogus (fails to follow the protocol)
* @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON * @param json detailed response from the HTTPD, or NULL if reply was not in JSON
*/ */
typedef void typedef void
(*TALER_BANK_AdminAddIncomingResultCallback) (void *cls, (*TALER_BANK_AdminAddIncomingResultCallback) (void *cls,
unsigned int http_status, unsigned int http_status,
uint64_t serial_id,
const json_t *json); const json_t *json);
@ -188,22 +190,22 @@ struct TALER_BANK_HistoryHandle;
struct TALER_BANK_TransferDetails struct TALER_BANK_TransferDetails
{ {
/** /**
* amount that was transferred * Amount that was transferred
*/ */
struct TALER_Amount amount; struct TALER_Amount amount;
/** /**
* when did the transfer happen * Time of the the transfer
*/ */
struct GNUNET_TIME_Absolute execution_date; struct GNUNET_TIME_Absolute execution_date;
/** /**
* wire transfer subject * Wire transfer subject
*/ */
const char *wire_transfer_subject; char *wire_transfer_subject;
/** /**
* what was the other account that was involved * The other account that was involved
*/ */
json_t *account_details; json_t *account_details;
}; };