automated refunds of expired reserves now work and tested, fixes #4956

This commit is contained in:
Christian Grothoff 2017-06-11 17:04:54 +02:00
parent ba17729f65
commit 0580168c0e
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
6 changed files with 242 additions and 48 deletions

View File

@ -1,3 +1,7 @@
Sun Jun 11 17:03:56 CEST 2017
Finish implementation and testing of automated refunding
of expired reserves (#4956). -CG
Tue Jun 6 13:53:34 CEST 2017 Tue Jun 6 13:53:34 CEST 2017
Releasing taler-exchange 0.3.0. -CG Releasing taler-exchange 0.3.0. -CG

View File

@ -507,6 +507,12 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
GNUNET_break (0); GNUNET_break (0);
return MHD_NO; return MHD_NO;
} }
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Client asked for up to %lld results of type %s for account %llu starting at %s\n",
count,
dir,
(unsigned long long) account_number,
start);
if (NULL == dir) if (NULL == dir)
direction = TALER_BANK_DIRECTION_BOTH; direction = TALER_BANK_DIRECTION_BOTH;
else if (0 == strcasecmp (dir, else if (0 == strcasecmp (dir,
@ -544,6 +550,7 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
/* list is empty */ /* list is empty */
pos = NULL; pos = NULL;
} }
history = json_array (); history = json_array ();
while ( (NULL != pos) && while ( (NULL != pos) &&
(0 != count) ) (0 != count) )
@ -551,6 +558,12 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
json_t *trans; json_t *trans;
char *subject; char *subject;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Found transaction over %s from %llu to %llu\n",
TALER_amount2s (&pos->amount),
(unsigned long long) pos->debit_account,
(unsigned long long) pos->credit_account);
if (! ( ( (account_number == pos->debit_account) && if (! ( ( (account_number == pos->debit_account) &&
(0 != (direction & TALER_BANK_DIRECTION_DEBIT)) ) || (0 != (direction & TALER_BANK_DIRECTION_DEBIT)) ) ||
( (account_number == pos->credit_account) && ( (account_number == pos->credit_account) &&
@ -595,6 +608,8 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
struct MHD_Response *resp; struct MHD_Response *resp;
json_decref (history); json_decref (history);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Returning empty transaction history\n");
resp = MHD_create_response_from_buffer (0, resp = MHD_create_response_from_buffer (0,
"", "",
MHD_RESPMEM_PERSISTENT); MHD_RESPMEM_PERSISTENT);

View File

@ -196,6 +196,11 @@ struct CloseTransferContext
* Wire transfer method. * Wire transfer method.
*/ */
char *type; char *type;
/**
* Wire plugin used for closing the reserve.
*/
struct WirePlugin *wp;
}; };
@ -428,8 +433,8 @@ find_plugin (const char *type)
static void static void
shutdown_task (void *cls) shutdown_task (void *cls)
{ {
struct WirePlugin *wp; GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Running shutdown\n");
if (NULL != task) if (NULL != task)
{ {
GNUNET_SCHEDULER_cancel (task); GNUNET_SCHEDULER_cancel (task);
@ -464,16 +469,32 @@ shutdown_task (void *cls)
au = NULL; au = NULL;
GNUNET_free (au); GNUNET_free (au);
} }
TALER_EXCHANGEDB_plugin_unload (db_plugin); if (NULL != ctc)
while (NULL != (wp = wp_head))
{ {
GNUNET_CONTAINER_DLL_remove (wp_head, ctc->wp->wire_plugin->prepare_wire_transfer_cancel (ctc->wp->wire_plugin->cls,
wp_tail, ctc->ph);
wp); ctc->ph = NULL;
TALER_WIRE_plugin_unload (wp->wire_plugin); db_plugin->rollback (db_plugin->cls,
TALER_EXCHANGEDB_fees_free (wp->af); ctc->session);
GNUNET_free (wp->type); GNUNET_free (ctc->type);
GNUNET_free (wp); GNUNET_free (ctc);
ctc = NULL;
}
TALER_EXCHANGEDB_plugin_unload (db_plugin);
{
struct WirePlugin *wp;
while (NULL != (wp = wp_head))
{
GNUNET_CONTAINER_DLL_remove (wp_head,
wp_tail,
wp);
TALER_WIRE_plugin_unload (wp->wire_plugin);
TALER_EXCHANGEDB_fees_free (wp->af);
GNUNET_free (wp->type);
GNUNET_free (wp);
}
} }
GNUNET_CONFIGURATION_destroy (cfg); GNUNET_CONFIGURATION_destroy (cfg);
cfg = NULL; cfg = NULL;
@ -740,6 +761,16 @@ static void
run_aggregation (void *cls); run_aggregation (void *cls);
/**
* Execute the wire transfers that we have committed to
* do.
*
* @param cls pointer to an `int` which we will return from main()
*/
static void
run_transfers (void *cls);
/** /**
* Perform a database commit. If it fails, print a warning. * Perform a database commit. If it fails, print a warning.
* *
@ -777,6 +808,9 @@ prepare_close_cb (void *cls,
size_t buf_size) size_t buf_size)
{ {
GNUNET_assert (cls == ctc); GNUNET_assert (cls == ctc);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Prepared for reserve closing\n");
ctc->ph = NULL; ctc->ph = NULL;
if (NULL == buf) if (NULL == buf)
{ {
@ -817,7 +851,9 @@ prepare_close_cb (void *cls,
GNUNET_free (ctc->type); GNUNET_free (ctc->type);
GNUNET_free (ctc); GNUNET_free (ctc);
ctc = NULL; ctc = NULL;
task = GNUNET_SCHEDULER_add_now (&run_aggregation, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Reserve closure committed, running transfer\n");
task = GNUNET_SCHEDULER_add_now (&run_transfers,
NULL); NULL);
} }
@ -923,6 +959,12 @@ expired_reserve_cb (void *cls,
&wtid, &wtid,
left, left,
closing_fee); closing_fee);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Closing reserve %s over %s (%d, %d)\n",
TALER_B2S (reserve_pub),
TALER_amount2s (left),
ret,
iret);
if ( (GNUNET_OK == ret) && if ( (GNUNET_OK == ret) &&
(GNUNET_OK == iret) ) (GNUNET_OK == iret) )
{ {
@ -939,11 +981,12 @@ expired_reserve_cb (void *cls,
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
ctc = GNUNET_new (struct CloseTransferContext); ctc = GNUNET_new (struct CloseTransferContext);
ctc->wp = wp;
ctc->session = session; ctc->session = session;
ctc->type = GNUNET_strdup (type); ctc->type = GNUNET_strdup (type);
ctc->ph ctc->ph
= wp->wire_plugin->prepare_wire_transfer (wp->wire_plugin->cls, = wp->wire_plugin->prepare_wire_transfer (wp->wire_plugin->cls,
au->wire, account_details,
&amount_without_fee, &amount_without_fee,
exchange_base_url, exchange_base_url,
&wtid, &wtid,
@ -973,6 +1016,8 @@ expired_reserve_cb (void *cls,
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
/* Reserve balance was almost zero; just commit */ /* Reserve balance was almost zero; just commit */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Reserve was virtually empty, moving on\n");
(void) commit_or_warn (session); (void) commit_or_warn (session);
task = GNUNET_SCHEDULER_add_now (&run_reserve_closures, task = GNUNET_SCHEDULER_add_now (&run_reserve_closures,
NULL); NULL);
@ -998,7 +1043,7 @@ run_reserve_closures (void *cls)
tc = GNUNET_SCHEDULER_get_task_context (); tc = GNUNET_SCHEDULER_get_task_context ();
if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
return; return;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Checking for reserves to close\n"); "Checking for reserves to close\n");
if (NULL == (session = db_plugin->get_session (db_plugin->cls))) if (NULL == (session = db_plugin->get_session (db_plugin->cls)))
{ {
@ -1034,6 +1079,8 @@ run_reserve_closures (void *cls)
} }
if (GNUNET_NO == ret) if (GNUNET_NO == ret)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"No more idle reserves, going back to aggregation\n");
reserves_idle = GNUNET_YES; reserves_idle = GNUNET_YES;
db_plugin->rollback (db_plugin->cls, db_plugin->rollback (db_plugin->cls,
session); session);
@ -1063,13 +1110,13 @@ run_aggregation (void *cls)
tc = GNUNET_SCHEDULER_get_task_context (); tc = GNUNET_SCHEDULER_get_task_context ();
if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
return; return;
if (0 == (++swap % 2)) if (0 == (++swap % 2))
{ {
task = GNUNET_SCHEDULER_add_now (&run_reserve_closures, task = GNUNET_SCHEDULER_add_now (&run_reserve_closures,
NULL); NULL);
return; return;
} }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Checking for ready deposits to aggregate\n"); "Checking for ready deposits to aggregate\n");
if (NULL == (session = db_plugin->get_session (db_plugin->cls))) if (NULL == (session = db_plugin->get_session (db_plugin->cls)))
{ {
@ -1111,9 +1158,10 @@ run_aggregation (void *cls)
GNUNET_SCHEDULER_shutdown (); GNUNET_SCHEDULER_shutdown ();
return; return;
} }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"No more ready deposits, going to sleep\n"); "No more ready deposits, going to sleep\n");
if (GNUNET_YES == test_mode) if ( (GNUNET_YES == test_mode) &&
(swap >= 2) )
{ {
/* in test mode, shutdown if we end up being idle */ /* in test mode, shutdown if we end up being idle */
GNUNET_SCHEDULER_shutdown (); GNUNET_SCHEDULER_shutdown ();
@ -1121,7 +1169,8 @@ run_aggregation (void *cls)
else else
{ {
/* nothing to do, sleep for a minute and try again */ /* nothing to do, sleep for a minute and try again */
if (GNUNET_NO == reserves_idle) if ( (GNUNET_NO == reserves_idle) ||
(GNUNET_YES == test_mode) )
task = GNUNET_SCHEDULER_add_now (&run_reserve_closures, task = GNUNET_SCHEDULER_add_now (&run_reserve_closures,
NULL); NULL);
else else
@ -1257,16 +1306,6 @@ run_aggregation (void *cls)
} }
/**
* Execute the wire transfers that we have committed to
* do.
*
* @param cls pointer to an `int` which we will return from main()
*/
static void
run_transfers (void *cls);
/** /**
* Function to be called with the prepared transfer data. * Function to be called with the prepared transfer data.
* *
@ -1518,7 +1557,7 @@ run_transfers (void *cls)
const struct GNUNET_SCHEDULER_TaskContext *tc; const struct GNUNET_SCHEDULER_TaskContext *tc;
task = NULL; task = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Checking for pending wire transfers\n"); "Checking for pending wire transfers\n");
tc = GNUNET_SCHEDULER_get_task_context (); tc = GNUNET_SCHEDULER_get_task_context ();
if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))

View File

@ -229,7 +229,7 @@ history_cb (void *cls,
{ {
hh = NULL; hh = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"End of list. Committing progress!\n"); "End of list. Committing progress!\n");
ret = db_plugin->commit (db_plugin->cls, ret = db_plugin->commit (db_plugin->cls,
session); session);
@ -254,7 +254,7 @@ history_cb (void *cls,
NULL); NULL);
return GNUNET_OK; /* will be ignored anyway */ return GNUNET_OK; /* will be ignored anyway */
} }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Adding wire transfer over %s with subject `%s'\n", "Adding wire transfer over %s with subject `%s'\n",
TALER_amount2s (&details->amount), TALER_amount2s (&details->amount),
TALER_B2S (&details->reserve_pub)); TALER_B2S (&details->reserve_pub));
@ -301,7 +301,7 @@ find_transfers (void *cls)
int ret; int ret;
task = NULL; task = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Checking for incoming wire transfers\n"); "Checking for incoming wire transfers\n");
if (NULL == (session = db_plugin->get_session (db_plugin->cls))) if (NULL == (session = db_plugin->get_session (db_plugin->cls)))

View File

@ -155,7 +155,12 @@ struct Command
/** /**
* Subject of the transfer, set by the command. * Subject of the transfer, set by the command.
*/ */
const char *wtid; const char *subject;
/**
* Serial ID of the wire transfer as assigned by the bank.
*/
uint64_t serial_id;
} run_transfer; } run_transfer;
@ -262,7 +267,11 @@ interpreter (void *cls);
static void static void
next_command (struct State *state) next_command (struct State *state)
{ {
GNUNET_assert (NULL == int_task);
state->ioff++; state->ioff++;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Advancing to command %s\n",
state->commands[state->ioff].label);
int_task = GNUNET_SCHEDULER_add_now (&interpreter, int_task = GNUNET_SCHEDULER_add_now (&interpreter,
state); state);
} }
@ -274,6 +283,7 @@ next_command (struct State *state)
static void static void
fail (struct Command *cmd) fail (struct Command *cmd)
{ {
GNUNET_assert (NULL == int_task);
fprintf (stderr, fprintf (stderr,
"Testcase failed at command `%s'\n", "Testcase failed at command `%s'\n",
cmd->label); cmd->label);
@ -308,6 +318,8 @@ shutdown_action (void *cls)
{ {
struct State *state = cls; struct State *state = cls;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Running shutdown\n");
if (NULL != timeout_task) if (NULL != timeout_task)
{ {
GNUNET_SCHEDULER_cancel (timeout_task); GNUNET_SCHEDULER_cancel (timeout_task);
@ -364,10 +376,6 @@ shutdown_action (void *cls)
case OPCODE_RUN_TRANSFER: case OPCODE_RUN_TRANSFER:
break; break;
case OPCODE_WAIT: case OPCODE_WAIT:
state->ioff++;
int_task = GNUNET_SCHEDULER_add_delayed (cmd->details.wait_delay,
&interpreter,
state);
break; break;
case OPCODE_EXPECT_TRANSFER: case OPCODE_EXPECT_TRANSFER:
GNUNET_free_non_null (cmd->details.expect_transfer.subject); GNUNET_free_non_null (cmd->details.expect_transfer.subject);
@ -396,6 +404,9 @@ maint_child_death (void *cls)
struct Command *cmd = &state->commands[state->ioff]; struct Command *cmd = &state->commands[state->ioff];
char c[16]; char c[16];
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Child process died for command %s\n",
cmd->label);
pr = GNUNET_DISK_pipe_handle (sigpipe, pr = GNUNET_DISK_pipe_handle (sigpipe,
GNUNET_DISK_PIPE_END_READ); GNUNET_DISK_PIPE_END_READ);
GNUNET_break (0 < GNUNET_DISK_file_read (pr, GNUNET_break (0 < GNUNET_DISK_file_read (pr,
@ -404,12 +415,14 @@ maint_child_death (void *cls)
switch (cmd->opcode) switch (cmd->opcode)
{ {
case OPCODE_RUN_AGGREGATOR: case OPCODE_RUN_AGGREGATOR:
GNUNET_assert (NULL != cmd->details.aggregator.child_death_task);
cmd->details.aggregator.child_death_task = NULL; cmd->details.aggregator.child_death_task = NULL;
GNUNET_OS_process_wait (cmd->details.aggregator.aggregator_proc); GNUNET_OS_process_wait (cmd->details.aggregator.aggregator_proc);
GNUNET_OS_process_destroy (cmd->details.aggregator.aggregator_proc); GNUNET_OS_process_destroy (cmd->details.aggregator.aggregator_proc);
cmd->details.aggregator.aggregator_proc = NULL; cmd->details.aggregator.aggregator_proc = NULL;
break; break;
case OPCODE_RUN_WIREWATCH: case OPCODE_RUN_WIREWATCH:
GNUNET_assert (NULL != cmd->details.wirewatch.child_death_task);
cmd->details.wirewatch.child_death_task = NULL; cmd->details.wirewatch.child_death_task = NULL;
GNUNET_OS_process_wait (cmd->details.wirewatch.wirewatch_proc); GNUNET_OS_process_wait (cmd->details.wirewatch.wirewatch_proc);
GNUNET_OS_process_destroy (cmd->details.wirewatch.wirewatch_proc); GNUNET_OS_process_destroy (cmd->details.wirewatch.wirewatch_proc);
@ -423,7 +436,6 @@ maint_child_death (void *cls)
} }
/** /**
* Interprets the commands from the test program. * Interprets the commands from the test program.
* *
@ -435,6 +447,7 @@ interpreter (void *cls)
struct State *state = cls; struct State *state = cls;
struct Command *cmd = &state->commands[state->ioff]; struct Command *cmd = &state->commands[state->ioff];
GNUNET_assert (NULL != int_task);
int_task = NULL; int_task = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Running command %u (%s)\n", "Running command %u (%s)\n",
@ -499,10 +512,34 @@ interpreter (void *cls)
} }
return; return;
case OPCODE_RUN_TRANSFER: case OPCODE_RUN_TRANSFER:
GNUNET_break (0); // FIXME: not implemented! {
return; struct TALER_Amount amount;
if (GNUNET_OK !=
TALER_string_to_amount (cmd->details.run_transfer.amount,
&amount))
{
GNUNET_break (0);
fail (cmd);
return;
}
GNUNET_assert (NULL != cmd->details.run_transfer.subject);
cmd->details.run_transfer.serial_id
= TALER_FAKEBANK_make_transfer (fb,
cmd->details.run_transfer.debit_account,
cmd->details.run_transfer.credit_account,
&amount,
cmd->details.run_transfer.subject,
"https://exchange.taler.net/");
next_command (state);
return;
}
case OPCODE_WAIT: case OPCODE_WAIT:
next_command (state); state->ioff++;
GNUNET_assert (NULL == int_task);
int_task = GNUNET_SCHEDULER_add_delayed (cmd->details.wait_delay,
&interpreter,
state);
return; return;
case OPCODE_EXPECT_TRANSFER: case OPCODE_EXPECT_TRANSFER:
{ {
@ -537,7 +574,7 @@ interpreter (void *cls)
return; return;
} }
next_command (state); next_command (state);
break; return;
case OPCODE_TERMINATE_SUCCESS: case OPCODE_TERMINATE_SUCCESS:
result = 0; result = 0;
GNUNET_SCHEDULER_shutdown (); GNUNET_SCHEDULER_shutdown ();
@ -572,22 +609,100 @@ run (void *cls)
.opcode = OPCODE_EXPECT_TRANSFERS_EMPTY, .opcode = OPCODE_EXPECT_TRANSFERS_EMPTY,
.label = "expect-empty-transactions-after-dry-run" .label = "expect-empty-transactions-after-dry-run"
}, },
/* fill exchange's reserve at bank */
{ {
.opcode = OPCODE_TERMINATE_SUCCESS, .opcode = OPCODE_RUN_TRANSFER,
.label = "testcase-complete-terminating-with-success" .label = "run-transfer-good-to-exchange",
.details.run_transfer.debit_account = 4,
.details.run_transfer.credit_account = 3,
.details.run_transfer.subject = "SRB8VQHNTNJWSSG7BXT24Z063ZSXN7T0MHCQCBAFC1V17BZH10D0",
.details.run_transfer.amount = "EUR:5.00"
}, },
/* creates reserve */
{
.opcode = OPCODE_RUN_WIREWATCH,
.label = "run-wirewatch-on-good-transfer"
},
/* clear first transfer from DLL */
{ {
.opcode = OPCODE_EXPECT_TRANSFER, .opcode = OPCODE_EXPECT_TRANSFER,
.label = "expect-deposit-1", .label = "clear-good-transfer-to-exchange",
.details.expect_transfer.debit_account = 4,
.details.expect_transfer.credit_account = 3,
.details.expect_transfer.exchange_base_url = "https://exchange.taler.net/",
.details.expect_transfer.amount = "EUR:5.00"
},
/* should do NOTHING, it is too early... */
{
.opcode = OPCODE_RUN_AGGREGATOR,
.label = "run-aggregator-non-expired-reserve"
},
/* check nothing happened */
{
.opcode = OPCODE_EXPECT_TRANSFERS_EMPTY,
.label = "expect-empty-transactions-1"
},
/* Configuration says reserves expire after 5s! */
{
.opcode = OPCODE_WAIT,
.label = "wait (5s)",
.details.wait_delay = { 1000LL * 1000 * 6 } /* 6s */
},
/* This time the reserve expired, so the money should go back... */
{
.opcode = OPCODE_RUN_AGGREGATOR,
.label = "run-aggregator-non-expired-reserve"
},
/* Check exchange sent money back, minus closing fee of EUR:0.01 */
{
.opcode = OPCODE_EXPECT_TRANSFER,
.label = "check-reserve-expiration-transfer",
.details.expect_transfer.debit_account = 3, .details.expect_transfer.debit_account = 3,
.details.expect_transfer.credit_account = 4, .details.expect_transfer.credit_account = 4,
.details.expect_transfer.exchange_base_url = "https://exchange.taler.net/", .details.expect_transfer.exchange_base_url = "https://exchange.taler.net/",
.details.expect_transfer.amount = "EUR:0.89" .details.expect_transfer.amount = "EUR:4.99"
},
/* check nothing else happened */
{
.opcode = OPCODE_EXPECT_TRANSFERS_EMPTY,
.label = "expect-empty-transactions-1"
},
/* This cannot work unless #5077 is implemented. */
#if TEST_5077
{
.opcode = OPCODE_RUN_TRANSFER,
.label = "run-transfer-bad-to-exchange",
.details.run_transfer.debit_account = 4,
.details.run_transfer.credit_account = 3,
.details.run_transfer.subject = "random junk",
.details.run_transfer.amount = "EUR:5.00"
},
{
.opcode = OPCODE_RUN_WIREWATCH,
.label = "run-wirewatch-on-bad-transfer"
},
{
.opcode = OPCODE_EXPECT_TRANSFER,
.label = "expect-bad-transfer-to-exchange",
.details.expect_transfer.debit_account = 4,
.details.expect_transfer.credit_account = 3,
.details.expect_transfer.exchange_base_url = "https://exchange.taler.net/",
.details.expect_transfer.amount = "EUR:5.00"
},
{
.opcode = OPCODE_EXPECT_TRANSFER,
.label = "expect-rewire-transfer-from-exchange",
.details.expect_transfer.debit_account = 3,
.details.expect_transfer.credit_account = 4,
.details.expect_transfer.exchange_base_url = "https://exchange.taler.net/",
.details.expect_transfer.amount = "EUR:5.00"
}, },
{ {
.opcode = OPCODE_EXPECT_TRANSFERS_EMPTY, .opcode = OPCODE_EXPECT_TRANSFERS_EMPTY,
.label = "expect-empty-transactions-on-start" .label = "expect-empty-transactions-1"
}, },
#endif
{ {
.opcode = OPCODE_TERMINATE_SUCCESS, .opcode = OPCODE_TERMINATE_SUCCESS,
.label = "testcase-complete-terminating-with-success" .label = "testcase-complete-terminating-with-success"
@ -679,6 +794,22 @@ main (int argc,
} }
GNUNET_OS_process_wait (proc); GNUNET_OS_process_wait (proc);
GNUNET_OS_process_destroy (proc); GNUNET_OS_process_destroy (proc);
proc = GNUNET_OS_start_process (GNUNET_NO,
GNUNET_OS_INHERIT_STD_ALL,
NULL, NULL, NULL,
"taler-exchange-dbinit",
"taler-exchange-dbinit",
"-c", config_filename,
"-r",
NULL);
if (NULL == proc)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to run `taler-exchange-keyup`, is your PATH correct?\n");
return 77;
}
GNUNET_OS_process_wait (proc);
GNUNET_OS_process_destroy (proc);
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_NETWORK_test_port_free (IPPROTO_TCP, GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
8082)) 8082))

View File

@ -2087,6 +2087,11 @@ postgres_reserves_in_insert (void *cls,
*/ */
} }
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Creating reserve %s with expiration in %s\n",
TALER_B2S (reserve_pub),
GNUNET_STRINGS_relative_time_to_string (pg->idle_reserve_expiration_time,
GNUNET_NO));
expiry = GNUNET_TIME_absolute_add (execution_time, expiry = GNUNET_TIME_absolute_add (execution_time,
pg->idle_reserve_expiration_time); pg->idle_reserve_expiration_time);
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == reserve_exists) if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == reserve_exists)