exchangedb: use partial index instead of materialized tables deposits_by_ready and deposits_by_matching; remove now broken code; rename benchmarks to use perf_-prefix and correspond to function they benchmark
This commit is contained in:
parent
e66087987f
commit
ab03ba16e9
@ -495,11 +495,13 @@ transaction_completed (void)
|
|||||||
* We got incoming transaction details from the bank. Add them
|
* We got incoming transaction details from the bank. Add them
|
||||||
* to the database.
|
* to the database.
|
||||||
*
|
*
|
||||||
|
* @param batch_size desired batch size
|
||||||
* @param details array of transaction details
|
* @param details array of transaction details
|
||||||
* @param details_length length of the @a details array
|
* @param details_length length of the @a details array
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
process_reply (const struct TALER_BANK_CreditDetails *details,
|
process_reply (unsigned int batch_size,
|
||||||
|
const struct TALER_BANK_CreditDetails *details,
|
||||||
unsigned int details_length)
|
unsigned int details_length)
|
||||||
{
|
{
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
@ -545,416 +547,31 @@ process_reply (const struct TALER_BANK_CreditDetails *details,
|
|||||||
}
|
}
|
||||||
lroff = cd->serial_id;
|
lroff = cd->serial_id;
|
||||||
}
|
}
|
||||||
if (GNUNET_OK !=
|
if (0 != details_length)
|
||||||
db_plugin->start_read_committed (db_plugin->cls,
|
|
||||||
"wirewatch check for incoming wire transfers"))
|
|
||||||
{
|
{
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
enum GNUNET_DB_QueryStatus qss[details_length];
|
||||||
"Failed to start database transaction!\n");
|
struct TALER_EXCHANGEDB_ReserveInInfo reserves[details_length];
|
||||||
global_ret = EXIT_FAILURE;
|
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
started_transaction = true;
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Importing %u transactions\n",
|
|
||||||
details_length);
|
|
||||||
for (unsigned int i = 0; i<details_length; i++)
|
|
||||||
{
|
|
||||||
const struct TALER_BANK_CreditDetails *cd = &details[i];
|
|
||||||
|
|
||||||
/* FIXME #7276: Consider using Postgres multi-valued insert here,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
for up to 15x speed-up according to
|
"Importing %u transactions\n",
|
||||||
https://dba.stackexchange.com/questions/224989/multi-row-insert-vs-transactional-single-row-inserts#225006
|
details_length);
|
||||||
(Note: this may require changing both the
|
for (unsigned int i = 0; i<details_length; i++)
|
||||||
plugin API as well as modifying how this function is called.) */
|
{
|
||||||
|
const struct TALER_BANK_CreditDetails *cd = &details[i];
|
||||||
|
struct TALER_EXCHANGEDB_ReserveInInfo *res = &reserves[i];
|
||||||
|
|
||||||
|
res->reserve_pub = &cd->reserve_pub;
|
||||||
|
res->balance = &cd->amount;
|
||||||
|
res->execution_time = cd->execution_date;
|
||||||
|
res->sender_account_details = cd->debit_account_uri;
|
||||||
|
res->exchange_account_name = ai->section_name;
|
||||||
|
res->wire_reference = cd->serial_id;
|
||||||
|
}
|
||||||
qs = db_plugin->reserves_in_insert (db_plugin->cls,
|
qs = db_plugin->reserves_in_insert (db_plugin->cls,
|
||||||
&cd->reserve_pub,
|
reserves,
|
||||||
&cd->amount,
|
details_length,
|
||||||
cd->execution_date,
|
batch_size,
|
||||||
cd->debit_account_uri,
|
qss);
|
||||||
ai->section_name,
|
|
||||||
cd->serial_id);
|
|
||||||
switch (qs)
|
|
||||||
{
|
|
||||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
|
||||||
GNUNET_break (0);
|
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
|
||||||
return;
|
|
||||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Got DB soft error for reserves_in_insert. Rolling back.\n");
|
|
||||||
handle_soft_error ();
|
|
||||||
return;
|
|
||||||
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
|
|
||||||
/* Either wirewatch was freshly started after the system was
|
|
||||||
shutdown and we're going over an incomplete shard again
|
|
||||||
after being restarted, or the shard lock period was too
|
|
||||||
short (number of workers set incorrectly?) and a 2nd
|
|
||||||
wirewatcher has been stealing our work while we are still
|
|
||||||
at it. */
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Attempted to import transaction %llu (%s) twice. "
|
|
||||||
"This should happen rarely (if not, ask for support).\n",
|
|
||||||
(unsigned long long) cd->serial_id,
|
|
||||||
job_name);
|
|
||||||
break;
|
|
||||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Imported transaction %llu.",
|
|
||||||
(unsigned long long) cd->serial_id);
|
|
||||||
/* normal case */
|
|
||||||
progress = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
latest_row_off = lroff;
|
|
||||||
shard_done = (shard_end <= latest_row_off);
|
|
||||||
if (shard_done)
|
|
||||||
{
|
|
||||||
/* shard is complete, mark this as well */
|
|
||||||
qs = db_plugin->complete_shard (db_plugin->cls,
|
|
||||||
job_name,
|
|
||||||
shard_start,
|
|
||||||
shard_end);
|
|
||||||
switch (qs)
|
|
||||||
{
|
|
||||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
|
||||||
GNUNET_break (0);
|
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
|
||||||
return;
|
|
||||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Got DB soft error for complete_shard. Rolling back.\n");
|
|
||||||
handle_soft_error ();
|
|
||||||
return;
|
|
||||||
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
|
|
||||||
GNUNET_break (0);
|
|
||||||
/* Not expected, but let's just continue */
|
|
||||||
break;
|
|
||||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
|
||||||
/* normal case */
|
|
||||||
progress = true;
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Completed shard %s (%llu,%llu] after %s\n",
|
|
||||||
job_name,
|
|
||||||
(unsigned long long) shard_start,
|
|
||||||
(unsigned long long) shard_end,
|
|
||||||
GNUNET_STRINGS_relative_time_to_string (
|
|
||||||
GNUNET_TIME_absolute_get_duration (shard_start_time),
|
|
||||||
true));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (! progress)
|
|
||||||
{
|
|
||||||
db_plugin->rollback (db_plugin->cls);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Committing %s progress (%llu,%llu] at %llu\n (%s)",
|
|
||||||
job_name,
|
|
||||||
(unsigned long long) shard_start,
|
|
||||||
(unsigned long long) shard_end,
|
|
||||||
(unsigned long long) latest_row_off,
|
|
||||||
shard_done
|
|
||||||
? "shard done"
|
|
||||||
: "shard incomplete");
|
|
||||||
qs = db_plugin->commit (db_plugin->cls);
|
|
||||||
switch (qs)
|
|
||||||
{
|
|
||||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
|
||||||
GNUNET_break (0);
|
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
|
||||||
return;
|
|
||||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
|
||||||
/* reduce transaction size to reduce rollback probability */
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Got DB soft error on commit. Reducing transaction size.\n");
|
|
||||||
handle_soft_error ();
|
|
||||||
return;
|
|
||||||
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
|
|
||||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
|
||||||
started_transaction = false;
|
|
||||||
/* normal case */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (shard_done)
|
|
||||||
{
|
|
||||||
shard_delay = GNUNET_TIME_absolute_get_duration (shard_start_time);
|
|
||||||
shard_open = false;
|
|
||||||
transaction_completed ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GNUNET_assert (NULL == task);
|
|
||||||
task = GNUNET_SCHEDULER_add_now (&continue_with_shard,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We got incoming transaction details from the bank. Add them
|
|
||||||
* to the database.
|
|
||||||
*
|
|
||||||
* @param details array of transaction details
|
|
||||||
* @param details_length length of the @a details array
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
process_reply_batched (const struct TALER_BANK_CreditDetails *details,
|
|
||||||
unsigned int details_length)
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
|
||||||
bool shard_done;
|
|
||||||
uint64_t lroff = latest_row_off;
|
|
||||||
|
|
||||||
if (0 == details_length)
|
|
||||||
{
|
|
||||||
/* Server should have used 204, not 200! */
|
|
||||||
GNUNET_break_op (0);
|
|
||||||
transaction_completed ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* check serial IDs for range constraints */
|
|
||||||
for (unsigned int i = 0; i<details_length; i++)
|
|
||||||
{
|
|
||||||
const struct TALER_BANK_CreditDetails *cd = &details[i];
|
|
||||||
|
|
||||||
if (cd->serial_id < lroff)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
|
||||||
"Serial ID %llu not monotonic (got %llu before). Failing!\n",
|
|
||||||
(unsigned long long) cd->serial_id,
|
|
||||||
(unsigned long long) lroff);
|
|
||||||
db_plugin->rollback (db_plugin->cls);
|
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (cd->serial_id > shard_end)
|
|
||||||
{
|
|
||||||
/* we are *past* the current shard (likely because the serial_id of the
|
|
||||||
shard_end happens to not exist in the DB). So commit and stop this
|
|
||||||
iteration! */
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Serial ID %llu past shard end at %llu, ending iteration early!\n",
|
|
||||||
(unsigned long long) cd->serial_id,
|
|
||||||
(unsigned long long) shard_end);
|
|
||||||
details_length = i;
|
|
||||||
progress = true;
|
|
||||||
lroff = cd->serial_id - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lroff = cd->serial_id;
|
|
||||||
}
|
|
||||||
if (0 != details_length)
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus qss[details_length];
|
|
||||||
struct TALER_EXCHANGEDB_ReserveInInfo reserves[details_length];
|
|
||||||
|
|
||||||
hh_returned_data = true;
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Importing %u transactions\n",
|
|
||||||
details_length);
|
|
||||||
for (unsigned int i = 0; i<details_length; i++)
|
|
||||||
{
|
|
||||||
const struct TALER_BANK_CreditDetails *cd = &details[i];
|
|
||||||
struct TALER_EXCHANGEDB_ReserveInInfo *res = &reserves[i];
|
|
||||||
|
|
||||||
res->reserve_pub = &cd->reserve_pub;
|
|
||||||
res->balance = &cd->amount;
|
|
||||||
res->execution_time = cd->execution_date;
|
|
||||||
res->sender_account_details = cd->debit_account_uri;
|
|
||||||
res->exchange_account_name = ai->section_name;
|
|
||||||
res->wire_reference = cd->serial_id;
|
|
||||||
}
|
|
||||||
qs = db_plugin->batch_reserves_in_insert (db_plugin->cls,
|
|
||||||
reserves,
|
|
||||||
details_length,
|
|
||||||
qss);
|
|
||||||
switch (qs)
|
|
||||||
{
|
|
||||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
|
||||||
GNUNET_break (0);
|
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
|
||||||
return;
|
|
||||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Got DB soft error for batch_reserves_in_insert. Rolling back.\n");
|
|
||||||
handle_soft_error ();
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (unsigned int i = 0; i<details_length; i++)
|
|
||||||
{
|
|
||||||
const struct TALER_BANK_CreditDetails *cd = &details[i];
|
|
||||||
|
|
||||||
switch (qss[i])
|
|
||||||
{
|
|
||||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
|
||||||
GNUNET_break (0);
|
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
|
||||||
return;
|
|
||||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Got DB soft error for batch_reserves_in_insert(%u). Rolling back.\n",
|
|
||||||
i);
|
|
||||||
handle_soft_error ();
|
|
||||||
return;
|
|
||||||
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
|
|
||||||
/* Either wirewatch was freshly started after the system was
|
|
||||||
shutdown and we're going over an incomplete shard again
|
|
||||||
after being restarted, or the shard lock period was too
|
|
||||||
short (number of workers set incorrectly?) and a 2nd
|
|
||||||
wirewatcher has been stealing our work while we are still
|
|
||||||
at it. */
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Attempted to import transaction %llu (%s) twice. "
|
|
||||||
"This should happen rarely (if not, ask for support).\n",
|
|
||||||
(unsigned long long) cd->serial_id,
|
|
||||||
job_name);
|
|
||||||
break;
|
|
||||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Imported transaction %llu.",
|
|
||||||
(unsigned long long) cd->serial_id);
|
|
||||||
/* normal case */
|
|
||||||
progress = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
latest_row_off = lroff;
|
|
||||||
shard_done = (shard_end <= latest_row_off);
|
|
||||||
if (shard_done)
|
|
||||||
{
|
|
||||||
/* shard is complete, mark this as well */
|
|
||||||
qs = db_plugin->complete_shard (db_plugin->cls,
|
|
||||||
job_name,
|
|
||||||
shard_start,
|
|
||||||
shard_end);
|
|
||||||
switch (qs)
|
|
||||||
{
|
|
||||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
|
||||||
GNUNET_break (0);
|
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
|
||||||
return;
|
|
||||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Got DB soft error for complete_shard. Rolling back.\n");
|
|
||||||
handle_soft_error ();
|
|
||||||
return;
|
|
||||||
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
|
|
||||||
GNUNET_break (0);
|
|
||||||
/* Not expected, but let's just continue */
|
|
||||||
break;
|
|
||||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
|
||||||
/* normal case */
|
|
||||||
progress = true;
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Completed shard %s (%llu,%llu] after %s\n",
|
|
||||||
job_name,
|
|
||||||
(unsigned long long) shard_start,
|
|
||||||
(unsigned long long) shard_end,
|
|
||||||
GNUNET_STRINGS_relative_time_to_string (
|
|
||||||
GNUNET_TIME_absolute_get_duration (shard_start_time),
|
|
||||||
true));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
shard_delay = GNUNET_TIME_absolute_get_duration (shard_start_time);
|
|
||||||
shard_open = false;
|
|
||||||
transaction_completed ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GNUNET_assert (NULL == task);
|
|
||||||
task = GNUNET_SCHEDULER_add_now (&continue_with_shard,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We got incoming transaction details from the bank. Add them
|
|
||||||
* to the database.
|
|
||||||
*
|
|
||||||
* @param batch_size desired batch size
|
|
||||||
* @param details array of transaction details
|
|
||||||
* @param details_length length of the @a details array
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
process_reply_batched2 (unsigned int batch_size,
|
|
||||||
const struct TALER_BANK_CreditDetails *details,
|
|
||||||
unsigned int details_length)
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
|
||||||
bool shard_done;
|
|
||||||
uint64_t lroff = latest_row_off;
|
|
||||||
|
|
||||||
if (0 == details_length)
|
|
||||||
{
|
|
||||||
/* Server should have used 204, not 200! */
|
|
||||||
GNUNET_break_op (0);
|
|
||||||
transaction_completed ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
hh_returned_data = true;
|
|
||||||
/* check serial IDs for range constraints */
|
|
||||||
for (unsigned int i = 0; i<details_length; i++)
|
|
||||||
{
|
|
||||||
const struct TALER_BANK_CreditDetails *cd = &details[i];
|
|
||||||
|
|
||||||
if (cd->serial_id < lroff)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
|
||||||
"Serial ID %llu not monotonic (got %llu before). Failing!\n",
|
|
||||||
(unsigned long long) cd->serial_id,
|
|
||||||
(unsigned long long) lroff);
|
|
||||||
db_plugin->rollback (db_plugin->cls);
|
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (cd->serial_id > shard_end)
|
|
||||||
{
|
|
||||||
/* we are *past* the current shard (likely because the serial_id of the
|
|
||||||
shard_end happens to not exist in the DB). So commit and stop this
|
|
||||||
iteration! */
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Serial ID %llu past shard end at %llu, ending iteration early!\n",
|
|
||||||
(unsigned long long) cd->serial_id,
|
|
||||||
(unsigned long long) shard_end);
|
|
||||||
details_length = i;
|
|
||||||
progress = true;
|
|
||||||
lroff = cd->serial_id - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lroff = cd->serial_id;
|
|
||||||
}
|
|
||||||
if (0 != details_length)
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus qss[details_length];
|
|
||||||
struct TALER_EXCHANGEDB_ReserveInInfo reserves[details_length];
|
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Importing %u transactions\n",
|
|
||||||
details_length);
|
|
||||||
for (unsigned int i = 0; i<details_length; i++)
|
|
||||||
{
|
|
||||||
const struct TALER_BANK_CreditDetails *cd = &details[i];
|
|
||||||
struct TALER_EXCHANGEDB_ReserveInInfo *res = &reserves[i];
|
|
||||||
|
|
||||||
res->reserve_pub = &cd->reserve_pub;
|
|
||||||
res->balance = &cd->amount;
|
|
||||||
res->execution_time = cd->execution_date;
|
|
||||||
res->sender_account_details = cd->debit_account_uri;
|
|
||||||
res->exchange_account_name = ai->section_name;
|
|
||||||
res->wire_reference = cd->serial_id;
|
|
||||||
}
|
|
||||||
qs = db_plugin->batch2_reserves_in_insert (db_plugin->cls,
|
|
||||||
reserves,
|
|
||||||
details_length,
|
|
||||||
batch_size,
|
|
||||||
qss);
|
|
||||||
switch (qs)
|
switch (qs)
|
||||||
{
|
{
|
||||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
case GNUNET_DB_STATUS_HARD_ERROR:
|
||||||
@ -1074,7 +691,7 @@ history_cb (void *cls,
|
|||||||
(void) cls;
|
(void) cls;
|
||||||
if (-2 == batch_mode)
|
if (-2 == batch_mode)
|
||||||
{
|
{
|
||||||
const char *mode = getenv ("TALER_USE_BATCH");
|
const char *mode = getenv ("TALER_WIREWATCH_BATCH_SIZE");
|
||||||
char dummy;
|
char dummy;
|
||||||
|
|
||||||
if ( (NULL == mode) ||
|
if ( (NULL == mode) ||
|
||||||
@ -1087,7 +704,7 @@ history_cb (void *cls,
|
|||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Bad batch mode `%s' specified\n",
|
"Bad batch mode `%s' specified\n",
|
||||||
mode);
|
mode);
|
||||||
batch_mode = -1;
|
batch_mode = 8; /* maximum supported is currently 8 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GNUNET_assert (NULL == task);
|
GNUNET_assert (NULL == task);
|
||||||
@ -1098,22 +715,9 @@ history_cb (void *cls,
|
|||||||
switch (reply->http_status)
|
switch (reply->http_status)
|
||||||
{
|
{
|
||||||
case MHD_HTTP_OK:
|
case MHD_HTTP_OK:
|
||||||
switch (batch_mode)
|
process_reply (batch_mode,
|
||||||
{
|
reply->details.success.details,
|
||||||
case -1:
|
reply->details.success.details_length);
|
||||||
process_reply (reply->details.success.details,
|
|
||||||
reply->details.success.details_length);
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
process_reply_batched (reply->details.success.details,
|
|
||||||
reply->details.success.details_length);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
process_reply_batched2 ((unsigned int) batch_mode,
|
|
||||||
reply->details.success.details,
|
|
||||||
reply->details.success.details_length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
case MHD_HTTP_NO_CONTENT:
|
case MHD_HTTP_NO_CONTENT:
|
||||||
transaction_completed ();
|
transaction_completed ();
|
||||||
|
16
src/exchangedb/.gitignore
vendored
16
src/exchangedb/.gitignore
vendored
@ -1,17 +1,9 @@
|
|||||||
test-exchangedb-auditors
|
|
||||||
test-exchangedb-denomkeys
|
|
||||||
test-exchangedb-fees
|
|
||||||
test-exchangedb-postgres
|
test-exchangedb-postgres
|
||||||
test-exchangedb-signkeys
|
|
||||||
test-perf-taler-exchangedb
|
|
||||||
bench-db-postgres
|
bench-db-postgres
|
||||||
shard-drop0001.sqltest-exchangedb-by-j-postgres
|
perf_deposits_get_ready-postgres
|
||||||
test-exchangedb-by-j-postgres
|
perf_get_link_data-postgres
|
||||||
perf-exchangedb-reserves-in-insert-postgres
|
perf_reserves_in_insert-postgres
|
||||||
|
perf_select_refunds_by_coin-postgres
|
||||||
exchange-0002.sql
|
exchange-0002.sql
|
||||||
procedures.sql
|
procedures.sql
|
||||||
exchange-0003.sql
|
exchange-0003.sql
|
||||||
test-exchangedb-batch-reserves-in-insert-postgres
|
|
||||||
test-exchangedb-populate-table-postgres
|
|
||||||
test-exchangedb-populate-link-data-postgres
|
|
||||||
test-exchangedb-populate-ready-deposit-postgres
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
--
|
--
|
||||||
-- This file is part of TALER
|
-- This file is part of TALER
|
||||||
-- Copyright (C) 2014--2022 Taler Systems SA
|
-- Copyright (C) 2014--2023 Taler Systems SA
|
||||||
--
|
--
|
||||||
-- TALER is free software; you can redistribute it and/or modify it under the
|
-- 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
|
-- terms of the GNU General Public License as published by the Free Software
|
||||||
@ -116,6 +116,22 @@ BEGIN
|
|||||||
',ADD CONSTRAINT ' || table_name || '_coin_pub_merchant_pub_h_contract_terms_key'
|
',ADD CONSTRAINT ' || table_name || '_coin_pub_merchant_pub_h_contract_terms_key'
|
||||||
' UNIQUE (coin_pub, merchant_pub, h_contract_terms)'
|
' UNIQUE (coin_pub, merchant_pub, h_contract_terms)'
|
||||||
);
|
);
|
||||||
|
EXECUTE FORMAT (
|
||||||
|
'CREATE INDEX ' || table_name || '_by_ready '
|
||||||
|
'ON ' || table_name || ' '
|
||||||
|
'(wire_deadline ASC'
|
||||||
|
',shard ASC'
|
||||||
|
',coin_pub'
|
||||||
|
') WHERE NOT (done OR policy_blocked);'
|
||||||
|
);
|
||||||
|
EXECUTE FORMAT (
|
||||||
|
'CREATE INDEX ' || table_name || '_for_matching '
|
||||||
|
'ON ' || table_name || ' '
|
||||||
|
'(refund_deadline ASC'
|
||||||
|
',merchant_pub'
|
||||||
|
',coin_pub'
|
||||||
|
') WHERE NOT (done OR policy_blocked);'
|
||||||
|
);
|
||||||
END
|
END
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
@ -399,29 +415,5 @@ INSERT INTO exchange_tables
|
|||||||
,'exchange-0002'
|
,'exchange-0002'
|
||||||
,'foreign'
|
,'foreign'
|
||||||
,TRUE
|
,TRUE
|
||||||
,FALSE),
|
,FALSE)
|
||||||
('deposits_by_ready'
|
;
|
||||||
,'exchange-0002'
|
|
||||||
,'create'
|
|
||||||
,TRUE
|
|
||||||
,TRUE),
|
|
||||||
('deposits_by_ready'
|
|
||||||
,'exchange-0002'
|
|
||||||
,'constrain'
|
|
||||||
,TRUE
|
|
||||||
,TRUE),
|
|
||||||
('deposits_for_matching'
|
|
||||||
,'exchange-0002'
|
|
||||||
,'create'
|
|
||||||
,TRUE
|
|
||||||
,TRUE),
|
|
||||||
('deposits_for_matching'
|
|
||||||
,'exchange-0002'
|
|
||||||
,'constrain'
|
|
||||||
,TRUE
|
|
||||||
,TRUE),
|
|
||||||
('deposits'
|
|
||||||
,'exchange-0002'
|
|
||||||
,'master'
|
|
||||||
,TRUE
|
|
||||||
,FALSE);
|
|
||||||
|
@ -255,8 +255,6 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
|
|||||||
pg_select_purse_deposits_above_serial_id.h pg_select_purse_deposits_above_serial_id.c \
|
pg_select_purse_deposits_above_serial_id.h pg_select_purse_deposits_above_serial_id.c \
|
||||||
pg_select_account_merges_above_serial_id.h pg_select_account_merges_above_serial_id.c \
|
pg_select_account_merges_above_serial_id.h pg_select_account_merges_above_serial_id.c \
|
||||||
pg_select_all_purse_decisions_above_serial_id.h pg_select_all_purse_decisions_above_serial_id.c \
|
pg_select_all_purse_decisions_above_serial_id.h pg_select_all_purse_decisions_above_serial_id.c \
|
||||||
pg_batch_reserves_in_insert.h pg_batch_reserves_in_insert.c \
|
|
||||||
pg_batch2_reserves_in_insert.h pg_batch2_reserves_in_insert.c \
|
|
||||||
pg_select_reserve_open_above_serial_id.c pg_select_reserve_open_above_serial_id.h
|
pg_select_reserve_open_above_serial_id.c pg_select_reserve_open_above_serial_id.h
|
||||||
libtaler_plugin_exchangedb_postgres_la_LIBADD = \
|
libtaler_plugin_exchangedb_postgres_la_LIBADD = \
|
||||||
$(LTLIBINTL)
|
$(LTLIBINTL)
|
||||||
@ -295,22 +293,14 @@ check_PROGRAMS = \
|
|||||||
|
|
||||||
noinst_PROGRAMS = \
|
noinst_PROGRAMS = \
|
||||||
bench-db-postgres\
|
bench-db-postgres\
|
||||||
perf-exchangedb-reserves-in-insert-postgres\
|
perf_get_link_data-postgres\
|
||||||
test-exchangedb-by-j-postgres\
|
perf_select_refunds_by_coin-postgres\
|
||||||
test-exchangedb-batch-reserves-in-insert-postgres\
|
perf_reserves_in_insert-postgres \
|
||||||
test-exchangedb-populate-select-refunds-by-coin-postgres\
|
perf_deposits_get_ready-postgres
|
||||||
test-exchangedb-populate-link-data-postgres\
|
|
||||||
test-exchangedb-populate-ready-deposit-postgres
|
|
||||||
|
|
||||||
AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
|
AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
|
||||||
TESTS = \
|
TESTS = \
|
||||||
test-exchangedb-postgres\
|
(check_PROGRAMS)
|
||||||
test-exchangedb-by-j-postgres\
|
|
||||||
perf-exchangedb-reserves-in-insert-postgres\
|
|
||||||
test-exchangedb-batch-reserves-in-insert-postgres\
|
|
||||||
test-exchangedb-populate-select-refunds-by-coin-postgres\
|
|
||||||
test-exchangedb-populate-link-data-postgres\
|
|
||||||
test-exchangedb-populate-ready-deposit-postgres
|
|
||||||
test_exchangedb_postgres_SOURCES = \
|
test_exchangedb_postgres_SOURCES = \
|
||||||
test_exchangedb.c
|
test_exchangedb.c
|
||||||
test_exchangedb_postgres_LDADD = \
|
test_exchangedb_postgres_LDADD = \
|
||||||
@ -323,32 +313,6 @@ test_exchangedb_postgres_LDADD = \
|
|||||||
-lgnunetutil \
|
-lgnunetutil \
|
||||||
$(XLIB)
|
$(XLIB)
|
||||||
|
|
||||||
test_exchangedb_by_j_postgres_SOURCES = \
|
|
||||||
test_exchangedb_by_j.c
|
|
||||||
test_exchangedb_by_j_postgres_LDADD = \
|
|
||||||
libtalerexchangedb.la \
|
|
||||||
$(top_builddir)/src/json/libtalerjson.la \
|
|
||||||
$(top_builddir)/src/util/libtalerutil.la \
|
|
||||||
$(top_builddir)/src/pq/libtalerpq.la \
|
|
||||||
-ljansson \
|
|
||||||
-lgnunetjson \
|
|
||||||
-lgnunetutil \
|
|
||||||
-lm \
|
|
||||||
$(XLIB)
|
|
||||||
|
|
||||||
|
|
||||||
perf_exchangedb_reserves_in_insert_postgres_SOURCES = \
|
|
||||||
perf_exchangedb_reserves_in_insert.c
|
|
||||||
perf_exchangedb_reserves_in_insert_postgres_LDADD = \
|
|
||||||
libtalerexchangedb.la \
|
|
||||||
$(top_builddir)/src/json/libtalerjson.la \
|
|
||||||
$(top_builddir)/src/util/libtalerutil.la \
|
|
||||||
$(top_builddir)/src/pq/libtalerpq.la \
|
|
||||||
-ljansson \
|
|
||||||
-lgnunetjson \
|
|
||||||
-lgnunetutil \
|
|
||||||
$(XLIB)
|
|
||||||
|
|
||||||
bench_db_postgres_SOURCES = \
|
bench_db_postgres_SOURCES = \
|
||||||
bench_db.c
|
bench_db.c
|
||||||
bench_db_postgres_LDADD = \
|
bench_db_postgres_LDADD = \
|
||||||
@ -359,21 +323,9 @@ bench_db_postgres_LDADD = \
|
|||||||
-lgnunetutil \
|
-lgnunetutil \
|
||||||
$(XLIB)
|
$(XLIB)
|
||||||
|
|
||||||
test_exchangedb_batch_reserves_in_insert_postgres_SOURCES = \
|
perf_reserves_in_insert_postgres_SOURCES = \
|
||||||
test_exchangedb_batch_reserves_in_insert.c
|
perf_reserves_in_insert.c
|
||||||
test_exchangedb_batch_reserves_in_insert_postgres_LDADD = \
|
perf_reserves_in_insert_postgres_LDADD = \
|
||||||
libtalerexchangedb.la \
|
|
||||||
$(top_builddir)/src/json/libtalerjson.la \
|
|
||||||
$(top_builddir)/src/util/libtalerutil.la \
|
|
||||||
$(top_builddir)/src/pq/libtalerpq.la \
|
|
||||||
-ljansson \
|
|
||||||
-lgnunetjson \
|
|
||||||
-lgnunetutil \
|
|
||||||
$(XLIB)
|
|
||||||
|
|
||||||
test_exchangedb_populate_select_refunds_by_coin_postgres_SOURCES = \
|
|
||||||
test_exchangedb_populate_select_refunds_by_coin.c
|
|
||||||
test_exchangedb_populate_select_refunds_by_coin_postgres_LDADD = \
|
|
||||||
libtalerexchangedb.la \
|
libtalerexchangedb.la \
|
||||||
$(top_builddir)/src/json/libtalerjson.la \
|
$(top_builddir)/src/json/libtalerjson.la \
|
||||||
$(top_builddir)/src/util/libtalerutil.la \
|
$(top_builddir)/src/util/libtalerutil.la \
|
||||||
@ -384,9 +336,9 @@ test_exchangedb_populate_select_refunds_by_coin_postgres_LDADD = \
|
|||||||
-lm \
|
-lm \
|
||||||
$(XLIB)
|
$(XLIB)
|
||||||
|
|
||||||
test_exchangedb_populate_link_data_postgres_SOURCES = \
|
perf_select_refunds_by_coin_postgres_SOURCES = \
|
||||||
test_exchangedb_populate_link_data.c
|
perf_select_refunds_by_coin.c
|
||||||
test_exchangedb_populate_link_data_postgres_LDADD = \
|
perf_select_refunds_by_coin_postgres_LDADD = \
|
||||||
libtalerexchangedb.la \
|
libtalerexchangedb.la \
|
||||||
$(top_builddir)/src/json/libtalerjson.la \
|
$(top_builddir)/src/json/libtalerjson.la \
|
||||||
$(top_builddir)/src/util/libtalerutil.la \
|
$(top_builddir)/src/util/libtalerutil.la \
|
||||||
@ -397,9 +349,22 @@ test_exchangedb_populate_link_data_postgres_LDADD = \
|
|||||||
-lm \
|
-lm \
|
||||||
$(XLIB)
|
$(XLIB)
|
||||||
|
|
||||||
test_exchangedb_populate_ready_deposit_postgres_SOURCES = \
|
perf_get_link_data_postgres_SOURCES = \
|
||||||
test_exchangedb_populate_ready_deposit.c
|
perf_get_link_data.c
|
||||||
test_exchangedb_populate_ready_deposit_postgres_LDADD = \
|
perf_get_link_data_postgres_LDADD = \
|
||||||
|
libtalerexchangedb.la \
|
||||||
|
$(top_builddir)/src/json/libtalerjson.la \
|
||||||
|
$(top_builddir)/src/util/libtalerutil.la \
|
||||||
|
$(top_builddir)/src/pq/libtalerpq.la \
|
||||||
|
-ljansson \
|
||||||
|
-lgnunetjson \
|
||||||
|
-lgnunetutil \
|
||||||
|
-lm \
|
||||||
|
$(XLIB)
|
||||||
|
|
||||||
|
perf_deposits_get_ready_postgres_SOURCES = \
|
||||||
|
perf_deposits_get_ready.c
|
||||||
|
perf_deposits_get_ready_postgres_LDADD = \
|
||||||
libtalerexchangedb.la \
|
libtalerexchangedb.la \
|
||||||
$(top_builddir)/src/json/libtalerjson.la \
|
$(top_builddir)/src/json/libtalerjson.la \
|
||||||
$(top_builddir)/src/util/libtalerutil.la \
|
$(top_builddir)/src/util/libtalerutil.la \
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2014-2022 Taler Systems SA
|
Copyright (C) 2014-2023 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
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
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -14,8 +14,8 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @file exchangedb/test_exchangedb_populate_ready_deposit.c
|
* @file exchangedb/perf_deposits_get_ready.c
|
||||||
* @brief test cases for DB interaction functions
|
* @brief benchmark for deposits_get_ready
|
||||||
* @author Joseph Xu
|
* @author Joseph Xu
|
||||||
*/
|
*/
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
@ -34,7 +34,7 @@ static int result;
|
|||||||
*/
|
*/
|
||||||
#define FAILIF(cond) \
|
#define FAILIF(cond) \
|
||||||
do { \
|
do { \
|
||||||
if (! (cond)) {break;} \
|
if (! (cond)) {break;} \
|
||||||
GNUNET_break (0); \
|
GNUNET_break (0); \
|
||||||
goto drop; \
|
goto drop; \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -57,21 +57,27 @@ static int result;
|
|||||||
*/
|
*/
|
||||||
#define CURRENCY "EUR"
|
#define CURRENCY "EUR"
|
||||||
#define RSA_KEY_SIZE 1024
|
#define RSA_KEY_SIZE 1024
|
||||||
#define NUM_ROWS 1000000
|
#define NUM_ROWS 1000
|
||||||
#define ROUNDS 10000
|
#define ROUNDS 100
|
||||||
#define MELT_NEW_COINS 5
|
#define MELT_NEW_COINS 5
|
||||||
#define MELT_NOREVEAL_INDEX 1
|
#define MELT_NOREVEAL_INDEX 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database plugin under test.
|
* Database plugin under test.
|
||||||
*/
|
*/
|
||||||
static struct TALER_EXCHANGEDB_Plugin *plugin;
|
static struct TALER_EXCHANGEDB_Plugin *plugin;
|
||||||
|
|
||||||
static struct TALER_DenomFeeSet fees;
|
static struct TALER_DenomFeeSet fees;
|
||||||
|
|
||||||
static struct TALER_MerchantWireHashP h_wire_wt;
|
static struct TALER_MerchantWireHashP h_wire_wt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Denomination keys used for fresh coins in melt test.
|
* Denomination keys used for fresh coins in melt test.
|
||||||
*/
|
*/
|
||||||
static struct DenomKeyPair **new_dkp;
|
static struct DenomKeyPair **new_dkp;
|
||||||
|
|
||||||
static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;
|
static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;
|
||||||
|
|
||||||
struct DenomKeyPair
|
struct DenomKeyPair
|
||||||
{
|
{
|
||||||
struct TALER_DenominationPrivateKey priv;
|
struct TALER_DenominationPrivateKey priv;
|
||||||
@ -173,8 +179,6 @@ create_denom_key_pair (unsigned int size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main function that will be run by the scheduler.
|
* Main function that will be run by the scheduler.
|
||||||
*
|
*
|
||||||
@ -191,19 +195,19 @@ run (void *cls)
|
|||||||
struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
|
struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
|
||||||
struct TALER_DenominationPublicKey *new_denom_pubs = NULL;
|
struct TALER_DenominationPublicKey *new_denom_pubs = NULL;
|
||||||
struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
|
struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
|
||||||
unsigned long long sqrs=0;
|
unsigned long long sqrs = 0;
|
||||||
struct TALER_EXCHANGEDB_Deposit *depos=NULL;
|
struct TALER_EXCHANGEDB_Deposit *depos = NULL;
|
||||||
struct TALER_EXCHANGEDB_Refund *ref=NULL;
|
struct TALER_EXCHANGEDB_Refund *ref = NULL;
|
||||||
unsigned int *perm;
|
unsigned int *perm;
|
||||||
unsigned long long duration_sq;
|
unsigned long long duration_sq;
|
||||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
|
struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
|
||||||
struct TALER_ExchangeWithdrawValues alg_values = {
|
struct TALER_ExchangeWithdrawValues alg_values = {
|
||||||
.cipher = TALER_DENOMINATION_RSA
|
.cipher = TALER_DENOMINATION_RSA
|
||||||
};
|
};
|
||||||
|
|
||||||
ref = GNUNET_new_array (ROUNDS +1,
|
ref = GNUNET_new_array (ROUNDS + 1,
|
||||||
struct TALER_EXCHANGEDB_Refund);
|
struct TALER_EXCHANGEDB_Refund);
|
||||||
depos = GNUNET_new_array (ROUNDS +1,
|
depos = GNUNET_new_array (ROUNDS + 1,
|
||||||
struct TALER_EXCHANGEDB_Deposit);
|
struct TALER_EXCHANGEDB_Deposit);
|
||||||
|
|
||||||
if (NULL ==
|
if (NULL ==
|
||||||
@ -245,194 +249,190 @@ run (void *cls)
|
|||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_string_to_amount (CURRENCY ":0.000010",
|
TALER_string_to_amount (CURRENCY ":0.000010",
|
||||||
&fees.refund));
|
&fees.refund));
|
||||||
//DENOMINATION
|
|
||||||
{
|
{
|
||||||
ZR_BLK (&cbc);
|
ZR_BLK (&cbc);
|
||||||
//PAIR KEY LIST
|
|
||||||
new_dkp = GNUNET_new_array (MELT_NEW_COINS,
|
new_dkp = GNUNET_new_array (MELT_NEW_COINS,
|
||||||
struct DenomKeyPair *);
|
struct DenomKeyPair *);
|
||||||
//PUBLIC KEY LIST
|
|
||||||
new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
|
new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
|
||||||
struct TALER_DenominationPublicKey);
|
struct TALER_DenominationPublicKey);
|
||||||
//REFRESH REVEAL COIN LIST
|
|
||||||
revealed_coins
|
revealed_coins
|
||||||
= GNUNET_new_array (MELT_NEW_COINS,
|
= GNUNET_new_array (MELT_NEW_COINS,
|
||||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin);
|
struct TALER_EXCHANGEDB_RefreshRevealedCoin);
|
||||||
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
|
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
|
||||||
{
|
{
|
||||||
struct GNUNET_TIME_Timestamp now;
|
struct GNUNET_TIME_Timestamp now;
|
||||||
struct TALER_BlindedRsaPlanchet *rp;
|
struct TALER_BlindedRsaPlanchet *rp;
|
||||||
struct TALER_BlindedPlanchet *bp;
|
struct TALER_BlindedPlanchet *bp;
|
||||||
|
|
||||||
now = GNUNET_TIME_timestamp_get ();
|
now = GNUNET_TIME_timestamp_get ();
|
||||||
//5 KEY PAIR
|
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
|
||||||
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
|
now,
|
||||||
now,
|
&value,
|
||||||
&value,
|
&fees);
|
||||||
&fees);
|
GNUNET_assert (NULL != new_dkp[cnt]);
|
||||||
GNUNET_assert (NULL != new_dkp[cnt]);
|
new_denom_pubs[cnt] = new_dkp[cnt]->pub;
|
||||||
new_denom_pubs[cnt] = new_dkp[cnt]->pub;
|
ccoin = &revealed_coins[cnt];
|
||||||
ccoin = &revealed_coins[cnt];
|
bp = &ccoin->blinded_planchet;
|
||||||
bp = &ccoin->blinded_planchet;
|
bp->cipher = TALER_DENOMINATION_RSA;
|
||||||
bp->cipher = TALER_DENOMINATION_RSA;
|
rp = &bp->details.rsa_blinded_planchet;
|
||||||
rp = &bp->details.rsa_blinded_planchet;
|
rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
|
||||||
rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
|
GNUNET_CRYPTO_QUALITY_WEAK,
|
||||||
GNUNET_CRYPTO_QUALITY_WEAK,
|
(RSA_KEY_SIZE / 8) - 1);
|
||||||
(RSA_KEY_SIZE / 8) - 1);
|
rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
|
||||||
rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
|
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
rp->blinded_msg,
|
||||||
rp->blinded_msg,
|
rp->blinded_msg_size);
|
||||||
rp->blinded_msg_size);
|
TALER_denom_pub_hash (&new_dkp[cnt]->pub,
|
||||||
TALER_denom_pub_hash (&new_dkp[cnt]->pub,
|
&ccoin->h_denom_pub);
|
||||||
&ccoin->h_denom_pub);
|
ccoin->exchange_vals = alg_values;
|
||||||
ccoin->exchange_vals = alg_values;
|
TALER_coin_ev_hash (bp,
|
||||||
TALER_coin_ev_hash (bp,
|
&ccoin->h_denom_pub,
|
||||||
&ccoin->h_denom_pub,
|
&ccoin->coin_envelope_hash);
|
||||||
&ccoin->coin_envelope_hash);
|
GNUNET_assert (GNUNET_OK ==
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_denom_sign_blinded (&ccoin->coin_sig,
|
TALER_denom_sign_blinded (&ccoin->coin_sig,
|
||||||
&new_dkp[cnt]->priv,
|
&new_dkp[cnt]->priv,
|
||||||
true,
|
true,
|
||||||
bp));
|
bp));
|
||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_coin_ev_hash (bp,
|
TALER_coin_ev_hash (bp,
|
||||||
&cbc.denom_pub_hash,
|
&cbc.denom_pub_hash,
|
||||||
&cbc.h_coin_envelope));
|
&cbc.h_coin_envelope));
|
||||||
GNUNET_assert (
|
GNUNET_assert (
|
||||||
GNUNET_OK ==
|
GNUNET_OK ==
|
||||||
TALER_denom_sign_blinded (
|
TALER_denom_sign_blinded (
|
||||||
&cbc.sig,
|
&cbc.sig,
|
||||||
&new_dkp[cnt]->priv,
|
&new_dkp[cnt]->priv,
|
||||||
false,
|
false,
|
||||||
bp));
|
bp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
|
perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||||
NUM_ROWS);
|
NUM_ROWS);
|
||||||
//BEGIN
|
|
||||||
FAILIF (GNUNET_OK !=
|
FAILIF (GNUNET_OK !=
|
||||||
plugin->start (plugin->cls,
|
plugin->start (plugin->cls,
|
||||||
"Transaction"));
|
"Transaction"));
|
||||||
for (unsigned int j = 0; j < NUM_ROWS; j++)
|
for (unsigned int j = 0; j < NUM_ROWS; j++)
|
||||||
|
{
|
||||||
|
/*** NEED TO INSERT REFRESH COMMITMENTS + ENSURECOIN ***/
|
||||||
|
union TALER_DenominationBlindingKeyP bks;
|
||||||
|
struct GNUNET_TIME_Timestamp deadline;
|
||||||
|
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||||
|
struct TALER_ReservePublicKeyP reserve_pub;
|
||||||
|
struct TALER_CoinPubHashP c_hash;
|
||||||
|
unsigned int k = (unsigned int) rand () % 5;
|
||||||
|
unsigned int i = perm[j];
|
||||||
|
if (i >= ROUNDS)
|
||||||
|
i = ROUNDS; /* throw-away slot, do not keep around */
|
||||||
|
depos[i].deposit_fee = fees.deposit;
|
||||||
|
RND_BLK (&coin_pub);
|
||||||
|
RND_BLK (&c_hash);
|
||||||
|
RND_BLK (&reserve_pub);
|
||||||
|
RND_BLK (&cbc.reserve_sig);
|
||||||
|
TALER_denom_pub_hash (&new_dkp[k]->pub,
|
||||||
|
&cbc.denom_pub_hash);
|
||||||
|
deadline = GNUNET_TIME_timestamp_get ();
|
||||||
|
RND_BLK (&depos[i].coin.coin_pub);
|
||||||
|
TALER_denom_pub_hash (&new_dkp[k]->pub,
|
||||||
|
&depos[i].coin.denom_pub_hash);
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
|
||||||
|
&ccoin->coin_sig,
|
||||||
|
&bks,
|
||||||
|
&c_hash,
|
||||||
|
&alg_values,
|
||||||
|
&new_dkp[k]->pub));
|
||||||
|
RND_BLK (&depos[i].merchant_pub);
|
||||||
|
RND_BLK (&depos[i].csig);
|
||||||
|
RND_BLK (&depos[i].h_contract_terms);
|
||||||
|
RND_BLK (&depos[i].wire_salt);
|
||||||
|
depos[i].amount_with_fee = value;
|
||||||
|
depos[i].refund_deadline = deadline;
|
||||||
|
depos[i].wire_deadline = deadline;
|
||||||
|
depos[i].receiver_wire_account =
|
||||||
|
"payto://iban/DE67830654080004822650?receiver-name=Test";
|
||||||
|
TALER_merchant_wire_signature_hash (
|
||||||
|
"payto://iban/DE67830654080004822650?receiver-name=Test",
|
||||||
|
&depos[i].wire_salt,
|
||||||
|
&h_wire_wt);
|
||||||
|
cbc.reserve_pub = reserve_pub;
|
||||||
|
cbc.amount_with_fee = value;
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_set_zero (CURRENCY,
|
||||||
|
&cbc.withdraw_fee));
|
||||||
{
|
{
|
||||||
/*** NEED TO INSERT REFRESH COMMITMENTS + ENSURECOIN ***/
|
bool found;
|
||||||
union TALER_DenominationBlindingKeyP bks;
|
bool nonce_ok;
|
||||||
struct GNUNET_TIME_Timestamp deadline;
|
bool balance_ok;
|
||||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
uint64_t ruuid;
|
||||||
struct TALER_ReservePublicKeyP reserve_pub;
|
struct GNUNET_TIME_Timestamp now;
|
||||||
struct TALER_CoinPubHashP c_hash;
|
|
||||||
unsigned int k = (unsigned int)rand()%5;
|
now = GNUNET_TIME_timestamp_get ();
|
||||||
unsigned int i = perm[j];
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
if (i >= ROUNDS)
|
plugin->do_withdraw (plugin->cls,
|
||||||
i = ROUNDS; /* throw-away slot, do not keep around */
|
NULL,
|
||||||
depos[i].deposit_fee = fees.deposit;
|
&cbc,
|
||||||
RND_BLK (&coin_pub);
|
now,
|
||||||
RND_BLK (&c_hash);
|
&found,
|
||||||
RND_BLK (&reserve_pub);
|
&balance_ok,
|
||||||
RND_BLK (&cbc.reserve_sig);
|
&nonce_ok,
|
||||||
TALER_denom_pub_hash (&new_dkp[k]->pub,
|
&ruuid));
|
||||||
&cbc.denom_pub_hash);
|
|
||||||
deadline = GNUNET_TIME_timestamp_get ();
|
|
||||||
RND_BLK (&depos[i].coin.coin_pub);
|
|
||||||
TALER_denom_pub_hash (&new_dkp[k]->pub,
|
|
||||||
&depos[i].coin.denom_pub_hash);
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
|
|
||||||
&ccoin->coin_sig,
|
|
||||||
&bks,
|
|
||||||
&c_hash,
|
|
||||||
&alg_values,
|
|
||||||
&new_dkp[k]->pub));
|
|
||||||
RND_BLK (&depos[i].merchant_pub);
|
|
||||||
RND_BLK (&depos[i].csig);
|
|
||||||
RND_BLK (&depos[i].h_contract_terms);
|
|
||||||
RND_BLK (&depos[i].wire_salt);
|
|
||||||
depos[i].amount_with_fee = value;
|
|
||||||
depos[i].refund_deadline = deadline;
|
|
||||||
depos[i].wire_deadline = deadline;
|
|
||||||
depos[i].receiver_wire_account =
|
|
||||||
"payto://iban/DE67830654080004822650?receiver-name=Test";
|
|
||||||
TALER_merchant_wire_signature_hash (
|
|
||||||
"payto://iban/DE67830654080004822650?receiver-name=Test",
|
|
||||||
&depos[i].wire_salt,
|
|
||||||
&h_wire_wt);
|
|
||||||
cbc.reserve_pub = reserve_pub;
|
|
||||||
cbc.amount_with_fee = value;
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_set_zero (CURRENCY,
|
|
||||||
&cbc.withdraw_fee));
|
|
||||||
{
|
|
||||||
/* INSERT WIRE TARGETS */
|
|
||||||
bool found;
|
|
||||||
bool nonce_ok;
|
|
||||||
bool balance_ok;
|
|
||||||
uint64_t ruuid;
|
|
||||||
struct GNUNET_TIME_Timestamp now;
|
|
||||||
now = GNUNET_TIME_timestamp_get ();
|
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
|
||||||
plugin->do_withdraw (plugin->cls,
|
|
||||||
NULL,
|
|
||||||
&cbc,
|
|
||||||
now,
|
|
||||||
&found,
|
|
||||||
&balance_ok,
|
|
||||||
&nonce_ok,
|
|
||||||
&ruuid));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
/* ENSURE_COIN_KNOWN */
|
|
||||||
uint64_t known_coin_id;
|
|
||||||
struct TALER_DenominationHashP dph;
|
|
||||||
struct TALER_AgeCommitmentHash agh;
|
|
||||||
FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
|
|
||||||
plugin->ensure_coin_known (plugin->cls,
|
|
||||||
&depos[i].coin,
|
|
||||||
&known_coin_id,
|
|
||||||
&dph,
|
|
||||||
&agh));
|
|
||||||
refresh.coin = depos[i].coin;
|
|
||||||
RND_BLK (&refresh.coin_sig);
|
|
||||||
RND_BLK (&refresh.rc);
|
|
||||||
refresh.amount_with_fee = value;
|
|
||||||
refresh.noreveal_index = MELT_NOREVEAL_INDEX;
|
|
||||||
}
|
|
||||||
/*STORE INTO DEPOSIT*/
|
|
||||||
{
|
|
||||||
struct GNUNET_TIME_Timestamp now;
|
|
||||||
now = GNUNET_TIME_timestamp_get ();
|
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
|
||||||
plugin->insert_deposit (plugin->cls,
|
|
||||||
now,
|
|
||||||
&depos[i]));
|
|
||||||
}
|
|
||||||
if (ROUNDS == i)
|
|
||||||
TALER_denom_sig_free (&depos[i].coin.denom_sig);
|
|
||||||
}
|
}
|
||||||
/* End of benchmark setup */
|
{
|
||||||
GNUNET_free(perm);
|
/* ENSURE_COIN_KNOWN */
|
||||||
// commit
|
uint64_t known_coin_id;
|
||||||
|
struct TALER_DenominationHashP dph;
|
||||||
|
struct TALER_AgeCommitmentHash agh;
|
||||||
|
FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
|
||||||
|
plugin->ensure_coin_known (plugin->cls,
|
||||||
|
&depos[i].coin,
|
||||||
|
&known_coin_id,
|
||||||
|
&dph,
|
||||||
|
&agh));
|
||||||
|
refresh.coin = depos[i].coin;
|
||||||
|
RND_BLK (&refresh.coin_sig);
|
||||||
|
RND_BLK (&refresh.rc);
|
||||||
|
refresh.amount_with_fee = value;
|
||||||
|
refresh.noreveal_index = MELT_NOREVEAL_INDEX;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
struct GNUNET_TIME_Timestamp now;
|
||||||
|
|
||||||
|
now = GNUNET_TIME_timestamp_get ();
|
||||||
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
|
plugin->insert_deposit (plugin->cls,
|
||||||
|
now,
|
||||||
|
&depos[i]));
|
||||||
|
}
|
||||||
|
if (ROUNDS == i)
|
||||||
|
TALER_denom_sig_free (&depos[i].coin.denom_sig);
|
||||||
|
}
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||||
plugin->commit (plugin->cls));
|
plugin->commit (plugin->cls));
|
||||||
|
GNUNET_free (perm);
|
||||||
|
/* End of benchmark setup */
|
||||||
|
|
||||||
/**** CALL GET READY DEPOSIT ****/
|
/**** CALL GET READY DEPOSIT ****/
|
||||||
for (unsigned int r=0; r< ROUNDS; r++)
|
for (unsigned int r = 0; r< ROUNDS; r++)
|
||||||
{
|
{
|
||||||
struct GNUNET_TIME_Absolute time;
|
struct GNUNET_TIME_Absolute time;
|
||||||
struct GNUNET_TIME_Relative duration;
|
struct GNUNET_TIME_Relative duration;
|
||||||
struct TALER_MerchantPublicKeyP merchant_pub;
|
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||||
char *payto_uri;
|
char *payto_uri;
|
||||||
time = GNUNET_TIME_absolute_get();
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
|
||||||
plugin->get_ready_deposit (plugin->cls,
|
|
||||||
0,
|
|
||||||
INT32_MAX,
|
|
||||||
&merchant_pub,
|
|
||||||
&payto_uri));
|
|
||||||
|
|
||||||
|
time = GNUNET_TIME_absolute_get ();
|
||||||
|
qs = plugin->get_ready_deposit (plugin->cls,
|
||||||
|
0,
|
||||||
|
INT32_MAX,
|
||||||
|
&merchant_pub,
|
||||||
|
&payto_uri);
|
||||||
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs);
|
||||||
duration = GNUNET_TIME_absolute_get_duration (time);
|
duration = GNUNET_TIME_absolute_get_duration (time);
|
||||||
times = GNUNET_TIME_relative_add (times,
|
times = GNUNET_TIME_relative_add (times,
|
||||||
duration);
|
duration);
|
||||||
duration_sq = duration.rel_value_us * duration.rel_value_us;
|
duration_sq = duration.rel_value_us * duration.rel_value_us;
|
||||||
GNUNET_assert (duration_sq / duration.rel_value_us == duration.rel_value_us);
|
GNUNET_assert (duration_sq / duration.rel_value_us ==
|
||||||
|
duration.rel_value_us);
|
||||||
GNUNET_assert (sqrs + duration_sq >= sqrs);
|
GNUNET_assert (sqrs + duration_sq >= sqrs);
|
||||||
sqrs += duration_sq;
|
sqrs += duration_sq;
|
||||||
}
|
}
|
||||||
@ -447,15 +447,14 @@ run (void *cls)
|
|||||||
ROUNDS);
|
ROUNDS);
|
||||||
avg_dbl = avg.rel_value_us;
|
avg_dbl = avg.rel_value_us;
|
||||||
variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
|
variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
|
||||||
fprintf(stdout,
|
fprintf (stdout,
|
||||||
"%8llu ± %6.0f\n",
|
"%8llu ± %6.0f\n",
|
||||||
(unsigned long long) avg.rel_value_us,
|
(unsigned long long) avg.rel_value_us,
|
||||||
sqrt (variance / (ROUNDS-1)));
|
sqrt (variance / (ROUNDS - 1)));
|
||||||
}
|
}
|
||||||
result = 0;
|
result = 0;
|
||||||
drop:
|
drop:
|
||||||
GNUNET_break (GNUNET_OK ==
|
// GNUNET_break (GNUNET_OK == plugin->drop_tables (plugin->cls));
|
||||||
plugin->drop_tables (plugin->cls));
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (NULL != revealed_coins)
|
if (NULL != revealed_coins)
|
||||||
{
|
{
|
||||||
@ -473,12 +472,12 @@ cleanup:
|
|||||||
cnt++)
|
cnt++)
|
||||||
destroy_denom_key_pair (new_dkp[cnt]);
|
destroy_denom_key_pair (new_dkp[cnt]);
|
||||||
GNUNET_free (new_dkp);
|
GNUNET_free (new_dkp);
|
||||||
for (unsigned int i=0; i< ROUNDS ; i++)
|
for (unsigned int i = 0; i< ROUNDS; i++)
|
||||||
{
|
{
|
||||||
TALER_denom_sig_free (&depos[i].coin.denom_sig);
|
TALER_denom_sig_free (&depos[i].coin.denom_sig);
|
||||||
}
|
}
|
||||||
GNUNET_free(depos);
|
GNUNET_free (depos);
|
||||||
GNUNET_free(ref);
|
GNUNET_free (ref);
|
||||||
TALER_EXCHANGEDB_plugin_unload (plugin);
|
TALER_EXCHANGEDB_plugin_unload (plugin);
|
||||||
plugin = NULL;
|
plugin = NULL;
|
||||||
}
|
}
|
||||||
@ -490,7 +489,6 @@ main (int argc,
|
|||||||
{
|
{
|
||||||
const char *plugin_name;
|
const char *plugin_name;
|
||||||
char *config_filename;
|
char *config_filename;
|
||||||
char *testname;
|
|
||||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||||
|
|
||||||
(void) argc;
|
(void) argc;
|
||||||
@ -504,15 +502,17 @@ main (int argc,
|
|||||||
"WARNING",
|
"WARNING",
|
||||||
NULL);
|
NULL);
|
||||||
plugin_name++;
|
plugin_name++;
|
||||||
(void) GNUNET_asprintf (&testname,
|
{
|
||||||
"test-exchange-db-%s",
|
char *testname;
|
||||||
plugin_name);
|
|
||||||
(void) GNUNET_asprintf (&config_filename,
|
GNUNET_asprintf (&testname,
|
||||||
"%s.conf",
|
"test-exchange-db-%s",
|
||||||
testname);
|
plugin_name);
|
||||||
fprintf (stdout,
|
GNUNET_asprintf (&config_filename,
|
||||||
"Using config: %s\n",
|
"%s.conf",
|
||||||
config_filename);
|
testname);
|
||||||
|
GNUNET_free (testname);
|
||||||
|
}
|
||||||
cfg = GNUNET_CONFIGURATION_create ();
|
cfg = GNUNET_CONFIGURATION_create ();
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CONFIGURATION_parse (cfg,
|
GNUNET_CONFIGURATION_parse (cfg,
|
||||||
@ -520,16 +520,14 @@ main (int argc,
|
|||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
GNUNET_free (config_filename);
|
GNUNET_free (config_filename);
|
||||||
GNUNET_free (testname);
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
GNUNET_SCHEDULER_run (&run,
|
GNUNET_SCHEDULER_run (&run,
|
||||||
cfg);
|
cfg);
|
||||||
GNUNET_CONFIGURATION_destroy (cfg);
|
GNUNET_CONFIGURATION_destroy (cfg);
|
||||||
GNUNET_free (config_filename);
|
GNUNET_free (config_filename);
|
||||||
GNUNET_free (testname);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end of test_exchangedb_by_j.c */
|
/* end of perf_deposits_get_ready.c */
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2014-2022 Taler Systems SA
|
Copyright (C) 2014-2023 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
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
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -14,8 +14,8 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @file exchangedb/test_exchangedb_populate_link_data.c
|
* @file exchangedb/perf_get_link_data.c
|
||||||
* @brief test cases for DB interaction functions
|
* @brief benchmark for get_link_data
|
||||||
* @author Joseph Xu
|
* @author Joseph Xu
|
||||||
*/
|
*/
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
@ -29,7 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
#define FAILIF(cond) \
|
#define FAILIF(cond) \
|
||||||
do { \
|
do { \
|
||||||
if (! (cond)) {break;} \
|
if (! (cond)) {break;} \
|
||||||
GNUNET_break (0); \
|
GNUNET_break (0); \
|
||||||
goto drop; \
|
goto drop; \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -166,6 +166,8 @@ create_denom_key_pair (unsigned int size,
|
|||||||
}
|
}
|
||||||
return dkp;
|
return dkp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called with the session hashes and transfer secret
|
* Function called with the session hashes and transfer secret
|
||||||
* information for a given coin.
|
* information for a given coin.
|
||||||
@ -199,22 +201,22 @@ run (void *cls)
|
|||||||
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
|
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
|
||||||
const uint32_t num_partitions = 10;
|
const uint32_t num_partitions = 10;
|
||||||
struct DenomKeyPair *dkp = NULL;
|
struct DenomKeyPair *dkp = NULL;
|
||||||
struct TALER_EXCHANGEDB_Deposit *depos=NULL;
|
struct TALER_EXCHANGEDB_Deposit *depos = NULL;
|
||||||
struct TALER_Amount value;
|
struct TALER_Amount value;
|
||||||
struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
|
struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
|
||||||
unsigned long long sqrs=0;
|
unsigned long long sqrs = 0;
|
||||||
struct TALER_EXCHANGEDB_Refund *ref=NULL;
|
struct TALER_EXCHANGEDB_Refund *ref = NULL;
|
||||||
unsigned int *perm;
|
unsigned int *perm;
|
||||||
unsigned long long duration_sq;
|
unsigned long long duration_sq;
|
||||||
struct TALER_ExchangeWithdrawValues alg_values = {
|
struct TALER_ExchangeWithdrawValues alg_values = {
|
||||||
.cipher = TALER_DENOMINATION_RSA
|
.cipher = TALER_DENOMINATION_RSA
|
||||||
};
|
};
|
||||||
|
|
||||||
ref = GNUNET_new_array (ROUNDS +1,
|
ref = GNUNET_new_array (ROUNDS + 1,
|
||||||
struct TALER_EXCHANGEDB_Refund);
|
struct TALER_EXCHANGEDB_Refund);
|
||||||
depos = GNUNET_new_array (ROUNDS +1,
|
depos = GNUNET_new_array (ROUNDS + 1,
|
||||||
struct TALER_EXCHANGEDB_Deposit);
|
struct TALER_EXCHANGEDB_Deposit);
|
||||||
refresh = GNUNET_new_array (ROUNDS +1,
|
refresh = GNUNET_new_array (ROUNDS + 1,
|
||||||
struct TALER_EXCHANGEDB_Refresh);
|
struct TALER_EXCHANGEDB_Refresh);
|
||||||
|
|
||||||
if (NULL ==
|
if (NULL ==
|
||||||
@ -256,16 +258,14 @@ run (void *cls)
|
|||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_string_to_amount (CURRENCY ":0.000010",
|
TALER_string_to_amount (CURRENCY ":0.000010",
|
||||||
&fees.refund));
|
&fees.refund));
|
||||||
//DENOMINATION
|
|
||||||
{
|
{
|
||||||
//PAIR KEY LIST
|
|
||||||
new_dkp = GNUNET_new_array (MELT_NEW_COINS,
|
new_dkp = GNUNET_new_array (MELT_NEW_COINS,
|
||||||
struct DenomKeyPair *);
|
struct DenomKeyPair *);
|
||||||
|
|
||||||
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
|
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
|
||||||
{
|
{
|
||||||
struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
|
struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
|
||||||
|
|
||||||
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
|
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
|
||||||
now,
|
now,
|
||||||
&value,
|
&value,
|
||||||
@ -275,7 +275,6 @@ run (void *cls)
|
|||||||
}
|
}
|
||||||
perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
|
perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||||
NUM_ROWS);
|
NUM_ROWS);
|
||||||
//BEGIN
|
|
||||||
FAILIF (GNUNET_OK !=
|
FAILIF (GNUNET_OK !=
|
||||||
plugin->start (plugin->cls,
|
plugin->start (plugin->cls,
|
||||||
"Transaction"));
|
"Transaction"));
|
||||||
@ -290,89 +289,96 @@ run (void *cls)
|
|||||||
i = ROUNDS; /* throw-away slot, do not keep around */
|
i = ROUNDS; /* throw-away slot, do not keep around */
|
||||||
RND_BLK (&depos[i].coin.coin_pub);
|
RND_BLK (&depos[i].coin.coin_pub);
|
||||||
ZR_BLK (&cbc);
|
ZR_BLK (&cbc);
|
||||||
TALER_denom_pub_hash (&new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->pub,
|
TALER_denom_pub_hash (&new_dkp[(unsigned int) rand ()
|
||||||
|
% MELT_NEW_COINS]->pub,
|
||||||
&depos[i].coin.denom_pub_hash);
|
&depos[i].coin.denom_pub_hash);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin revealed_coins[MELT_NEW_COINS];
|
struct TALER_EXCHANGEDB_RefreshRevealedCoin
|
||||||
|
revealed_coins[MELT_NEW_COINS];
|
||||||
for (unsigned int p=0;p<MELT_NEW_COINS;p++)
|
|
||||||
{
|
|
||||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coin = &revealed_coins[p];
|
|
||||||
struct TALER_BlindedPlanchet *bp = &revealed_coin->blinded_planchet;
|
|
||||||
struct TALER_BlindedRsaPlanchet *rp = &bp->details.rsa_blinded_planchet;
|
|
||||||
|
|
||||||
/* h_coin_ev must be unique, but we only have MELT_NEW_COINS created
|
|
||||||
above for NUM_ROWS iterations; instead of making "all new" coins,
|
|
||||||
we simply randomize the hash here as nobody is checking for consistency
|
|
||||||
anyway ;-) */
|
|
||||||
bp->cipher = TALER_DENOMINATION_RSA;
|
|
||||||
rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
|
|
||||||
GNUNET_CRYPTO_QUALITY_WEAK,
|
|
||||||
(RSA_KEY_SIZE / 8) - 1);
|
|
||||||
rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
|
|
||||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
|
||||||
rp->blinded_msg,
|
|
||||||
rp->blinded_msg_size);
|
|
||||||
TALER_denom_pub_hash (&new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->pub,
|
|
||||||
&revealed_coin->h_denom_pub);
|
|
||||||
revealed_coin->exchange_vals = alg_values;
|
|
||||||
TALER_coin_ev_hash (bp,
|
|
||||||
&revealed_coin->h_denom_pub,
|
|
||||||
&revealed_coin->coin_envelope_hash);
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_denom_sign_blinded (&revealed_coin->coin_sig,
|
|
||||||
&new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->priv,
|
|
||||||
true,
|
|
||||||
bp));
|
|
||||||
GNUNET_assert (
|
|
||||||
GNUNET_OK ==
|
|
||||||
TALER_denom_sign_blinded (
|
|
||||||
&cbc.sig,
|
|
||||||
&new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->priv,
|
|
||||||
false,
|
|
||||||
bp));
|
|
||||||
}
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
|
|
||||||
&cbc.sig,
|
|
||||||
&bks,
|
|
||||||
&c_hash,
|
|
||||||
&alg_values,
|
|
||||||
&new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->pub));
|
|
||||||
{
|
|
||||||
/* ENSURE_COIN_KNOWN */
|
|
||||||
struct TALER_DenominationHashP dph;
|
|
||||||
struct TALER_AgeCommitmentHash agh;
|
|
||||||
bool zombie_required = false;
|
|
||||||
bool balance_ok;
|
|
||||||
|
|
||||||
FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
|
for (unsigned int p = 0; p<MELT_NEW_COINS; p++)
|
||||||
plugin->ensure_coin_known (plugin->cls,
|
{
|
||||||
&depos[i].coin,
|
struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coin =
|
||||||
&known_coin_id,
|
&revealed_coins[p];
|
||||||
&dph,
|
struct TALER_BlindedPlanchet *bp = &revealed_coin->blinded_planchet;
|
||||||
&agh));
|
struct TALER_BlindedRsaPlanchet *rp = &bp->details.rsa_blinded_planchet;
|
||||||
/**** INSERT REFRESH COMMITMENTS ****/
|
|
||||||
refresh[i].coin = depos[i].coin;
|
/* h_coin_ev must be unique, but we only have MELT_NEW_COINS created
|
||||||
RND_BLK (&refresh[i].coin_sig);
|
above for NUM_ROWS iterations; instead of making "all new" coins,
|
||||||
RND_BLK (&refresh[i].rc);
|
we simply randomize the hash here as nobody is checking for consistency
|
||||||
refresh[i].amount_with_fee = value;
|
anyway ;-) */
|
||||||
refresh[i].noreveal_index = MELT_NOREVEAL_INDEX;
|
bp->cipher = TALER_DENOMINATION_RSA;
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
|
||||||
plugin->do_melt (plugin->cls,
|
GNUNET_CRYPTO_QUALITY_WEAK,
|
||||||
NULL,
|
(RSA_KEY_SIZE / 8) - 1);
|
||||||
&refresh[i],
|
rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
|
||||||
known_coin_id,
|
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||||
&zombie_required,
|
rp->blinded_msg,
|
||||||
&balance_ok));
|
rp->blinded_msg_size);
|
||||||
}
|
TALER_denom_pub_hash (&new_dkp[(unsigned int) rand ()
|
||||||
|
% MELT_NEW_COINS]->pub,
|
||||||
|
&revealed_coin->h_denom_pub);
|
||||||
|
revealed_coin->exchange_vals = alg_values;
|
||||||
|
TALER_coin_ev_hash (bp,
|
||||||
|
&revealed_coin->h_denom_pub,
|
||||||
|
&revealed_coin->coin_envelope_hash);
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_denom_sign_blinded (&revealed_coin->coin_sig,
|
||||||
|
&new_dkp[(unsigned
|
||||||
|
int) rand ()
|
||||||
|
% MELT_NEW_COINS]->
|
||||||
|
priv,
|
||||||
|
true,
|
||||||
|
bp));
|
||||||
|
GNUNET_assert (
|
||||||
|
GNUNET_OK ==
|
||||||
|
TALER_denom_sign_blinded (
|
||||||
|
&cbc.sig,
|
||||||
|
&new_dkp[(unsigned int) rand () % MELT_NEW_COINS]->priv,
|
||||||
|
false,
|
||||||
|
bp));
|
||||||
|
}
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
|
||||||
|
&cbc.sig,
|
||||||
|
&bks,
|
||||||
|
&c_hash,
|
||||||
|
&alg_values,
|
||||||
|
&new_dkp[(unsigned int) rand ()
|
||||||
|
% MELT_NEW_COINS]->pub));
|
||||||
|
{
|
||||||
|
/* ENSURE_COIN_KNOWN */
|
||||||
|
struct TALER_DenominationHashP dph;
|
||||||
|
struct TALER_AgeCommitmentHash agh;
|
||||||
|
bool zombie_required = false;
|
||||||
|
bool balance_ok;
|
||||||
|
|
||||||
|
FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
|
||||||
|
plugin->ensure_coin_known (plugin->cls,
|
||||||
|
&depos[i].coin,
|
||||||
|
&known_coin_id,
|
||||||
|
&dph,
|
||||||
|
&agh));
|
||||||
|
/**** INSERT REFRESH COMMITMENTS ****/
|
||||||
|
refresh[i].coin = depos[i].coin;
|
||||||
|
RND_BLK (&refresh[i].coin_sig);
|
||||||
|
RND_BLK (&refresh[i].rc);
|
||||||
|
refresh[i].amount_with_fee = value;
|
||||||
|
refresh[i].noreveal_index = MELT_NOREVEAL_INDEX;
|
||||||
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
|
plugin->do_melt (plugin->cls,
|
||||||
|
NULL,
|
||||||
|
&refresh[i],
|
||||||
|
known_coin_id,
|
||||||
|
&zombie_required,
|
||||||
|
&balance_ok));
|
||||||
|
}
|
||||||
/****GET melt_serial_id generated by default****/
|
/****GET melt_serial_id generated by default****/
|
||||||
{
|
{
|
||||||
struct TALER_EXCHANGEDB_Melt ret_refresh_session;
|
struct TALER_EXCHANGEDB_Melt ret_refresh_session;
|
||||||
|
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
plugin->get_melt (plugin->cls,
|
plugin->get_melt (plugin->cls,
|
||||||
&refresh[i].rc,
|
&refresh[i].rc,
|
||||||
@ -382,7 +388,7 @@ run (void *cls)
|
|||||||
/**** INSERT REFRESH_REVEAL + TRANSFER_KEYS *****/
|
/**** INSERT REFRESH_REVEAL + TRANSFER_KEYS *****/
|
||||||
{
|
{
|
||||||
static unsigned int cnt;
|
static unsigned int cnt;
|
||||||
|
|
||||||
RND_BLK (&tprivs);
|
RND_BLK (&tprivs);
|
||||||
RND_BLK (&tpub);
|
RND_BLK (&tpub);
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
@ -398,14 +404,14 @@ run (void *cls)
|
|||||||
}
|
}
|
||||||
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
|
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
|
||||||
{
|
{
|
||||||
TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig);
|
TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig);
|
||||||
TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet);
|
TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* {
|
/* {
|
||||||
struct TALER_CoinSpendPublicKeyP ocp;
|
struct TALER_CoinSpendPublicKeyP ocp;
|
||||||
uint64_t rrc_serial;
|
uint64_t rrc_serial;
|
||||||
|
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
plugin->get_old_coin_by_h_blind (plugin->cls,
|
plugin->get_old_coin_by_h_blind (plugin->cls,
|
||||||
&revealed_coins->coin_envelope_hash,
|
&revealed_coins->coin_envelope_hash,
|
||||||
@ -417,17 +423,15 @@ run (void *cls)
|
|||||||
TALER_denom_sig_free (&depos[i].coin.denom_sig);
|
TALER_denom_sig_free (&depos[i].coin.denom_sig);
|
||||||
}
|
}
|
||||||
/* End of benchmark setup */
|
/* End of benchmark setup */
|
||||||
GNUNET_free(perm);
|
GNUNET_free (perm);
|
||||||
// commit
|
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||||
plugin->commit (plugin->cls));
|
plugin->commit (plugin->cls));
|
||||||
/**** CALL GET LINK DATA ****/
|
for (unsigned int r = 0; r< ROUNDS; r++)
|
||||||
for (unsigned int r=0; r< ROUNDS; r++)
|
|
||||||
{
|
{
|
||||||
struct GNUNET_TIME_Absolute time;
|
struct GNUNET_TIME_Absolute time;
|
||||||
struct GNUNET_TIME_Relative duration;
|
struct GNUNET_TIME_Relative duration;
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
time = GNUNET_TIME_absolute_get();
|
time = GNUNET_TIME_absolute_get ();
|
||||||
|
|
||||||
qs = plugin->get_link_data (plugin->cls,
|
qs = plugin->get_link_data (plugin->cls,
|
||||||
&refresh[r].coin.coin_pub,
|
&refresh[r].coin.coin_pub,
|
||||||
@ -439,7 +443,8 @@ run (void *cls)
|
|||||||
times = GNUNET_TIME_relative_add (times,
|
times = GNUNET_TIME_relative_add (times,
|
||||||
duration);
|
duration);
|
||||||
duration_sq = duration.rel_value_us * duration.rel_value_us;
|
duration_sq = duration.rel_value_us * duration.rel_value_us;
|
||||||
GNUNET_assert (duration_sq / duration.rel_value_us == duration.rel_value_us);
|
GNUNET_assert (duration_sq / duration.rel_value_us ==
|
||||||
|
duration.rel_value_us);
|
||||||
GNUNET_assert (sqrs + duration_sq >= sqrs);
|
GNUNET_assert (sqrs + duration_sq >= sqrs);
|
||||||
sqrs += duration_sq;
|
sqrs += duration_sq;
|
||||||
}
|
}
|
||||||
@ -454,10 +459,10 @@ run (void *cls)
|
|||||||
ROUNDS);
|
ROUNDS);
|
||||||
avg_dbl = avg.rel_value_us;
|
avg_dbl = avg.rel_value_us;
|
||||||
variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
|
variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
|
||||||
fprintf(stdout,
|
fprintf (stdout,
|
||||||
"%8llu ± %6.0f\n",
|
"%8llu ± %6.0f\n",
|
||||||
(unsigned long long) avg.rel_value_us,
|
(unsigned long long) avg.rel_value_us,
|
||||||
sqrt (variance / (ROUNDS-1)));
|
sqrt (variance / (ROUNDS - 1)));
|
||||||
}
|
}
|
||||||
result = 0;
|
result = 0;
|
||||||
drop:
|
drop:
|
||||||
@ -470,13 +475,13 @@ cleanup:
|
|||||||
cnt++)
|
cnt++)
|
||||||
destroy_denom_key_pair (new_dkp[cnt]);
|
destroy_denom_key_pair (new_dkp[cnt]);
|
||||||
GNUNET_free (new_dkp);
|
GNUNET_free (new_dkp);
|
||||||
for (unsigned int i=0; i< ROUNDS; i++)
|
for (unsigned int i = 0; i< ROUNDS; i++)
|
||||||
{
|
{
|
||||||
TALER_denom_sig_free (&depos[i].coin.denom_sig);
|
TALER_denom_sig_free (&depos[i].coin.denom_sig);
|
||||||
}
|
}
|
||||||
GNUNET_free(depos);
|
GNUNET_free (depos);
|
||||||
GNUNET_free(ref);
|
GNUNET_free (ref);
|
||||||
GNUNET_free(refresh);
|
GNUNET_free (refresh);
|
||||||
dkp = NULL;
|
dkp = NULL;
|
||||||
TALER_EXCHANGEDB_plugin_unload (plugin);
|
TALER_EXCHANGEDB_plugin_unload (plugin);
|
||||||
plugin = NULL;
|
plugin = NULL;
|
||||||
@ -509,9 +514,6 @@ main (int argc,
|
|||||||
(void) GNUNET_asprintf (&config_filename,
|
(void) GNUNET_asprintf (&config_filename,
|
||||||
"%s.conf",
|
"%s.conf",
|
||||||
testname);
|
testname);
|
||||||
fprintf (stdout,
|
|
||||||
"Using config: %s\n",
|
|
||||||
config_filename);
|
|
||||||
cfg = GNUNET_CONFIGURATION_create ();
|
cfg = GNUNET_CONFIGURATION_create ();
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CONFIGURATION_parse (cfg,
|
GNUNET_CONFIGURATION_parse (cfg,
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2014-2022 Taler Systems SA
|
Copyright (C) 2014-2023 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
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
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -14,8 +14,8 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @file exchangedb/test_exchangedb_by_j.c
|
* @file exchangedb/perf_reserves_in_insert.c
|
||||||
* @brief test cases for DB interaction functions
|
* @brief benchmark for 'reserves_in_insert'
|
||||||
* @author Joseph Xu
|
* @author Joseph Xu
|
||||||
*/
|
*/
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
@ -23,6 +23,7 @@
|
|||||||
#include "taler_json_lib.h"
|
#include "taler_json_lib.h"
|
||||||
#include "taler_exchangedb_plugin.h"
|
#include "taler_exchangedb_plugin.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global result from the testcase.
|
* Global result from the testcase.
|
||||||
*/
|
*/
|
||||||
@ -33,7 +34,7 @@ static int result;
|
|||||||
*/
|
*/
|
||||||
#define FAILIF(cond) \
|
#define FAILIF(cond) \
|
||||||
do { \
|
do { \
|
||||||
if (! (cond)) { break;} \
|
if (! (cond)) {break;} \
|
||||||
GNUNET_break (0); \
|
GNUNET_break (0); \
|
||||||
goto drop; \
|
goto drop; \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -51,6 +52,10 @@ static int result;
|
|||||||
#define ZR_BLK(ptr) \
|
#define ZR_BLK(ptr) \
|
||||||
memset (ptr, 0, sizeof (*ptr))
|
memset (ptr, 0, sizeof (*ptr))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many rounds do we average over?
|
||||||
|
*/
|
||||||
|
#define ROUNDS 5
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currency we use. Must match test-exchange-db-*.conf.
|
* Currency we use. Must match test-exchange-db-*.conf.
|
||||||
@ -73,6 +78,10 @@ run (void *cls)
|
|||||||
{
|
{
|
||||||
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
|
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
|
||||||
const uint32_t num_partitions = 10;
|
const uint32_t num_partitions = 10;
|
||||||
|
static unsigned int batches[] = {1, 1, 2, 3, 4, 16, 32 };
|
||||||
|
const unsigned int lcm = 3 * 32;
|
||||||
|
struct GNUNET_TIME_Relative times[sizeof (batches) / sizeof(*batches)];
|
||||||
|
unsigned long long sqrs[sizeof (batches) / sizeof(*batches)];
|
||||||
|
|
||||||
if (NULL ==
|
if (NULL ==
|
||||||
(plugin = TALER_EXCHANGEDB_plugin_load (cfg)))
|
(plugin = TALER_EXCHANGEDB_plugin_load (cfg)))
|
||||||
@ -91,46 +100,78 @@ run (void *cls)
|
|||||||
result = 77;
|
result = 77;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
for (unsigned int i = 0; i< 8; i++)
|
|
||||||
{
|
|
||||||
static unsigned int batches[] = {1, 1, 0, 2, 4, 16, 64, 256};
|
|
||||||
const char *sndr = "payto://x-taler-bank/localhost:8080/1";
|
|
||||||
struct TALER_Amount value;
|
|
||||||
unsigned int batch_size = batches[i];
|
|
||||||
struct GNUNET_TIME_Absolute now;
|
|
||||||
struct GNUNET_TIME_Timestamp ts;
|
|
||||||
struct GNUNET_TIME_Relative duration;
|
|
||||||
struct TALER_ReservePublicKeyP reserve_pub;
|
|
||||||
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
memset (times, 0, sizeof (times));
|
||||||
TALER_string_to_amount (CURRENCY ":1.000010",
|
memset (sqrs, 0, sizeof (sqrs));
|
||||||
&value));
|
for (unsigned int r = 0; r < ROUNDS; r++)
|
||||||
now = GNUNET_TIME_absolute_get ();
|
{
|
||||||
ts = GNUNET_TIME_timestamp_get ();
|
for (unsigned int i = 0;
|
||||||
for (unsigned int r = 0; r<10; r++)
|
i< sizeof(batches) / sizeof(*batches);
|
||||||
|
i++)
|
||||||
{
|
{
|
||||||
plugin->start (plugin->cls,
|
unsigned int batch_size = batches[i];
|
||||||
"test_by_exchange_j");
|
struct TALER_Amount value;
|
||||||
for (unsigned int k = 0; k<batch_size; k++)
|
struct GNUNET_TIME_Absolute now;
|
||||||
|
struct GNUNET_TIME_Timestamp ts;
|
||||||
|
unsigned long long duration_sq;
|
||||||
|
struct GNUNET_TIME_Relative duration;
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_string_to_amount (CURRENCY ":1.000010",
|
||||||
|
&value));
|
||||||
|
now = GNUNET_TIME_absolute_get ();
|
||||||
|
ts = GNUNET_TIME_timestamp_get ();
|
||||||
{
|
{
|
||||||
RND_BLK (&reserve_pub);
|
const char *sndr = "payto://x-taler-bank/localhost:8080/1";
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
struct TALER_ReservePublicKeyP reserve_pubs[lcm];
|
||||||
|
struct TALER_EXCHANGEDB_ReserveInInfo reserves[lcm];
|
||||||
|
enum GNUNET_DB_QueryStatus results[lcm];
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k<lcm; k++)
|
||||||
|
{
|
||||||
|
RND_BLK (&reserve_pubs[k]);
|
||||||
|
reserves[k].reserve_pub = &reserve_pubs[k];
|
||||||
|
reserves[k].balance = &value;
|
||||||
|
reserves[k].execution_time = ts;
|
||||||
|
reserves[k].sender_account_details = sndr;
|
||||||
|
reserves[k].exchange_account_name = "name";
|
||||||
|
reserves[k].wire_reference = k;
|
||||||
|
}
|
||||||
|
FAILIF (lcm !=
|
||||||
plugin->reserves_in_insert (plugin->cls,
|
plugin->reserves_in_insert (plugin->cls,
|
||||||
&reserve_pub,
|
reserves,
|
||||||
&value,
|
lcm,
|
||||||
ts,
|
batch_size,
|
||||||
sndr,
|
results));
|
||||||
"section",
|
|
||||||
4));
|
|
||||||
}
|
}
|
||||||
plugin->commit (plugin->cls);
|
duration = GNUNET_TIME_absolute_get_duration (now);
|
||||||
}
|
times[i] = GNUNET_TIME_relative_add (times[i],
|
||||||
duration = GNUNET_TIME_absolute_get_duration (now);
|
duration);
|
||||||
|
duration_sq = duration.rel_value_us * duration.rel_value_us;
|
||||||
|
GNUNET_assert (duration_sq / duration.rel_value_us ==
|
||||||
|
duration.rel_value_us);
|
||||||
|
GNUNET_assert (sqrs[i] + duration_sq >= sqrs[i]);
|
||||||
|
sqrs[i] += duration_sq;
|
||||||
|
} /* for 'i' batch size */
|
||||||
|
} /* for 'r' ROUNDS */
|
||||||
|
|
||||||
|
for (unsigned int i = 0;
|
||||||
|
i< sizeof(batches) / sizeof(*batches);
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
struct GNUNET_TIME_Relative avg;
|
||||||
|
double avg_dbl;
|
||||||
|
double variance;
|
||||||
|
|
||||||
|
avg = GNUNET_TIME_relative_divide (times[i],
|
||||||
|
ROUNDS);
|
||||||
|
avg_dbl = avg.rel_value_us;
|
||||||
|
variance = sqrs[i] - (avg_dbl * avg_dbl * ROUNDS);
|
||||||
fprintf (stdout,
|
fprintf (stdout,
|
||||||
"for a batchsize equal to %d it took %s\n",
|
"Batch[%2u]: %8llu ± %6.0f\n",
|
||||||
batch_size,
|
batches[i],
|
||||||
GNUNET_STRINGS_relative_time_to_string (duration,
|
(unsigned long long) avg.rel_value_us,
|
||||||
GNUNET_NO) );
|
sqrt (variance / (ROUNDS - 1)));
|
||||||
}
|
}
|
||||||
result = 0;
|
result = 0;
|
||||||
drop:
|
drop:
|
||||||
@ -150,7 +191,6 @@ main (int argc,
|
|||||||
char *config_filename;
|
char *config_filename;
|
||||||
char *testname;
|
char *testname;
|
||||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||||
|
|
||||||
(void) argc;
|
(void) argc;
|
||||||
result = -1;
|
result = -1;
|
||||||
if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
|
if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
|
||||||
@ -158,6 +198,7 @@ main (int argc,
|
|||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
GNUNET_log_setup (argv[0],
|
GNUNET_log_setup (argv[0],
|
||||||
"WARNING",
|
"WARNING",
|
||||||
NULL);
|
NULL);
|
||||||
@ -168,9 +209,6 @@ main (int argc,
|
|||||||
(void) GNUNET_asprintf (&config_filename,
|
(void) GNUNET_asprintf (&config_filename,
|
||||||
"%s.conf",
|
"%s.conf",
|
||||||
testname);
|
testname);
|
||||||
fprintf (stdout,
|
|
||||||
"Using config: %s\n",
|
|
||||||
config_filename);
|
|
||||||
cfg = GNUNET_CONFIGURATION_create ();
|
cfg = GNUNET_CONFIGURATION_create ();
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CONFIGURATION_parse (cfg,
|
GNUNET_CONFIGURATION_parse (cfg,
|
||||||
@ -190,4 +228,4 @@ main (int argc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end of test_exchangedb_by_j.c */
|
/* end of perf_reserves_in_insert.c */
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2014-2022 Taler Systems SA
|
Copyright (C) 2014-2023 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
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
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -14,8 +14,8 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @file exchangedb/test_exchangedb_populate_table.c
|
* @file exchangedb/perf_select_refunds_by_coin.c
|
||||||
* @brief test cases for DB interaction functions
|
* @brief benchmark for select_refunds_by_coin
|
||||||
* @author Joseph Xu
|
* @author Joseph Xu
|
||||||
*/
|
*/
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
@ -34,7 +34,7 @@ static int result;
|
|||||||
*/
|
*/
|
||||||
#define FAILIF(cond) \
|
#define FAILIF(cond) \
|
||||||
do { \
|
do { \
|
||||||
if (! (cond)) {break;} \
|
if (! (cond)) {break;} \
|
||||||
GNUNET_break (0); \
|
GNUNET_break (0); \
|
||||||
goto drop; \
|
goto drop; \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -56,24 +56,31 @@ static int result;
|
|||||||
*/
|
*/
|
||||||
#define CURRENCY "EUR"
|
#define CURRENCY "EUR"
|
||||||
#define RSA_KEY_SIZE 1024
|
#define RSA_KEY_SIZE 1024
|
||||||
#define ROUNDS 10000
|
#define ROUNDS 100
|
||||||
#define NUM_ROWS 1000000
|
#define NUM_ROWS 1000
|
||||||
#define MELT_NEW_COINS 5
|
#define MELT_NEW_COINS 5
|
||||||
#define MELT_NOREVEAL_INDEX 1
|
#define MELT_NOREVEAL_INDEX 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database plugin under test.
|
* Database plugin under test.
|
||||||
*/
|
*/
|
||||||
static struct TALER_EXCHANGEDB_Plugin *plugin;
|
static struct TALER_EXCHANGEDB_Plugin *plugin;
|
||||||
|
|
||||||
static struct TALER_DenomFeeSet fees;
|
static struct TALER_DenomFeeSet fees;
|
||||||
|
|
||||||
static struct TALER_MerchantWireHashP h_wire_wt;
|
static struct TALER_MerchantWireHashP h_wire_wt;
|
||||||
|
|
||||||
static struct DenomKeyPair **new_dkp;
|
static struct DenomKeyPair **new_dkp;
|
||||||
|
|
||||||
static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;
|
static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;
|
||||||
|
|
||||||
struct DenomKeyPair
|
struct DenomKeyPair
|
||||||
{
|
{
|
||||||
struct TALER_DenominationPrivateKey priv;
|
struct TALER_DenominationPrivateKey priv;
|
||||||
struct TALER_DenominationPublicKey pub;
|
struct TALER_DenominationPublicKey pub;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a denomination key pair. The key is not necessarily removed from the DB.
|
* Destroy a denomination key pair. The key is not necessarily removed from the DB.
|
||||||
*
|
*
|
||||||
@ -166,6 +173,8 @@ create_denom_key_pair (unsigned int size,
|
|||||||
}
|
}
|
||||||
return dkp;
|
return dkp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback invoked with information about refunds applicable
|
* Callback invoked with information about refunds applicable
|
||||||
* to a particular coin.
|
* to a particular coin.
|
||||||
@ -179,6 +188,7 @@ check_refund_cb (void *cls,
|
|||||||
const struct TALER_Amount *amount_with_fee)
|
const struct TALER_Amount *amount_with_fee)
|
||||||
{
|
{
|
||||||
const struct TALER_EXCHANGEDB_Refund *refund = cls;
|
const struct TALER_EXCHANGEDB_Refund *refund = cls;
|
||||||
|
|
||||||
if (0 != TALER_amount_cmp (amount_with_fee,
|
if (0 != TALER_amount_cmp (amount_with_fee,
|
||||||
&refund->details.refund_amount))
|
&refund->details.refund_amount))
|
||||||
{
|
{
|
||||||
@ -201,7 +211,7 @@ run (void *cls)
|
|||||||
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
|
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
|
||||||
const uint32_t num_partitions = 10;
|
const uint32_t num_partitions = 10;
|
||||||
struct GNUNET_TIME_Timestamp ts;
|
struct GNUNET_TIME_Timestamp ts;
|
||||||
struct TALER_EXCHANGEDB_Deposit *depos=NULL;
|
struct TALER_EXCHANGEDB_Deposit *depos = NULL;
|
||||||
struct GNUNET_TIME_Timestamp deadline;
|
struct GNUNET_TIME_Timestamp deadline;
|
||||||
struct TALER_Amount value;
|
struct TALER_Amount value;
|
||||||
union TALER_DenominationBlindingKeyP bks;
|
union TALER_DenominationBlindingKeyP bks;
|
||||||
@ -209,20 +219,20 @@ run (void *cls)
|
|||||||
struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
|
struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
|
||||||
struct TALER_ExchangeWithdrawValues alg_values = {
|
struct TALER_ExchangeWithdrawValues alg_values = {
|
||||||
.cipher = TALER_DENOMINATION_RSA
|
.cipher = TALER_DENOMINATION_RSA
|
||||||
};
|
};
|
||||||
struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
|
struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
|
||||||
unsigned long long sqrs = 0;
|
unsigned long long sqrs = 0;
|
||||||
struct TALER_EXCHANGEDB_Refund *ref=NULL;
|
struct TALER_EXCHANGEDB_Refund *ref = NULL;
|
||||||
unsigned int *perm;
|
unsigned int *perm;
|
||||||
unsigned long long duration_sq;
|
unsigned long long duration_sq;
|
||||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
|
struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
|
||||||
struct TALER_DenominationPublicKey *new_denom_pubs = NULL;
|
struct TALER_DenominationPublicKey *new_denom_pubs = NULL;
|
||||||
unsigned int count=0;
|
unsigned int count = 0;
|
||||||
|
|
||||||
ref = GNUNET_new_array (ROUNDS +1,
|
ref = GNUNET_new_array (ROUNDS + 1,
|
||||||
struct TALER_EXCHANGEDB_Refund);
|
struct TALER_EXCHANGEDB_Refund);
|
||||||
depos = GNUNET_new_array (ROUNDS +1,
|
depos = GNUNET_new_array (ROUNDS + 1,
|
||||||
struct TALER_EXCHANGEDB_Deposit);
|
struct TALER_EXCHANGEDB_Deposit);
|
||||||
ZR_BLK (&cbc);
|
ZR_BLK (&cbc);
|
||||||
|
|
||||||
@ -249,8 +259,6 @@ run (void *cls)
|
|||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_string_to_amount (CURRENCY ":1.000010",
|
TALER_string_to_amount (CURRENCY ":1.000010",
|
||||||
&value));
|
&value));
|
||||||
@ -270,78 +278,72 @@ run (void *cls)
|
|||||||
|
|
||||||
ts = GNUNET_TIME_timestamp_get ();
|
ts = GNUNET_TIME_timestamp_get ();
|
||||||
deadline = GNUNET_TIME_timestamp_get ();
|
deadline = GNUNET_TIME_timestamp_get ();
|
||||||
//DENOMINATION
|
|
||||||
{
|
{
|
||||||
//PAIR KEY LIST
|
|
||||||
new_dkp = GNUNET_new_array (MELT_NEW_COINS,
|
new_dkp = GNUNET_new_array (MELT_NEW_COINS,
|
||||||
struct DenomKeyPair *);
|
struct DenomKeyPair *);
|
||||||
//PUBLIC KEY LIST
|
|
||||||
new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
|
new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
|
||||||
struct TALER_DenominationPublicKey);
|
struct TALER_DenominationPublicKey);
|
||||||
//REFRESH REVEAL COIN LIST
|
|
||||||
revealed_coins
|
revealed_coins
|
||||||
= GNUNET_new_array (MELT_NEW_COINS,
|
= GNUNET_new_array (MELT_NEW_COINS,
|
||||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin);
|
struct TALER_EXCHANGEDB_RefreshRevealedCoin);
|
||||||
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
|
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
|
||||||
{
|
{
|
||||||
struct GNUNET_TIME_Timestamp now;
|
struct GNUNET_TIME_Timestamp now;
|
||||||
struct TALER_BlindedRsaPlanchet *rp;
|
struct TALER_BlindedRsaPlanchet *rp;
|
||||||
struct TALER_BlindedPlanchet *bp;
|
struct TALER_BlindedPlanchet *bp;
|
||||||
|
|
||||||
now = GNUNET_TIME_timestamp_get ();
|
now = GNUNET_TIME_timestamp_get ();
|
||||||
//5 KEY PAIR
|
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
|
||||||
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
|
now,
|
||||||
now,
|
&value,
|
||||||
&value,
|
&fees);
|
||||||
&fees);
|
GNUNET_assert (NULL != new_dkp[cnt]);
|
||||||
GNUNET_assert (NULL != new_dkp[cnt]);
|
new_denom_pubs[cnt] = new_dkp[cnt]->pub;
|
||||||
new_denom_pubs[cnt] = new_dkp[cnt]->pub;
|
ccoin = &revealed_coins[cnt];
|
||||||
ccoin = &revealed_coins[cnt];
|
bp = &ccoin->blinded_planchet;
|
||||||
bp = &ccoin->blinded_planchet;
|
bp->cipher = TALER_DENOMINATION_RSA;
|
||||||
bp->cipher = TALER_DENOMINATION_RSA;
|
rp = &bp->details.rsa_blinded_planchet;
|
||||||
rp = &bp->details.rsa_blinded_planchet;
|
rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
|
||||||
rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
|
GNUNET_CRYPTO_QUALITY_WEAK,
|
||||||
GNUNET_CRYPTO_QUALITY_WEAK,
|
(RSA_KEY_SIZE / 8) - 1);
|
||||||
(RSA_KEY_SIZE / 8) - 1);
|
rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
|
||||||
rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
|
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
rp->blinded_msg,
|
||||||
rp->blinded_msg,
|
rp->blinded_msg_size);
|
||||||
rp->blinded_msg_size);
|
TALER_denom_pub_hash (&new_dkp[cnt]->pub,
|
||||||
TALER_denom_pub_hash (&new_dkp[cnt]->pub,
|
&ccoin->h_denom_pub);
|
||||||
&ccoin->h_denom_pub);
|
ccoin->exchange_vals = alg_values;
|
||||||
ccoin->exchange_vals = alg_values;
|
TALER_coin_ev_hash (bp,
|
||||||
TALER_coin_ev_hash (bp,
|
&ccoin->h_denom_pub,
|
||||||
&ccoin->h_denom_pub,
|
&ccoin->coin_envelope_hash);
|
||||||
&ccoin->coin_envelope_hash);
|
GNUNET_assert (GNUNET_OK ==
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_denom_sign_blinded (&ccoin->coin_sig,
|
TALER_denom_sign_blinded (&ccoin->coin_sig,
|
||||||
&new_dkp[cnt]->priv,
|
&new_dkp[cnt]->priv,
|
||||||
true,
|
true,
|
||||||
bp));
|
bp));
|
||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_coin_ev_hash (bp,
|
TALER_coin_ev_hash (bp,
|
||||||
&cbc.denom_pub_hash,
|
&cbc.denom_pub_hash,
|
||||||
&cbc.h_coin_envelope));
|
&cbc.h_coin_envelope));
|
||||||
GNUNET_assert (
|
GNUNET_assert (
|
||||||
GNUNET_OK ==
|
GNUNET_OK ==
|
||||||
TALER_denom_sign_blinded (
|
TALER_denom_sign_blinded (
|
||||||
&cbc.sig,
|
&cbc.sig,
|
||||||
&new_dkp[cnt]->priv,
|
&new_dkp[cnt]->priv,
|
||||||
false,
|
false,
|
||||||
bp));
|
bp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
|
perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||||
NUM_ROWS);
|
NUM_ROWS);
|
||||||
// begin
|
|
||||||
FAILIF (GNUNET_OK !=
|
FAILIF (GNUNET_OK !=
|
||||||
plugin->start (plugin->cls,
|
plugin->start (plugin->cls,
|
||||||
"Transaction"));
|
"Transaction"));
|
||||||
for (unsigned int j=0; j< NUM_ROWS; j++)
|
for (unsigned int j = 0; j< NUM_ROWS; j++)
|
||||||
{
|
{
|
||||||
unsigned int i = perm[j];
|
unsigned int i = perm[j];
|
||||||
unsigned int k = (unsigned int)rand()%5;
|
unsigned int k = (unsigned int) rand () % 5;
|
||||||
if (i >= ROUNDS)
|
if (i >= ROUNDS)
|
||||||
i = ROUNDS; /* throw-away slot, do not keep around */
|
i = ROUNDS; /* throw-away slot, do not keep around */
|
||||||
RND_BLK (&coin_pub);
|
RND_BLK (&coin_pub);
|
||||||
@ -350,8 +352,6 @@ run (void *cls)
|
|||||||
RND_BLK (&depos[i].coin.coin_pub);
|
RND_BLK (&depos[i].coin.coin_pub);
|
||||||
TALER_denom_pub_hash (&new_dkp[k]->pub,
|
TALER_denom_pub_hash (&new_dkp[k]->pub,
|
||||||
&depos[i].coin.denom_pub_hash);
|
&depos[i].coin.denom_pub_hash);
|
||||||
// TALER_denom_pub_hash (&dkp->pub,
|
|
||||||
// &ref.coin.denom_pub_hash);
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
|
TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
|
||||||
&cbc.sig,
|
&cbc.sig,
|
||||||
@ -369,15 +369,15 @@ run (void *cls)
|
|||||||
depos[i].receiver_wire_account =
|
depos[i].receiver_wire_account =
|
||||||
"payto://iban/DE67830654080004822650?receiver-name=Test";
|
"payto://iban/DE67830654080004822650?receiver-name=Test";
|
||||||
TALER_merchant_wire_signature_hash (
|
TALER_merchant_wire_signature_hash (
|
||||||
"payto://iban/DE67830654080004822650?receiver-name=Test",
|
"payto://iban/DE67830654080004822650?receiver-name=Test",
|
||||||
&depos[i].wire_salt,
|
&depos[i].wire_salt,
|
||||||
&h_wire_wt);
|
&h_wire_wt);
|
||||||
depos[i].timestamp = ts;
|
depos[i].timestamp = ts;
|
||||||
uint64_t known_coin_id;
|
uint64_t known_coin_id;
|
||||||
{//ENSURE_COIN_KNOWN
|
{
|
||||||
|
|
||||||
struct TALER_DenominationHashP dph;
|
struct TALER_DenominationHashP dph;
|
||||||
struct TALER_AgeCommitmentHash agh;
|
struct TALER_AgeCommitmentHash agh;
|
||||||
|
|
||||||
FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
|
FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
|
||||||
plugin->ensure_coin_known (plugin->cls,
|
plugin->ensure_coin_known (plugin->cls,
|
||||||
&depos[i].coin,
|
&depos[i].coin,
|
||||||
@ -385,9 +385,9 @@ run (void *cls)
|
|||||||
&dph,
|
&dph,
|
||||||
&agh));
|
&agh));
|
||||||
}
|
}
|
||||||
/*STORE INTO DEPOSIT*/
|
|
||||||
{
|
{
|
||||||
struct GNUNET_TIME_Timestamp now;
|
struct GNUNET_TIME_Timestamp now;
|
||||||
|
|
||||||
now = GNUNET_TIME_timestamp_get ();
|
now = GNUNET_TIME_timestamp_get ();
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
plugin->insert_deposit (plugin->cls,
|
plugin->insert_deposit (plugin->cls,
|
||||||
@ -399,12 +399,13 @@ run (void *cls)
|
|||||||
bool refund_ok;
|
bool refund_ok;
|
||||||
bool gone;
|
bool gone;
|
||||||
bool conflict;
|
bool conflict;
|
||||||
unsigned int refund_percent=0;
|
unsigned int refund_percent = 0;
|
||||||
switch (refund_percent){
|
switch (refund_percent)
|
||||||
case 2 ://100% refund
|
{
|
||||||
|
case 2: // 100% refund
|
||||||
ref[i].coin = depos[i].coin;
|
ref[i].coin = depos[i].coin;
|
||||||
ref[i].details.merchant_pub = depos[i].merchant_pub;
|
ref[i].details.merchant_pub = depos[i].merchant_pub;
|
||||||
RND_BLK(&ref[i].details.merchant_sig);
|
RND_BLK (&ref[i].details.merchant_sig);
|
||||||
ref[i].details.h_contract_terms = depos[i].h_contract_terms;
|
ref[i].details.h_contract_terms = depos[i].h_contract_terms;
|
||||||
ref[i].coin.coin_pub = depos[i].coin.coin_pub;
|
ref[i].coin.coin_pub = depos[i].coin.coin_pub;
|
||||||
ref[i].details.rtransaction_id = i;
|
ref[i].details.rtransaction_id = i;
|
||||||
@ -420,58 +421,58 @@ run (void *cls)
|
|||||||
&gone,
|
&gone,
|
||||||
&conflict));
|
&conflict));
|
||||||
break;
|
break;
|
||||||
case 1 ://10% refund
|
case 1:// 10% refund
|
||||||
if (count < (NUM_ROWS/10))
|
if (count < (NUM_ROWS / 10))
|
||||||
{
|
{
|
||||||
|
ref[i].coin = depos[i].coin;
|
||||||
|
ref[i].details.merchant_pub = depos[i].merchant_pub;
|
||||||
|
RND_BLK (&ref[i].details.merchant_sig);
|
||||||
|
ref[i].details.h_contract_terms = depos[i].h_contract_terms;
|
||||||
|
ref[i].coin.coin_pub = depos[i].coin.coin_pub;
|
||||||
|
ref[i].details.rtransaction_id = i;
|
||||||
|
ref[i].details.refund_amount = value;
|
||||||
|
ref[i].details.refund_fee = fees.refund;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ref[i].coin = depos[i].coin;
|
||||||
|
RND_BLK (&ref[i].details.merchant_pub);
|
||||||
|
RND_BLK (&ref[i].details.merchant_sig);
|
||||||
|
RND_BLK (&ref[i].details.h_contract_terms);
|
||||||
|
RND_BLK (&ref[i].coin.coin_pub);
|
||||||
|
ref[i].details.rtransaction_id = i;
|
||||||
|
ref[i].details.refund_amount = value;
|
||||||
|
ref[i].details.refund_fee = fees.refund;
|
||||||
|
}
|
||||||
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
|
plugin->do_refund (plugin->cls,
|
||||||
|
&ref[i],
|
||||||
|
&fees.deposit,
|
||||||
|
known_coin_id,
|
||||||
|
¬_found,
|
||||||
|
&refund_ok,
|
||||||
|
&gone,
|
||||||
|
&conflict));
|
||||||
|
count++;
|
||||||
|
break;
|
||||||
|
case 0:// no refund
|
||||||
ref[i].coin = depos[i].coin;
|
ref[i].coin = depos[i].coin;
|
||||||
ref[i].details.merchant_pub = depos[i].merchant_pub;
|
RND_BLK (&ref[i].details.merchant_pub);
|
||||||
RND_BLK(&ref[i].details.merchant_sig);
|
RND_BLK (&ref[i].details.merchant_sig);
|
||||||
ref[i].details.h_contract_terms = depos[i].h_contract_terms;
|
RND_BLK (&ref[i].details.h_contract_terms);
|
||||||
ref[i].coin.coin_pub = depos[i].coin.coin_pub;
|
RND_BLK (&ref[i].coin.coin_pub);
|
||||||
ref[i].details.rtransaction_id = i;
|
ref[i].details.rtransaction_id = i;
|
||||||
ref[i].details.refund_amount = value;
|
ref[i].details.refund_amount = value;
|
||||||
ref[i].details.refund_fee = fees.refund;
|
ref[i].details.refund_fee = fees.refund;
|
||||||
}
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
else
|
plugin->do_refund (plugin->cls,
|
||||||
{
|
&ref[i],
|
||||||
ref[i].coin = depos[i].coin;
|
&fees.deposit,
|
||||||
RND_BLK(&ref[i].details.merchant_pub);
|
known_coin_id,
|
||||||
RND_BLK(&ref[i].details.merchant_sig);
|
¬_found,
|
||||||
RND_BLK(&ref[i].details.h_contract_terms);
|
&refund_ok,
|
||||||
RND_BLK(&ref[i].coin.coin_pub);
|
&gone,
|
||||||
ref[i].details.rtransaction_id = i;
|
&conflict));
|
||||||
ref[i].details.refund_amount = value;
|
|
||||||
ref[i].details.refund_fee = fees.refund;
|
|
||||||
}
|
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
|
||||||
plugin->do_refund (plugin->cls,
|
|
||||||
&ref[i],
|
|
||||||
&fees.deposit,
|
|
||||||
known_coin_id,
|
|
||||||
¬_found,
|
|
||||||
&refund_ok,
|
|
||||||
&gone,
|
|
||||||
&conflict));
|
|
||||||
count++;
|
|
||||||
break;
|
|
||||||
case 0://no refund
|
|
||||||
ref[i].coin=depos[i].coin;
|
|
||||||
RND_BLK(&ref[i].details.merchant_pub);
|
|
||||||
RND_BLK(&ref[i].details.merchant_sig);
|
|
||||||
RND_BLK(&ref[i].details.h_contract_terms);
|
|
||||||
RND_BLK(&ref[i].coin.coin_pub);
|
|
||||||
ref[i].details.rtransaction_id = i;
|
|
||||||
ref[i].details.refund_amount = value;
|
|
||||||
ref[i].details.refund_fee = fees.refund;
|
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
|
||||||
plugin->do_refund (plugin->cls,
|
|
||||||
&ref[i],
|
|
||||||
&fees.deposit,
|
|
||||||
known_coin_id,
|
|
||||||
¬_found,
|
|
||||||
&refund_ok,
|
|
||||||
&gone,
|
|
||||||
&conflict));
|
|
||||||
break;
|
break;
|
||||||
}/* END OF SWITCH CASE */
|
}/* END OF SWITCH CASE */
|
||||||
}
|
}
|
||||||
@ -480,7 +481,6 @@ run (void *cls)
|
|||||||
}
|
}
|
||||||
/* End of benchmark setup */
|
/* End of benchmark setup */
|
||||||
GNUNET_free (perm);
|
GNUNET_free (perm);
|
||||||
// commit
|
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||||
plugin->commit (plugin->cls));
|
plugin->commit (plugin->cls));
|
||||||
for (unsigned int r = 0; r < ROUNDS; r++)
|
for (unsigned int r = 0; r < ROUNDS; r++)
|
||||||
@ -500,7 +500,8 @@ run (void *cls)
|
|||||||
times = GNUNET_TIME_relative_add (times,
|
times = GNUNET_TIME_relative_add (times,
|
||||||
duration);
|
duration);
|
||||||
duration_sq = duration.rel_value_us * duration.rel_value_us;
|
duration_sq = duration.rel_value_us * duration.rel_value_us;
|
||||||
GNUNET_assert (duration_sq / duration.rel_value_us == duration.rel_value_us);
|
GNUNET_assert (duration_sq / duration.rel_value_us ==
|
||||||
|
duration.rel_value_us);
|
||||||
GNUNET_assert (sqrs + duration_sq >= sqrs);
|
GNUNET_assert (sqrs + duration_sq >= sqrs);
|
||||||
sqrs += duration_sq;
|
sqrs += duration_sq;
|
||||||
}
|
}
|
||||||
@ -514,10 +515,10 @@ run (void *cls)
|
|||||||
ROUNDS);
|
ROUNDS);
|
||||||
avg_dbl = avg.rel_value_us;
|
avg_dbl = avg.rel_value_us;
|
||||||
variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
|
variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
|
||||||
fprintf(stdout,
|
fprintf (stdout,
|
||||||
"%8llu ± %6.0f\n",
|
"%8llu ± %6.0f\n",
|
||||||
(unsigned long long) avg.rel_value_us,
|
(unsigned long long) avg.rel_value_us,
|
||||||
sqrt (variance / (ROUNDS-1)));
|
sqrt (variance / (ROUNDS - 1)));
|
||||||
}
|
}
|
||||||
result = 0;
|
result = 0;
|
||||||
drop:
|
drop:
|
||||||
@ -540,12 +541,12 @@ cleanup:
|
|||||||
cnt++)
|
cnt++)
|
||||||
destroy_denom_key_pair (new_dkp[cnt]);
|
destroy_denom_key_pair (new_dkp[cnt]);
|
||||||
GNUNET_free (new_dkp);
|
GNUNET_free (new_dkp);
|
||||||
for (unsigned int i=0; i< ROUNDS +1 ; i++)
|
for (unsigned int i = 0; i< ROUNDS + 1; i++)
|
||||||
{
|
{
|
||||||
TALER_denom_sig_free (&depos[i].coin.denom_sig);
|
TALER_denom_sig_free (&depos[i].coin.denom_sig);
|
||||||
}
|
}
|
||||||
GNUNET_free(depos);
|
GNUNET_free (depos);
|
||||||
GNUNET_free(ref);
|
GNUNET_free (ref);
|
||||||
TALER_EXCHANGEDB_plugin_unload (plugin);
|
TALER_EXCHANGEDB_plugin_unload (plugin);
|
||||||
plugin = NULL;
|
plugin = NULL;
|
||||||
}
|
}
|
||||||
@ -557,7 +558,6 @@ main (int argc,
|
|||||||
{
|
{
|
||||||
const char *plugin_name;
|
const char *plugin_name;
|
||||||
char *config_filename;
|
char *config_filename;
|
||||||
char *testname;
|
|
||||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||||
|
|
||||||
(void) argc;
|
(void) argc;
|
||||||
@ -571,15 +571,17 @@ main (int argc,
|
|||||||
"WARNING",
|
"WARNING",
|
||||||
NULL);
|
NULL);
|
||||||
plugin_name++;
|
plugin_name++;
|
||||||
(void) GNUNET_asprintf (&testname,
|
{
|
||||||
"test-exchange-db-%s",
|
char *testname;
|
||||||
plugin_name);
|
|
||||||
(void) GNUNET_asprintf (&config_filename,
|
GNUNET_asprintf (&testname,
|
||||||
"%s.conf",
|
"test-exchange-db-%s",
|
||||||
testname);
|
plugin_name);
|
||||||
fprintf (stdout,
|
GNUNET_asprintf (&config_filename,
|
||||||
"Using config: %s\n",
|
"%s.conf",
|
||||||
config_filename);
|
testname);
|
||||||
|
GNUNET_free (testname);
|
||||||
|
}
|
||||||
cfg = GNUNET_CONFIGURATION_create ();
|
cfg = GNUNET_CONFIGURATION_create ();
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CONFIGURATION_parse (cfg,
|
GNUNET_CONFIGURATION_parse (cfg,
|
||||||
@ -587,16 +589,14 @@ main (int argc,
|
|||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
GNUNET_free (config_filename);
|
GNUNET_free (config_filename);
|
||||||
GNUNET_free (testname);
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
GNUNET_SCHEDULER_run (&run,
|
GNUNET_SCHEDULER_run (&run,
|
||||||
cfg);
|
cfg);
|
||||||
GNUNET_CONFIGURATION_destroy (cfg);
|
GNUNET_CONFIGURATION_destroy (cfg);
|
||||||
GNUNET_free (config_filename);
|
GNUNET_free (config_filename);
|
||||||
GNUNET_free (testname);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end of test_exchangedb_by_j.c */
|
/* end of perf_select_refunds_by_coin.c */
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2022 Taler Systems SA
|
Copyright (C) 2022, 2023 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
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
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -72,26 +72,16 @@ TEH_PG_aggregate (
|
|||||||
now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
|
now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
|
||||||
pg->aggregator_shift);
|
pg->aggregator_shift);
|
||||||
|
|
||||||
/* Used in #postgres_aggregate() */
|
/* Used in #postgres_aggregate() */
|
||||||
PREPARE (pg,
|
PREPARE (pg,
|
||||||
"aggregate",
|
"aggregate",
|
||||||
"WITH rdy AS (" /* find deposits ready by merchant */
|
"WITH dep AS (" /* restrict to our merchant and account and mark as done */
|
||||||
" SELECT"
|
|
||||||
" coin_pub"
|
|
||||||
" FROM deposits_for_matching"
|
|
||||||
" WHERE refund_deadline<$1" /* filter by shard, only actually executable deposits */
|
|
||||||
" AND merchant_pub=$2" /* filter by target merchant */
|
|
||||||
" ORDER BY refund_deadline ASC" /* ordering is not critical */
|
|
||||||
" LIMIT "
|
|
||||||
TALER_QUOTE (TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) /* limits transaction size */
|
|
||||||
" )"
|
|
||||||
" ,dep AS (" /* restrict to our merchant and account and mark as done */
|
|
||||||
" UPDATE deposits"
|
" UPDATE deposits"
|
||||||
" SET done=TRUE"
|
" SET done=TRUE"
|
||||||
" WHERE coin_pub IN (SELECT coin_pub FROM rdy)"
|
" WHERE NOT (done OR policy_blocked)" /* only actually executable deposits */
|
||||||
" AND merchant_pub=$2" /* theoretically, same coin could be spent at another merchant */
|
" AND refund_deadline<$1" /* filter by shard */
|
||||||
|
" AND merchant_pub=$2" /* filter by target merchant */
|
||||||
" AND wire_target_h_payto=$3" /* merchant could have a 2nd bank account */
|
" AND wire_target_h_payto=$3" /* merchant could have a 2nd bank account */
|
||||||
" AND done=FALSE" /* theoretically, same coin could be spend at the same merchant a 2nd time */
|
|
||||||
" RETURNING"
|
" RETURNING"
|
||||||
" deposit_serial_id"
|
" deposit_serial_id"
|
||||||
" ,coin_pub"
|
" ,coin_pub"
|
||||||
|
@ -1,914 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of TALER
|
|
||||||
Copyright (C) 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 as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @file exchangedb/pg_batch2_reserves_in_insert.c
|
|
||||||
* @brief Implementation of the reserves_in_insert function for Postgres
|
|
||||||
* @author Joseph Xu
|
|
||||||
*/
|
|
||||||
#include "platform.h"
|
|
||||||
#include "taler_error_codes.h"
|
|
||||||
#include "taler_dbevents.h"
|
|
||||||
#include "taler_pq_lib.h"
|
|
||||||
#include "pg_batch2_reserves_in_insert.h"
|
|
||||||
#include "pg_helper.h"
|
|
||||||
#include "pg_start.h"
|
|
||||||
#include "pg_rollback.h"
|
|
||||||
#include "pg_start_read_committed.h"
|
|
||||||
#include "pg_commit.h"
|
|
||||||
#include "pg_reserves_get.h"
|
|
||||||
#include "pg_reserves_update.h"
|
|
||||||
#include "pg_setup_wire_target.h"
|
|
||||||
#include "pg_event_notify.h"
|
|
||||||
#include "pg_preflight.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate event notification for the reserve change.
|
|
||||||
*
|
|
||||||
* @param reserve_pub reserve to notfiy on
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)
|
|
||||||
{
|
|
||||||
struct TALER_ReserveEventP rep = {
|
|
||||||
.header.size = htons (sizeof (rep)),
|
|
||||||
.header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING),
|
|
||||||
.reserve_pub = *reserve_pub
|
|
||||||
};
|
|
||||||
|
|
||||||
return GNUNET_PG_get_event_notify_channel (&rep.header);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static enum GNUNET_DB_QueryStatus
|
|
||||||
insert1(struct PostgresClosure *pg,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo reserves[1],
|
|
||||||
struct GNUNET_TIME_Timestamp expiry,
|
|
||||||
struct GNUNET_TIME_Timestamp gc,
|
|
||||||
struct TALER_PaytoHashP h_payto,
|
|
||||||
char *const * notify_s,
|
|
||||||
struct GNUNET_TIME_Timestamp reserve_expiration,
|
|
||||||
bool *transaction_duplicate,
|
|
||||||
bool *conflict,
|
|
||||||
uint64_t *reserve_uuid,
|
|
||||||
enum GNUNET_DB_QueryStatus results[1])
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus qs2;
|
|
||||||
PREPARE (pg,
|
|
||||||
"batch1_reserve_create",
|
|
||||||
"SELECT "
|
|
||||||
" out_reserve_found AS conflicted"
|
|
||||||
",transaction_duplicate"
|
|
||||||
",ruuid AS reserve_uuid"
|
|
||||||
" FROM exchange_do_batch_reserves_in_insert"
|
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
|
|
||||||
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&gc),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[0].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[0]),
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted",
|
|
||||||
&conflict[0]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate",
|
|
||||||
&transaction_duplicate[0]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
|
|
||||||
&reserve_uuid[0]),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
TALER_payto_hash (reserves[0].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
|
|
||||||
qs2 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
|
||||||
"batch1_reserve_create",
|
|
||||||
params,
|
|
||||||
rs);
|
|
||||||
|
|
||||||
if (qs2 < 0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserves 1(%d)\n",
|
|
||||||
qs2);
|
|
||||||
results[0] = qs2;
|
|
||||||
return qs2;
|
|
||||||
}
|
|
||||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs2);
|
|
||||||
if ((! conflict[0]) && transaction_duplicate[0])
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
TEH_PG_rollback (pg);
|
|
||||||
results[0] = GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
|
||||||
return qs2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static enum GNUNET_DB_QueryStatus
|
|
||||||
insert2 (struct PostgresClosure *pg,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo reserves[2],
|
|
||||||
struct GNUNET_TIME_Timestamp expiry,
|
|
||||||
struct GNUNET_TIME_Timestamp gc,
|
|
||||||
struct TALER_PaytoHashP h_payto,
|
|
||||||
char *const*notify_s,
|
|
||||||
struct GNUNET_TIME_Timestamp reserve_expiration,
|
|
||||||
bool *transaction_duplicate,
|
|
||||||
bool *conflict,
|
|
||||||
uint64_t *reserve_uuid,
|
|
||||||
enum GNUNET_DB_QueryStatus results[1])
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus qs1;
|
|
||||||
PREPARE (pg,
|
|
||||||
"batch2_reserve_create",
|
|
||||||
"SELECT "
|
|
||||||
"out_reserve_found AS conflicted"
|
|
||||||
",out_reserve_found2 AS conflicted2"
|
|
||||||
",transaction_duplicate"
|
|
||||||
",transaction_duplicate2"
|
|
||||||
",ruuid AS reserve_uuid"
|
|
||||||
",ruuid2 AS reserve_uuid2"
|
|
||||||
" FROM exchange_do_batch2_reserves_insert"
|
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22);");
|
|
||||||
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&gc),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[0].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[0]),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[1]),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[1].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[1].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[1].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted",
|
|
||||||
&conflict[0]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted2",
|
|
||||||
&conflict[1]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate",
|
|
||||||
&transaction_duplicate[0]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
|
|
||||||
&transaction_duplicate[1]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
|
|
||||||
&reserve_uuid[0]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
|
|
||||||
&reserve_uuid[1]),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
|
|
||||||
TALER_payto_hash (reserves[0].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserves[1].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
|
|
||||||
|
|
||||||
qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
|
||||||
"batch2_reserve_create",
|
|
||||||
params,
|
|
||||||
rs);
|
|
||||||
if (qs1 < 0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserves 2(%d)\n",
|
|
||||||
qs1);
|
|
||||||
results[0]=qs1;
|
|
||||||
return qs1;
|
|
||||||
}
|
|
||||||
|
|
||||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
|
|
||||||
/* results[i] = (transaction_duplicate)
|
|
||||||
? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
|
|
||||||
: GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/
|
|
||||||
|
|
||||||
if (
|
|
||||||
((! conflict[0]) && (transaction_duplicate[0]))
|
|
||||||
||((! conflict[1]) && (transaction_duplicate[1]))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
TEH_PG_rollback (pg); //ROLLBACK
|
|
||||||
results[0] = GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
|
||||||
return qs1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static enum GNUNET_DB_QueryStatus
|
|
||||||
insert4 (struct PostgresClosure *pg,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo reserves[4],
|
|
||||||
struct GNUNET_TIME_Timestamp expiry,
|
|
||||||
struct GNUNET_TIME_Timestamp gc,
|
|
||||||
struct TALER_PaytoHashP h_payto,
|
|
||||||
char *const*notify_s,
|
|
||||||
struct GNUNET_TIME_Timestamp reserve_expiration,
|
|
||||||
bool *transaction_duplicate,
|
|
||||||
bool *conflict,
|
|
||||||
uint64_t *reserve_uuid,
|
|
||||||
enum GNUNET_DB_QueryStatus results[1])
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus qs3;
|
|
||||||
PREPARE (pg,
|
|
||||||
"batch4_reserve_create",
|
|
||||||
"SELECT "
|
|
||||||
"out_reserve_found AS conflicted"
|
|
||||||
",out_reserve_found2 AS conflicted2"
|
|
||||||
",out_reserve_found3 AS conflicted3"
|
|
||||||
",out_reserve_found4 AS conflicted4"
|
|
||||||
",transaction_duplicate"
|
|
||||||
",transaction_duplicate2"
|
|
||||||
",transaction_duplicate3"
|
|
||||||
",transaction_duplicate4"
|
|
||||||
",ruuid AS reserve_uuid"
|
|
||||||
",ruuid2 AS reserve_uuid2"
|
|
||||||
",ruuid3 AS reserve_uuid3"
|
|
||||||
",ruuid4 AS reserve_uuid4"
|
|
||||||
" FROM exchange_do_batch4_reserves_insert"
|
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39, $40, $41,$42);");
|
|
||||||
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&gc),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[0].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[0]),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[1]),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[2]),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[3]),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[1].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[1].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[1].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[2].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[2].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[2].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[3].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[3].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[3].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted",
|
|
||||||
&conflict[0]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted2",
|
|
||||||
&conflict[1]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted3",
|
|
||||||
&conflict[2]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted4",
|
|
||||||
&conflict[3]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate",
|
|
||||||
&transaction_duplicate[0]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
|
|
||||||
&transaction_duplicate[1]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate3",
|
|
||||||
&transaction_duplicate[2]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate4",
|
|
||||||
&transaction_duplicate[3]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
|
|
||||||
&reserve_uuid[0]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
|
|
||||||
&reserve_uuid[1]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid3",
|
|
||||||
&reserve_uuid[2]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid4",
|
|
||||||
&reserve_uuid[3]),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
|
|
||||||
TALER_payto_hash (reserves[0].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserves[1].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserves[2].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserves[3].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
|
|
||||||
qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
|
||||||
"batch4_reserve_create",
|
|
||||||
params,
|
|
||||||
rs);
|
|
||||||
if (qs3 < 0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserves4 (%d)\n",
|
|
||||||
qs3);
|
|
||||||
results[0] = qs3;
|
|
||||||
return qs3;
|
|
||||||
}
|
|
||||||
|
|
||||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3);
|
|
||||||
|
|
||||||
if (
|
|
||||||
((! conflict[0]) && (transaction_duplicate[0]))
|
|
||||||
||((! conflict[1]) && (transaction_duplicate[1]))
|
|
||||||
||((! conflict[2]) && (transaction_duplicate[2]))
|
|
||||||
||((! conflict[3]) && (transaction_duplicate[3]))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
TEH_PG_rollback (pg);
|
|
||||||
results[0] = GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
|
||||||
return qs3;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static enum GNUNET_DB_QueryStatus
|
|
||||||
insert8 (struct PostgresClosure *pg,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo reserves[8],
|
|
||||||
struct GNUNET_TIME_Timestamp expiry,
|
|
||||||
struct GNUNET_TIME_Timestamp gc,
|
|
||||||
struct TALER_PaytoHashP h_payto,
|
|
||||||
char *const*notify_s,
|
|
||||||
struct GNUNET_TIME_Timestamp reserve_expiration,
|
|
||||||
bool *transaction_duplicate,
|
|
||||||
bool *conflict,
|
|
||||||
uint64_t *reserve_uuid,
|
|
||||||
enum GNUNET_DB_QueryStatus results[1])
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus qs3;
|
|
||||||
PREPARE (pg,
|
|
||||||
"batch8_reserve_create",
|
|
||||||
"SELECT "
|
|
||||||
"out_reserve_found AS conflicted"
|
|
||||||
",out_reserve_found2 AS conflicted2"
|
|
||||||
",out_reserve_found3 AS conflicted3"
|
|
||||||
",out_reserve_found4 AS conflicted4"
|
|
||||||
",out_reserve_found5 AS conflicted5"
|
|
||||||
",out_reserve_found6 AS conflicted6"
|
|
||||||
",out_reserve_found7 AS conflicted7"
|
|
||||||
",out_reserve_found8 AS conflicted8"
|
|
||||||
",transaction_duplicate"
|
|
||||||
",transaction_duplicate2"
|
|
||||||
",transaction_duplicate3"
|
|
||||||
",transaction_duplicate4"
|
|
||||||
",transaction_duplicate5"
|
|
||||||
",transaction_duplicate6"
|
|
||||||
",transaction_duplicate7"
|
|
||||||
",transaction_duplicate8"
|
|
||||||
",ruuid AS reserve_uuid"
|
|
||||||
",ruuid2 AS reserve_uuid2"
|
|
||||||
",ruuid3 AS reserve_uuid3"
|
|
||||||
",ruuid4 AS reserve_uuid4"
|
|
||||||
",ruuid5 AS reserve_uuid5"
|
|
||||||
",ruuid6 AS reserve_uuid6"
|
|
||||||
",ruuid7 AS reserve_uuid7"
|
|
||||||
",ruuid8 AS reserve_uuid8"
|
|
||||||
" FROM exchange_do_batch8_reserves_insert"
|
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39, $40, $41,$42,$43,$44,$45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$80,$81,$82);");
|
|
||||||
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&gc),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[0].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[0]),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[1]),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[2]),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[3]),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[4]),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[5]),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[6]),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[7]),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[1].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[1].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[1].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[2].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[2].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[2].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[3].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[3].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[3].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[4].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[4].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[4].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[4].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[4].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[4].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[5].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[5].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[5].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[5].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[5].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[5].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[6].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[6].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[6].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[6].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[6].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[6].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[7].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[7].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[7].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[7].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[7].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[7].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted",
|
|
||||||
&conflict[0]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted2",
|
|
||||||
&conflict[1]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted3",
|
|
||||||
&conflict[2]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted4",
|
|
||||||
&conflict[3]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted5",
|
|
||||||
&conflict[4]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted6",
|
|
||||||
&conflict[5]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted7",
|
|
||||||
&conflict[6]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted8",
|
|
||||||
&conflict[7]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate",
|
|
||||||
&transaction_duplicate[0]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
|
|
||||||
&transaction_duplicate[1]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate3",
|
|
||||||
&transaction_duplicate[2]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate4",
|
|
||||||
&transaction_duplicate[3]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate5",
|
|
||||||
&transaction_duplicate[4]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate6",
|
|
||||||
&transaction_duplicate[5]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate7",
|
|
||||||
&transaction_duplicate[6]),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate8",
|
|
||||||
&transaction_duplicate[7]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
|
|
||||||
&reserve_uuid[0]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
|
|
||||||
&reserve_uuid[1]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid3",
|
|
||||||
&reserve_uuid[2]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid4",
|
|
||||||
&reserve_uuid[3]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid5",
|
|
||||||
&reserve_uuid[4]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid6",
|
|
||||||
&reserve_uuid[5]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid7",
|
|
||||||
&reserve_uuid[6]),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid8",
|
|
||||||
&reserve_uuid[7]),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
|
|
||||||
TALER_payto_hash (reserves[0].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserves[1].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserves[2].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserves[3].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserves[4].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserves[5].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserves[6].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserves[7].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
|
|
||||||
qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
|
||||||
"batch8_reserve_create",
|
|
||||||
params,
|
|
||||||
rs);
|
|
||||||
if (qs3 < 0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserves8 (%d)\n",
|
|
||||||
qs3);
|
|
||||||
results[0]=qs3;
|
|
||||||
return qs3;
|
|
||||||
}
|
|
||||||
|
|
||||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3);
|
|
||||||
/* results[i] = (transaction_duplicate)
|
|
||||||
? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
|
|
||||||
: GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/
|
|
||||||
|
|
||||||
if (
|
|
||||||
((! conflict[0]) && (transaction_duplicate[0]))
|
|
||||||
||((! conflict[1]) && (transaction_duplicate[1]))
|
|
||||||
||((! conflict[2]) && (transaction_duplicate[2]))
|
|
||||||
||((! conflict[3]) && (transaction_duplicate[3]))
|
|
||||||
||((! conflict[4]) && (transaction_duplicate[4]))
|
|
||||||
||((! conflict[5]) && (transaction_duplicate[5]))
|
|
||||||
||((! conflict[6]) && (transaction_duplicate[6]))
|
|
||||||
||((! conflict[7]) && (transaction_duplicate[7]))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
TEH_PG_rollback (pg);
|
|
||||||
results[0]=GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
|
||||||
return qs3;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum GNUNET_DB_QueryStatus
|
|
||||||
TEH_PG_batch2_reserves_in_insert (void *cls,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
|
|
||||||
unsigned int reserves_length,
|
|
||||||
unsigned int batch_size,
|
|
||||||
enum GNUNET_DB_QueryStatus *results)
|
|
||||||
{
|
|
||||||
struct PostgresClosure *pg = cls;
|
|
||||||
enum GNUNET_DB_QueryStatus qs1;
|
|
||||||
enum GNUNET_DB_QueryStatus qs2;
|
|
||||||
enum GNUNET_DB_QueryStatus qs4;
|
|
||||||
enum GNUNET_DB_QueryStatus qs5;
|
|
||||||
struct GNUNET_TIME_Timestamp expiry;
|
|
||||||
struct GNUNET_TIME_Timestamp gc;
|
|
||||||
struct TALER_PaytoHashP h_payto;
|
|
||||||
uint64_t reserve_uuid[reserves_length];
|
|
||||||
bool transaction_duplicate[reserves_length];
|
|
||||||
bool need_update = false;
|
|
||||||
bool t_duplicate=false;
|
|
||||||
struct GNUNET_TIME_Timestamp reserve_expiration
|
|
||||||
= GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
|
|
||||||
bool conflicts[reserves_length];
|
|
||||||
char *notify_s[reserves_length];
|
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TEH_PG_preflight (pg))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
expiry = GNUNET_TIME_absolute_to_timestamp (
|
|
||||||
GNUNET_TIME_absolute_add (reserves->execution_time.abs_time,
|
|
||||||
pg->idle_reserve_expiration_time));
|
|
||||||
gc = GNUNET_TIME_absolute_to_timestamp (
|
|
||||||
GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
|
|
||||||
pg->legal_reserve_expiration_time));
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
|
||||||
"Creating reserve %s with expiration in %s\n",
|
|
||||||
TALER_B2S (&(reserves->reserve_pub)),
|
|
||||||
GNUNET_STRINGS_relative_time_to_string (
|
|
||||||
pg->idle_reserve_expiration_time,
|
|
||||||
GNUNET_NO));
|
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TEH_PG_start_read_committed(pg,
|
|
||||||
"READ_COMMITED"))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Optimistically assume this is a new reserve, create balance for the first
|
|
||||||
time; we do this before adding the actual transaction to "reserves_in",
|
|
||||||
as for a new reserve it can't be a duplicate 'add' operation, and as
|
|
||||||
the 'add' operation needs the reserve entry as a foreign key. */
|
|
||||||
for (unsigned int i=0;i<reserves_length;i++)
|
|
||||||
{
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
|
|
||||||
|
|
||||||
notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int i=0;
|
|
||||||
|
|
||||||
while (i < reserves_length)
|
|
||||||
{
|
|
||||||
unsigned int bs = GNUNET_MIN (batch_size,
|
|
||||||
reserves_length - i);
|
|
||||||
if (bs >= 8)
|
|
||||||
{
|
|
||||||
qs1=insert8(pg,
|
|
||||||
&reserves[i],
|
|
||||||
expiry,
|
|
||||||
gc,
|
|
||||||
h_payto,
|
|
||||||
¬ify_s[i],
|
|
||||||
reserve_expiration,
|
|
||||||
&transaction_duplicate[i],
|
|
||||||
&conflicts[i],
|
|
||||||
&reserve_uuid[i],
|
|
||||||
&results[i]);
|
|
||||||
|
|
||||||
if (qs1<0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserve batch_8 (%d)\n",
|
|
||||||
qs1);
|
|
||||||
return qs1;
|
|
||||||
}
|
|
||||||
need_update |= conflicts[i];
|
|
||||||
need_update |= conflicts[i+1];
|
|
||||||
need_update |= conflicts[i+2];
|
|
||||||
need_update |= conflicts[i+3];
|
|
||||||
need_update |= conflicts[i+4];
|
|
||||||
need_update |= conflicts[i+5];
|
|
||||||
need_update |= conflicts[i+6];
|
|
||||||
need_update |= conflicts[i+7];
|
|
||||||
t_duplicate |= transaction_duplicate[i];
|
|
||||||
t_duplicate |= transaction_duplicate[i+1];
|
|
||||||
t_duplicate |= transaction_duplicate[i+2];
|
|
||||||
t_duplicate |= transaction_duplicate[i+3];
|
|
||||||
t_duplicate |= transaction_duplicate[i+4];
|
|
||||||
t_duplicate |= transaction_duplicate[i+5];
|
|
||||||
t_duplicate |= transaction_duplicate[i+6];
|
|
||||||
t_duplicate |= transaction_duplicate[i+7];
|
|
||||||
i+=8;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (bs)
|
|
||||||
{
|
|
||||||
case 7:
|
|
||||||
case 6 :
|
|
||||||
case 5:
|
|
||||||
case 4 :
|
|
||||||
qs4=insert4(pg,
|
|
||||||
&reserves[i],
|
|
||||||
expiry,
|
|
||||||
gc,
|
|
||||||
h_payto,
|
|
||||||
¬ify_s[i],
|
|
||||||
reserve_expiration,
|
|
||||||
&transaction_duplicate[i],
|
|
||||||
&conflicts[i],
|
|
||||||
&reserve_uuid[i],
|
|
||||||
&results[i]);
|
|
||||||
|
|
||||||
if (qs4<0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserve batch_4 (%d)\n",
|
|
||||||
qs4);
|
|
||||||
return qs4;
|
|
||||||
}
|
|
||||||
need_update |= conflicts[i];
|
|
||||||
need_update |= conflicts[i+1];
|
|
||||||
need_update |= conflicts[i+2];
|
|
||||||
need_update |= conflicts[i+3];
|
|
||||||
t_duplicate |= transaction_duplicate[i];
|
|
||||||
t_duplicate |= transaction_duplicate[i+1];
|
|
||||||
t_duplicate |= transaction_duplicate[i+2];
|
|
||||||
t_duplicate |= transaction_duplicate[i+3];
|
|
||||||
// fprintf(stdout, "reserve_uuid : %ld %ld %ld %ld\n", reserve_uuid[i], reserve_uuid[i+1], reserve_uuid[i+2], reserve_uuid[i+3]);
|
|
||||||
i += 4;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
case 2:
|
|
||||||
qs5=insert2(pg,
|
|
||||||
&reserves[i],
|
|
||||||
expiry,
|
|
||||||
gc,
|
|
||||||
h_payto,
|
|
||||||
¬ify_s[i],
|
|
||||||
reserve_expiration,
|
|
||||||
&transaction_duplicate[i],
|
|
||||||
&conflicts[i],
|
|
||||||
&reserve_uuid[i],
|
|
||||||
&results[i]);
|
|
||||||
if (qs5<0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserve batch_2 (%d)\n",
|
|
||||||
qs5);
|
|
||||||
return qs5;
|
|
||||||
}
|
|
||||||
need_update |= conflicts[i];
|
|
||||||
need_update |= conflicts[i+1];
|
|
||||||
t_duplicate |= transaction_duplicate[i];
|
|
||||||
t_duplicate |= transaction_duplicate[i+1];
|
|
||||||
results[i] = (t_duplicate)
|
|
||||||
? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
|
|
||||||
: GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
|
||||||
// fprintf(stdout, "reserve_uuid : %ld %ld\n", reserve_uuid[i], reserve_uuid[i+1]);
|
|
||||||
i += 2;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
qs2 = insert1(pg,
|
|
||||||
&reserves[i],
|
|
||||||
expiry,
|
|
||||||
gc,
|
|
||||||
h_payto,
|
|
||||||
¬ify_s[i],
|
|
||||||
reserve_expiration,
|
|
||||||
&transaction_duplicate[i],
|
|
||||||
&conflicts[i],
|
|
||||||
&reserve_uuid[i],
|
|
||||||
&results[i]);
|
|
||||||
if (qs2<0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserve batch_1 (%d)\n)"
|
|
||||||
,qs2);
|
|
||||||
return qs2;
|
|
||||||
}
|
|
||||||
need_update |= conflicts[i];
|
|
||||||
t_duplicate |= transaction_duplicate[i];
|
|
||||||
// fprintf(stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], conflicts[i], transaction_duplicate[i]);
|
|
||||||
i += 1;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
GNUNET_assert (0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} /* end while */
|
|
||||||
// commit
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus cs;
|
|
||||||
|
|
||||||
cs = TEH_PG_commit (pg);
|
|
||||||
if (cs < 0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to commit\n");
|
|
||||||
return cs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (! need_update)
|
|
||||||
{
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
// begin serializable
|
|
||||||
{
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TEH_PG_start (pg,
|
|
||||||
"reserve-insert-continued"))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum GNUNET_DB_QueryStatus qs3;
|
|
||||||
PREPARE (pg,
|
|
||||||
"reserves_update",
|
|
||||||
"SELECT"
|
|
||||||
" out_duplicate AS duplicate "
|
|
||||||
"FROM exchange_do_batch_reserves_update"
|
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8);");
|
|
||||||
for (unsigned int i = 0; i<reserves_length; i++)
|
|
||||||
{
|
|
||||||
if (! conflicts[i])
|
|
||||||
continue;
|
|
||||||
{
|
|
||||||
bool duplicate;
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[i].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[i].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[i]),
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
|
||||||
GNUNET_PQ_result_spec_bool ("duplicate",
|
|
||||||
&duplicate),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
|
||||||
"reserves_update",
|
|
||||||
params,
|
|
||||||
rs);
|
|
||||||
if (qs3<0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to update reserves (%d)\n",
|
|
||||||
qs3);
|
|
||||||
results[i] = qs3;
|
|
||||||
return qs3;
|
|
||||||
}
|
|
||||||
results[i] = duplicate
|
|
||||||
? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
|
|
||||||
: GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus cs;
|
|
||||||
|
|
||||||
cs = TEH_PG_commit (pg);
|
|
||||||
if (cs < 0)
|
|
||||||
return cs;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
for (unsigned int i = 0; i<reserves_length; i++)
|
|
||||||
GNUNET_free (notify_s[i]);
|
|
||||||
|
|
||||||
return reserves_length;
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of TALER
|
|
||||||
Copyright (C) 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 as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @file exchangedb/pg_batch2_reserves_in_insert.h
|
|
||||||
* @brief implementation of the batch2_reserves_in_insert function for Postgres
|
|
||||||
* @author Joseph XU
|
|
||||||
*/
|
|
||||||
#ifndef PG_BATCH2_RESERVES_IN_INSERT_H
|
|
||||||
#define PG_BATCH2_RESERVES_IN_INSERT_H
|
|
||||||
|
|
||||||
#include "taler_util.h"
|
|
||||||
#include "taler_json_lib.h"
|
|
||||||
#include "taler_exchangedb_plugin.h"
|
|
||||||
enum GNUNET_DB_QueryStatus
|
|
||||||
TEH_PG_batch2_reserves_in_insert (void *cls,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
|
|
||||||
unsigned int reserves_length,
|
|
||||||
unsigned int batch_size,
|
|
||||||
enum GNUNET_DB_QueryStatus *results);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,595 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
This file is part of TALER
|
|
||||||
Copyright (C) 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 as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @file exchangedb/pg_batch_reserves_in_insert.c
|
|
||||||
* @brief Implementation of the reserves_in_insert function for Postgres
|
|
||||||
* @author Joseph Xu
|
|
||||||
*/
|
|
||||||
#include "platform.h"
|
|
||||||
#include "taler_error_codes.h"
|
|
||||||
#include "taler_dbevents.h"
|
|
||||||
#include "taler_pq_lib.h"
|
|
||||||
#include "pg_batch_reserves_in_insert.h"
|
|
||||||
#include "pg_helper.h"
|
|
||||||
#include "pg_start.h"
|
|
||||||
#include "pg_rollback.h"
|
|
||||||
#include "pg_start_read_committed.h"
|
|
||||||
#include "pg_commit.h"
|
|
||||||
#include "pg_reserves_get.h"
|
|
||||||
#include "pg_reserves_update.h"
|
|
||||||
#include "pg_setup_wire_target.h"
|
|
||||||
#include "pg_event_notify.h"
|
|
||||||
#include "pg_preflight.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate event notification for the reserve change.
|
|
||||||
*
|
|
||||||
* @param reserve_pub reserve to notfiy on
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)
|
|
||||||
{
|
|
||||||
struct TALER_ReserveEventP rep = {
|
|
||||||
.header.size = htons (sizeof (rep)),
|
|
||||||
.header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING),
|
|
||||||
.reserve_pub = *reserve_pub
|
|
||||||
};
|
|
||||||
|
|
||||||
return GNUNET_PG_get_event_notify_channel (&rep.header);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static enum GNUNET_DB_QueryStatus
|
|
||||||
insert1(struct PostgresClosure *pg,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserve,
|
|
||||||
struct GNUNET_TIME_Timestamp expiry,
|
|
||||||
struct GNUNET_TIME_Timestamp gc,
|
|
||||||
struct TALER_PaytoHashP h_payto,
|
|
||||||
const char *notify_s,
|
|
||||||
struct GNUNET_TIME_Timestamp reserve_expiration,
|
|
||||||
bool *transaction_duplicate,
|
|
||||||
bool *conflict,
|
|
||||||
uint64_t *reserve_uuid)
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus qs2;
|
|
||||||
PREPARE (pg,
|
|
||||||
"reserve_creates",
|
|
||||||
"SELECT "
|
|
||||||
"out_reserve_found AS conflicted"
|
|
||||||
",transaction_duplicate"
|
|
||||||
",ruuid AS reserve_uuid"
|
|
||||||
" FROM exchange_do_batch_reserves_in_insert"
|
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
|
|
||||||
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&gc),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (&reserve->balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserve->exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve->execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserve->sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s),
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted",
|
|
||||||
conflict),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate",
|
|
||||||
transaction_duplicate),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
|
|
||||||
reserve_uuid),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
|
|
||||||
TALER_payto_hash (reserve->sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
|
|
||||||
/* Note: query uses 'on conflict do nothing' */
|
|
||||||
qs2 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
|
||||||
"reserve_creates",
|
|
||||||
params,
|
|
||||||
rs);
|
|
||||||
|
|
||||||
if (qs2 < 0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserves (%d)\n",
|
|
||||||
qs2);
|
|
||||||
return qs2;
|
|
||||||
}
|
|
||||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs2);
|
|
||||||
|
|
||||||
if ((*conflict) && (*transaction_duplicate))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
TEH_PG_rollback (pg);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
return qs2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static enum GNUNET_DB_QueryStatus
|
|
||||||
insert2 (struct PostgresClosure *pg,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserve0,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserve1,
|
|
||||||
struct GNUNET_TIME_Timestamp expiry,
|
|
||||||
struct GNUNET_TIME_Timestamp gc,
|
|
||||||
struct TALER_PaytoHashP h_payto,
|
|
||||||
const char *notify_s,
|
|
||||||
struct GNUNET_TIME_Timestamp reserve_expiration,
|
|
||||||
bool *transaction_duplicate,
|
|
||||||
bool *transaction_duplicate2,
|
|
||||||
bool *conflict,
|
|
||||||
bool *conflict2,
|
|
||||||
uint64_t *reserve_uuid,
|
|
||||||
uint64_t *reserve_uuid2)
|
|
||||||
{
|
|
||||||
PREPARE (pg,
|
|
||||||
"reserve_create",
|
|
||||||
"SELECT "
|
|
||||||
"out_reserve_found AS conflicted"
|
|
||||||
",out_reserve_found2 AS conflicted2"
|
|
||||||
",transaction_duplicate"
|
|
||||||
",transaction_duplicate2"
|
|
||||||
",ruuid AS reserve_uuid"
|
|
||||||
",ruuid2 AS reserve_uuid2"
|
|
||||||
" FROM exchange_do_batch2_reserves_insert"
|
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21);");
|
|
||||||
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&reserve0->reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&gc),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserve0->wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (&reserve0->balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserve0->exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve0->execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserve0->sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&reserve1->reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserve1->wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (&reserve1->balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserve1->exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve1->execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserve1->sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted",
|
|
||||||
conflict),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted2",
|
|
||||||
conflict2),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate",
|
|
||||||
transaction_duplicate),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
|
|
||||||
transaction_duplicate2),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
|
|
||||||
reserve_uuid),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
|
|
||||||
reserve_uuid2),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
|
|
||||||
TALER_payto_hash (reserve0->sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserve1->sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
|
|
||||||
|
|
||||||
qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
|
||||||
"reserve_create",
|
|
||||||
params,
|
|
||||||
rs);
|
|
||||||
if (qs1 < 0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserves (%d)\n",
|
|
||||||
qs1);
|
|
||||||
return qs1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
|
|
||||||
results[i] = (transaction_duplicate)
|
|
||||||
? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
|
|
||||||
: GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/
|
|
||||||
|
|
||||||
if ((*conflict) && (*transaction_duplicate) ||((*conflict2) && (*transaction_duplicate2)))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
TEH_PG_rollback (pg);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static enum GNUNET_DB_QueryStatus
|
|
||||||
insert4 (struct PostgresClosure *pg,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserve0,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserve1,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserve2,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserve3,
|
|
||||||
struct GNUNET_TIME_Timestamp expiry,
|
|
||||||
struct GNUNET_TIME_Timestamp gc,
|
|
||||||
struct TALER_PaytoHashP h_payto,
|
|
||||||
const char *notify_s,
|
|
||||||
struct GNUNET_TIME_Timestamp reserve_expiration,
|
|
||||||
bool *transaction_duplicate,
|
|
||||||
bool *transaction_duplicate2,
|
|
||||||
bool *transaction_duplicate3,
|
|
||||||
bool *transaction_duplicate4,
|
|
||||||
bool *conflict,
|
|
||||||
bool *conflict2,
|
|
||||||
bool *conflict3,
|
|
||||||
bool *conflict4,
|
|
||||||
uint64_t *reserve_uuid,
|
|
||||||
uint64_t *reserve_uuid2,
|
|
||||||
uint64_t *reserve_uuid3,
|
|
||||||
uint64_t *reserve_uuid4)
|
|
||||||
{
|
|
||||||
PREPARE (pg,
|
|
||||||
"reserve_create",
|
|
||||||
"SELECT "
|
|
||||||
"out_reserve_found AS conflicted"
|
|
||||||
",out_reserve_found2 AS conflicted2"
|
|
||||||
",out_reserve_found3 AS conflicted3"
|
|
||||||
",out_reserve_found4 AS conflicted4"
|
|
||||||
",transaction_duplicate"
|
|
||||||
",transaction_duplicate2"
|
|
||||||
",transaction_duplicate3"
|
|
||||||
",transaction_duplicate4"
|
|
||||||
",ruuid AS reserve_uuid"
|
|
||||||
",ruuid2 AS reserve_uuid2"
|
|
||||||
",ruuid3 AS reserve_uuid3"
|
|
||||||
",ruuid4 AS reserve_uuid4"
|
|
||||||
" FROM exchange_do_batch4_reserves_insert"
|
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39);");
|
|
||||||
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&reserve0->reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&gc),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserve0->wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (&reserve0->balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserve0->exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve0->execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserve0->sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&reserve1->reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserve1->wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (&reserve1->balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserve1->exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve1->execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserve1->sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&reserve2->reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&gc),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserve2->wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (&reserve2->balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserve2->exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve2->execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserve2->sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&reserve3->reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&gc),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserve3->wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (&reserve3->balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserve3->exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve3->execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserve3->sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration)
|
|
||||||
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted",
|
|
||||||
conflict),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted2",
|
|
||||||
conflict2),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted3",
|
|
||||||
conflict3),
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted4",
|
|
||||||
conflict4),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate",
|
|
||||||
transaction_duplicate),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
|
|
||||||
transaction_duplicate2),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate3",
|
|
||||||
transaction_duplicate3),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate4",
|
|
||||||
transaction_duplicate4),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
|
|
||||||
reserve_uuid),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
|
|
||||||
reserve_uuid2),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid3",
|
|
||||||
reserve_uuid3),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid4",
|
|
||||||
reserve_uuid4),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
|
|
||||||
TALER_payto_hash (reserve0->sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
TALER_payto_hash (reserve1->sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
|
|
||||||
|
|
||||||
qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
|
||||||
"reserve_create",
|
|
||||||
params,
|
|
||||||
rs);
|
|
||||||
if (qs1 < 0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserves (%d)\n",
|
|
||||||
qs1);
|
|
||||||
return qs1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
|
|
||||||
results[i] = (transaction_duplicate)
|
|
||||||
? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
|
|
||||||
: GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/
|
|
||||||
|
|
||||||
if ((*conflict) && (*transaction_duplicate) ||((*conflict2) && (*transaction_duplicate2)))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
TEH_PG_rollback (pg);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum GNUNET_DB_QueryStatus
|
|
||||||
TEH_PG_batch2_reserves_in_insert (void *cls,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
|
|
||||||
unsigned int reserves_length,
|
|
||||||
enum GNUNET_DB_QueryStatus *results)
|
|
||||||
{
|
|
||||||
struct PostgresClosure *pg = cls;
|
|
||||||
enum GNUNET_DB_QueryStatus qs1;
|
|
||||||
enum GNUNET_DB_QueryStatus qs2;
|
|
||||||
enum GNUNET_DB_QueryStatus qs4;
|
|
||||||
enum GNUNET_DB_QueryStatus qs5;
|
|
||||||
struct GNUNET_TIME_Timestamp expiry;
|
|
||||||
struct GNUNET_TIME_Timestamp gc;
|
|
||||||
struct TALER_PaytoHashP h_payto;
|
|
||||||
uint64_t reserve_uuid[reserves_length];
|
|
||||||
bool conflicted;
|
|
||||||
bool conflicted2;
|
|
||||||
bool transaction_duplicate[reserves_length];
|
|
||||||
bool need_update = false;
|
|
||||||
bool need_update2 = false;
|
|
||||||
struct GNUNET_TIME_Timestamp reserve_expiration
|
|
||||||
= GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
|
|
||||||
bool conflicts[reserves_length];
|
|
||||||
char *notify_s[reserves_length];
|
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TEH_PG_preflight (pg))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
expiry = GNUNET_TIME_absolute_to_timestamp (
|
|
||||||
GNUNET_TIME_absolute_add (reserves->execution_time.abs_time,
|
|
||||||
pg->idle_reserve_expiration_time));
|
|
||||||
gc = GNUNET_TIME_absolute_to_timestamp (
|
|
||||||
GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
|
|
||||||
pg->legal_reserve_expiration_time));
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
|
||||||
"Creating reserve %s with expiration in %s\n",
|
|
||||||
TALER_B2S (&(reserves->reserve_pub)),
|
|
||||||
GNUNET_STRINGS_relative_time_to_string (
|
|
||||||
pg->idle_reserve_expiration_time,
|
|
||||||
GNUNET_NO));
|
|
||||||
|
|
||||||
{
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TEH_PG_start_read_committed(pg,
|
|
||||||
"READ_COMMITED"))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Optimistically assume this is a new reserve, create balance for the first
|
|
||||||
time; we do this before adding the actual transaction to "reserves_in",
|
|
||||||
as for a new reserve it can't be a duplicate 'add' operation, and as
|
|
||||||
the 'add' operation needs the reserve entry as a foreign key. */
|
|
||||||
for (unsigned int i=0;i<reserves_length;i++)
|
|
||||||
{
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
|
|
||||||
notify_s[i] = compute_notify_on_reserve (&reserve->reserve_pub);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int i=0;
|
|
||||||
|
|
||||||
while (i < reserves_length)
|
|
||||||
{
|
|
||||||
if (reserves_length - i >= 4)
|
|
||||||
{
|
|
||||||
qs4=insert4(pg,
|
|
||||||
&reserves[i],
|
|
||||||
&reserves[i+2],
|
|
||||||
&reserves[i+3],
|
|
||||||
&reserves[i+4],
|
|
||||||
expiry,
|
|
||||||
gc,
|
|
||||||
h_payto,
|
|
||||||
¬ify_s[i],
|
|
||||||
reserve_expiration,
|
|
||||||
&transaction_duplicate[i],
|
|
||||||
&transaction_duplicate[i+1],
|
|
||||||
&transaction_duplicate[i+2],
|
|
||||||
&transaction_duplicate[i+3],
|
|
||||||
&conflicts[i],
|
|
||||||
&conflicts[i+1],
|
|
||||||
&conflicts[i+2],
|
|
||||||
&conflicts[i+3],
|
|
||||||
&reserve_uuid[i],
|
|
||||||
&reserve_uuid[i+1],
|
|
||||||
&reserve_uuid[i+2],
|
|
||||||
&reserve_uuid[i+3]);
|
|
||||||
|
|
||||||
need_update |= conflicts[i];
|
|
||||||
need_update |= conflicts[i+1];
|
|
||||||
need_update |= conflicts[i+2];
|
|
||||||
need_update |= conflicts[i+3];
|
|
||||||
i += 4;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (reserves_length - i)
|
|
||||||
{
|
|
||||||
case 3:
|
|
||||||
case 2:
|
|
||||||
qs5=insert2(pg,
|
|
||||||
&reserves[i],
|
|
||||||
&reserves[i+1],
|
|
||||||
expiry,
|
|
||||||
gc,
|
|
||||||
h_payto,
|
|
||||||
notify_s[i],
|
|
||||||
reserve_expiration,
|
|
||||||
&transaction_duplicate[i],
|
|
||||||
&transaction_duplicate[i+1],
|
|
||||||
&conflicts[i],
|
|
||||||
&conflicts[i+1],
|
|
||||||
&reserve_uuid[i],
|
|
||||||
&reserve_uuid[i+1]);
|
|
||||||
need_update |= conflicts[i];
|
|
||||||
need_update |= conflicts[i+1];
|
|
||||||
i += 2;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
qs2 = insert1(pg,
|
|
||||||
&reserves[i],
|
|
||||||
expiry,
|
|
||||||
gc,
|
|
||||||
h_payto,
|
|
||||||
notify_s[i],
|
|
||||||
reserve_expiration,
|
|
||||||
&transaction_duplicate[i],
|
|
||||||
&conflicts[i],
|
|
||||||
&reserve_uuid[i]);
|
|
||||||
need_update |= conflicts[i];
|
|
||||||
i += 1;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
GNUNET_assert (0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} /* end while */
|
|
||||||
// commit
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus cs;
|
|
||||||
|
|
||||||
cs = TEH_PG_commit (pg);
|
|
||||||
if (cs < 0)
|
|
||||||
return cs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!need_update )
|
|
||||||
goto exit;
|
|
||||||
// begin serializable
|
|
||||||
{
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TEH_PG_start(pg,
|
|
||||||
"reserve-insert-continued"))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum GNUNET_DB_QueryStatus qs3;
|
|
||||||
PREPARE (pg,
|
|
||||||
"reserves_in_add_transaction",
|
|
||||||
"CALL exchange_do_batch_reserves_update"
|
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
|
|
||||||
for (unsigned int i=0;i<reserves_length;i++)
|
|
||||||
{
|
|
||||||
if (! conflicts[i])
|
|
||||||
continue;
|
|
||||||
{
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (&reserve->balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserve->exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_bool (conflicted),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[i]),
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
|
|
||||||
qs3 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
|
|
||||||
"reserves_in_add_transaction",
|
|
||||||
params);
|
|
||||||
if (qs3<0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to update reserves (%d)\n",
|
|
||||||
qs3);
|
|
||||||
return qs3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus cs;
|
|
||||||
|
|
||||||
cs = TEH_PG_commit (pg);
|
|
||||||
if (cs < 0)
|
|
||||||
return cs;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
for (unsigned int i=0;i<reserves_length;i++)
|
|
||||||
GNUNET_free (notify_s[i]);
|
|
||||||
|
|
||||||
return reserves_length;
|
|
||||||
}
|
|
@ -1,252 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of TALER
|
|
||||||
Copyright (C) 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 as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @file exchangedb/pg_batch_reserves_in_insert.c
|
|
||||||
* @brief Implementation of the reserves_in_insert function for Postgres
|
|
||||||
* @author Joseph Xu
|
|
||||||
*/
|
|
||||||
#include "platform.h"
|
|
||||||
#include "taler_error_codes.h"
|
|
||||||
#include "taler_dbevents.h"
|
|
||||||
#include "taler_pq_lib.h"
|
|
||||||
#include "pg_batch_reserves_in_insert.h"
|
|
||||||
#include "pg_helper.h"
|
|
||||||
#include "pg_start.h"
|
|
||||||
#include "pg_rollback.h"
|
|
||||||
#include "pg_start_read_committed.h"
|
|
||||||
#include "pg_commit.h"
|
|
||||||
#include "pg_reserves_get.h"
|
|
||||||
#include "pg_reserves_update.h"
|
|
||||||
#include "pg_setup_wire_target.h"
|
|
||||||
#include "pg_event_notify.h"
|
|
||||||
#include "pg_preflight.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate event notification for the reserve change.
|
|
||||||
*
|
|
||||||
* @param reserve_pub reserve to notfiy on
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)
|
|
||||||
{
|
|
||||||
struct TALER_ReserveEventP rep = {
|
|
||||||
.header.size = htons (sizeof (rep)),
|
|
||||||
.header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING),
|
|
||||||
.reserve_pub = *reserve_pub
|
|
||||||
};
|
|
||||||
|
|
||||||
return GNUNET_PG_get_event_notify_channel (&rep.header);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
enum GNUNET_DB_QueryStatus
|
|
||||||
TEH_PG_batch_reserves_in_insert (
|
|
||||||
void *cls,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
|
|
||||||
unsigned int reserves_length,
|
|
||||||
enum GNUNET_DB_QueryStatus *results)
|
|
||||||
{
|
|
||||||
struct PostgresClosure *pg = cls;
|
|
||||||
enum GNUNET_DB_QueryStatus qs1;
|
|
||||||
struct GNUNET_TIME_Timestamp expiry;
|
|
||||||
struct GNUNET_TIME_Timestamp gc;
|
|
||||||
struct TALER_PaytoHashP h_payto;
|
|
||||||
uint64_t reserve_uuid;
|
|
||||||
struct GNUNET_TIME_Timestamp reserve_expiration
|
|
||||||
= GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
|
|
||||||
bool conflicts[reserves_length];
|
|
||||||
char *notify_s[reserves_length];
|
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TEH_PG_preflight (pg))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
PREPARE (pg,
|
|
||||||
"reserve_create",
|
|
||||||
"SELECT "
|
|
||||||
"out_reserve_found AS conflicted"
|
|
||||||
",transaction_duplicate"
|
|
||||||
",ruuid AS reserve_uuid"
|
|
||||||
" FROM exchange_do_batch_reserves_in_insert"
|
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
|
|
||||||
expiry = GNUNET_TIME_absolute_to_timestamp (
|
|
||||||
GNUNET_TIME_absolute_add (reserves->execution_time.abs_time,
|
|
||||||
pg->idle_reserve_expiration_time));
|
|
||||||
gc = GNUNET_TIME_absolute_to_timestamp (
|
|
||||||
GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
|
|
||||||
pg->legal_reserve_expiration_time));
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
|
||||||
"Creating reserve %s with expiration in %s\n",
|
|
||||||
TALER_B2S (reserves->reserve_pub),
|
|
||||||
GNUNET_STRINGS_relative_time_to_string (
|
|
||||||
pg->idle_reserve_expiration_time,
|
|
||||||
GNUNET_NO));
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TEH_PG_start_read_committed (pg,
|
|
||||||
"READ_COMMITED"))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
/* Optimistically assume this is a new reserve, create balance for the first
|
|
||||||
time; we do this before adding the actual transaction to "reserves_in",
|
|
||||||
as for a new reserve it can't be a duplicate 'add' operation, and as
|
|
||||||
the 'add' operation needs the reserve entry as a foreign key. */
|
|
||||||
for (unsigned int i = 0; i<reserves_length; i++)
|
|
||||||
{
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
|
|
||||||
notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub);
|
|
||||||
}
|
|
||||||
bool need_update = false;
|
|
||||||
for (unsigned int i = 0; i<reserves_length; i++)
|
|
||||||
{
|
|
||||||
bool conflicted;
|
|
||||||
bool transaction_duplicate;
|
|
||||||
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&gc),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[i].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[i].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserves[i].execution_time),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[i].sender_account_details),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&reserve_expiration),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[i]),
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
|
||||||
GNUNET_PQ_result_spec_bool ("conflicted",
|
|
||||||
&conflicted),
|
|
||||||
GNUNET_PQ_result_spec_bool ("transaction_duplicate",
|
|
||||||
&transaction_duplicate),
|
|
||||||
GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
|
|
||||||
&reserve_uuid),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
|
|
||||||
TALER_payto_hash (reserves[i].sender_account_details,
|
|
||||||
&h_payto);
|
|
||||||
/* Note: query uses 'on conflict do nothing' */
|
|
||||||
qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
|
||||||
"reserve_create",
|
|
||||||
params,
|
|
||||||
rs);
|
|
||||||
if (qs1 < 0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to create reserves (%d)\n",
|
|
||||||
qs1);
|
|
||||||
results[i] = qs1;
|
|
||||||
return qs1;
|
|
||||||
}
|
|
||||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
|
|
||||||
conflicts[i] = conflicted;
|
|
||||||
// fprintf(stdout, "%d", conflicts[i]);
|
|
||||||
if (conflicts[i] && transaction_duplicate)
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
results[i] = GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
TEH_PG_rollback (pg);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
results[i] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
|
||||||
need_update |= conflicted;
|
|
||||||
}
|
|
||||||
// commit
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus cs;
|
|
||||||
|
|
||||||
cs = TEH_PG_commit (pg);
|
|
||||||
if (cs < 0)
|
|
||||||
return cs;
|
|
||||||
}
|
|
||||||
if (! need_update)
|
|
||||||
goto exit;
|
|
||||||
// begin serializable
|
|
||||||
{
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TEH_PG_start (pg,
|
|
||||||
"reserve-insert-continued"))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum GNUNET_DB_QueryStatus qs2;
|
|
||||||
PREPARE (pg,
|
|
||||||
"reserves_in_add_transaction",
|
|
||||||
"SELECT"
|
|
||||||
" out_duplicate AS duplicate"
|
|
||||||
" FROM exchange_do_batch_reserves_update"
|
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8);");
|
|
||||||
for (unsigned int i = 0; i<reserves_length; i++)
|
|
||||||
{
|
|
||||||
if (! conflicts[i])
|
|
||||||
continue;
|
|
||||||
{
|
|
||||||
bool duplicate;
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&expiry),
|
|
||||||
GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference),
|
|
||||||
TALER_PQ_query_param_amount (reserves[i].balance),
|
|
||||||
GNUNET_PQ_query_param_string (reserves[i].exchange_account_name),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (&h_payto),
|
|
||||||
GNUNET_PQ_query_param_string (notify_s[i]),
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
|
||||||
GNUNET_PQ_result_spec_bool ("duplicate",
|
|
||||||
&duplicate),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
qs2 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
|
||||||
"reserves_in_add_transaction",
|
|
||||||
params,
|
|
||||||
rs);
|
|
||||||
if (qs2 < 0)
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"Failed to update reserves (%d)\n",
|
|
||||||
qs2);
|
|
||||||
results[i] = qs2;
|
|
||||||
return qs2;
|
|
||||||
}
|
|
||||||
results[i] = duplicate
|
|
||||||
? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
|
|
||||||
: GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
enum GNUNET_DB_QueryStatus cs;
|
|
||||||
|
|
||||||
cs = TEH_PG_commit (pg);
|
|
||||||
if (cs < 0)
|
|
||||||
return cs;
|
|
||||||
}
|
|
||||||
exit:
|
|
||||||
for (unsigned int i = 0; i<reserves_length; i++)
|
|
||||||
GNUNET_free (notify_s[i]);
|
|
||||||
|
|
||||||
return reserves_length;
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of TALER
|
|
||||||
Copyright (C) 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 as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @file exchangedb/pg_batch_reserves_in_insert.h
|
|
||||||
* @brief implementation of the batch_reserves_in_insert function for Postgres
|
|
||||||
* @author Christian Grothoff
|
|
||||||
*/
|
|
||||||
#ifndef PG_BATCH_RESERVES_IN_INSERT_H
|
|
||||||
#define PG_BATCH_RESERVES_IN_INSERT_H
|
|
||||||
|
|
||||||
#include "taler_util.h"
|
|
||||||
#include "taler_json_lib.h"
|
|
||||||
#include "taler_exchangedb_plugin.h"
|
|
||||||
|
|
||||||
|
|
||||||
enum GNUNET_DB_QueryStatus
|
|
||||||
TEH_PG_batch_reserves_in_insert (void *cls,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
|
|
||||||
unsigned int reserves_length,
|
|
||||||
enum GNUNET_DB_QueryStatus *results);
|
|
||||||
|
|
||||||
#endif
|
|
@ -55,7 +55,7 @@ struct LinkDataContext
|
|||||||
/**
|
/**
|
||||||
* Status, set to #GNUNET_SYSERR on errors,
|
* Status, set to #GNUNET_SYSERR on errors,
|
||||||
*/
|
*/
|
||||||
int status;
|
enum GNUNET_GenericReturnValue status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -190,20 +190,18 @@ TEH_PG_get_link_data (void *cls,
|
|||||||
"%d%c",
|
"%d%c",
|
||||||
&percent_refund,
|
&percent_refund,
|
||||||
&dummy)) )
|
&dummy)) )
|
||||||
{
|
{
|
||||||
if (NULL != mode)
|
if (NULL != mode)
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Bad mode `%s' specified\n",
|
"Bad mode `%s' specified\n",
|
||||||
mode);
|
mode);
|
||||||
}
|
percent_refund = 0;
|
||||||
if (NULL==mode)
|
}
|
||||||
percent_refund=0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (percent_refund)
|
switch (percent_refund)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
query="get_link";
|
query = "get_link";
|
||||||
PREPARE (pg,
|
PREPARE (pg,
|
||||||
query,
|
query,
|
||||||
"SELECT "
|
"SELECT "
|
||||||
@ -225,7 +223,7 @@ TEH_PG_get_link_data (void *cls,
|
|||||||
" ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
|
" ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
query="get_link_v1";
|
query = "get_link_v1";
|
||||||
PREPARE (pg,
|
PREPARE (pg,
|
||||||
query,
|
query,
|
||||||
"WITH rc AS MATERIALIZED ("
|
"WITH rc AS MATERIALIZED ("
|
||||||
@ -252,7 +250,7 @@ TEH_PG_get_link_data (void *cls,
|
|||||||
" ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
|
" ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
query="get_link_v2";
|
query = "get_link_v2";
|
||||||
PREPARE (pg,
|
PREPARE (pg,
|
||||||
query,
|
query,
|
||||||
"SELECT"
|
"SELECT"
|
||||||
@ -300,5 +298,3 @@ TEH_PG_get_link_data (void *cls,
|
|||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
return qs;
|
return qs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2022 Taler Systems SA
|
Copyright (C) 2022, 2023 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
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
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -33,15 +33,16 @@ TEH_PG_get_ready_deposit (void *cls,
|
|||||||
struct TALER_MerchantPublicKeyP *merchant_pub,
|
struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
char **payto_uri)
|
char **payto_uri)
|
||||||
{
|
{
|
||||||
|
static int choose_mode = -2;
|
||||||
struct PostgresClosure *pg = cls;
|
struct PostgresClosure *pg = cls;
|
||||||
struct GNUNET_TIME_Absolute now = {0};
|
struct GNUNET_TIME_Absolute now
|
||||||
|
= GNUNET_TIME_absolute_get ();
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
GNUNET_PQ_query_param_absolute_time (&now),
|
GNUNET_PQ_query_param_absolute_time (&now),
|
||||||
GNUNET_PQ_query_param_uint64 (&start_shard_row),
|
GNUNET_PQ_query_param_uint64 (&start_shard_row),
|
||||||
GNUNET_PQ_query_param_uint64 (&end_shard_row),
|
GNUNET_PQ_query_param_uint64 (&end_shard_row),
|
||||||
GNUNET_PQ_query_param_end
|
GNUNET_PQ_query_param_end
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||||
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
|
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
|
||||||
merchant_pub),
|
merchant_pub),
|
||||||
@ -49,181 +50,70 @@ TEH_PG_get_ready_deposit (void *cls,
|
|||||||
payto_uri),
|
payto_uri),
|
||||||
GNUNET_PQ_result_spec_end
|
GNUNET_PQ_result_spec_end
|
||||||
};
|
};
|
||||||
|
|
||||||
now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
|
|
||||||
pg->aggregator_shift);
|
|
||||||
GNUNET_assert (start_shard_row < end_shard_row);
|
|
||||||
GNUNET_assert (end_shard_row <= INT32_MAX);
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Finding ready deposits by deadline %s (%llu)\n",
|
|
||||||
GNUNET_TIME_absolute2s (now),
|
|
||||||
(unsigned long long) now.abs_value_us);
|
|
||||||
int choose_mode =-2;
|
|
||||||
const char *query;
|
const char *query;
|
||||||
|
|
||||||
if (-2 == choose_mode)
|
if (-2 == choose_mode)
|
||||||
{
|
{
|
||||||
const char *mode = getenv ("NEW_LOGIC");
|
const char *mode = getenv ("TALER_POSTGRES_GET_READY_LOGIC");
|
||||||
char dummy;
|
char dummy;
|
||||||
|
|
||||||
if ( (NULL==mode) ||
|
if ( (NULL==mode) ||
|
||||||
(1 != sscanf (mode,
|
(1 != sscanf (mode,
|
||||||
"%d%c",
|
"%d%c",
|
||||||
&choose_mode,
|
&choose_mode,
|
||||||
&dummy)) )
|
&dummy)) )
|
||||||
{
|
{
|
||||||
if (NULL != mode)
|
if (NULL != mode)
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Bad mode `%s' specified\n",
|
"Bad mode `%s' specified\n",
|
||||||
mode);
|
mode);
|
||||||
}
|
choose_mode = 0;
|
||||||
if (NULL==mode)
|
}
|
||||||
choose_mode=0;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
switch (choose_mode)
|
switch (choose_mode)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
query="deposits_get_ready";
|
query = "deposits_get_ready-v5";
|
||||||
PREPARE (pg,
|
PREPARE (pg,
|
||||||
query,
|
query,
|
||||||
"SELECT"
|
"SELECT"
|
||||||
" payto_uri"
|
" payto_uri"
|
||||||
",merchant_pub"
|
",merchant_pub"
|
||||||
" FROM deposits_by_ready dbr"
|
" FROM deposits dep"
|
||||||
" JOIN deposits dep"
|
" JOIN wire_targets wt"
|
||||||
" ON (dbr.coin_pub = dep.coin_pub AND"
|
" USING (wire_target_h_payto)"
|
||||||
" dbr.deposit_serial_id = dep.deposit_serial_id)"
|
" WHERE NOT (done OR policy_blocked)"
|
||||||
" JOIN wire_targets wt"
|
" AND dep.wire_deadline<=$1"
|
||||||
" USING (wire_target_h_payto)"
|
" AND dep.shard >= $2"
|
||||||
" WHERE dbr.wire_deadline<=$1"
|
" AND dep.shard <= $3"
|
||||||
" AND dbr.shard >= $2"
|
|
||||||
" AND dbr.shard <= $3"
|
|
||||||
" ORDER BY "
|
" ORDER BY "
|
||||||
" dbr.wire_deadline ASC"
|
" dep.wire_deadline ASC"
|
||||||
" ,dbr.shard ASC"
|
" ,dep.shard ASC"
|
||||||
" LIMIT 1;");
|
" LIMIT 1;");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
query="deposits_get_ready_v1";
|
query = "deposits_get_ready-v6";
|
||||||
PREPARE (pg,
|
PREPARE (pg,
|
||||||
query,
|
query,
|
||||||
"WITH rc AS MATERIALIZED ("
|
"WITH rc AS MATERIALIZED ("
|
||||||
" SELECT"
|
" SELECT"
|
||||||
" coin_pub"
|
" merchant_pub"
|
||||||
",deposit_serial_id"
|
|
||||||
" FROM deposits_by_ready"
|
|
||||||
" WHERE"
|
|
||||||
" wire_deadline<=$1"
|
|
||||||
" AND shard >= $2"
|
|
||||||
" AND shard <= $3"
|
|
||||||
" ORDER BY "
|
|
||||||
" wire_deadline ASC"
|
|
||||||
" ,shard ASC"
|
|
||||||
" LIMIT 1"
|
|
||||||
")"
|
|
||||||
"SELECT"
|
|
||||||
" wt.payto_uri"
|
|
||||||
",dep.merchant_pub"
|
|
||||||
" FROM ("
|
|
||||||
" SELECT"
|
|
||||||
" wire_target_h_payto"
|
|
||||||
",merchant_pub"
|
|
||||||
" FROM deposits"
|
|
||||||
" WHERE coin_pub=(SELECT coin_pub FROM rc)"
|
|
||||||
" AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)"
|
|
||||||
") dep"
|
|
||||||
" JOIN wire_targets wt"
|
|
||||||
" ON (dep.wire_target_h_payto = wt.wire_target_h_payto)"
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
query = "stored_procedure_get_ready_deposit";
|
|
||||||
PREPARE (pg,
|
|
||||||
query,
|
|
||||||
"SELECT"
|
|
||||||
" out_payto_uri AS payto_uri"
|
|
||||||
",out_merchant_pub AS merchant_pub"
|
|
||||||
" FROM"
|
|
||||||
" exchange_do_get_ready_deposit"
|
|
||||||
" ($1, $2, $3) ");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
query="deposits_get_ready_v3";
|
|
||||||
PREPARE (pg,
|
|
||||||
query,
|
|
||||||
"WITH rc AS MATERIALIZED ("
|
|
||||||
" SELECT"
|
|
||||||
" coin_pub"
|
|
||||||
",deposit_serial_id"
|
|
||||||
" FROM deposits_by_ready"
|
|
||||||
" WHERE"
|
|
||||||
" wire_deadline<=$1"
|
|
||||||
" AND shard >= $2"
|
|
||||||
" AND shard <= $3"
|
|
||||||
" ORDER BY "
|
|
||||||
" wire_deadline ASC"
|
|
||||||
" ,shard ASC"
|
|
||||||
" LIMIT 1"
|
|
||||||
")"
|
|
||||||
"SELECT"
|
|
||||||
" wt.payto_uri"
|
|
||||||
",dep.merchant_pub"
|
|
||||||
" FROM ("
|
|
||||||
" SELECT"
|
|
||||||
" wire_target_h_payto"
|
|
||||||
",merchant_pub"
|
|
||||||
",coin_pub"
|
|
||||||
" FROM deposits"
|
|
||||||
" WHERE coin_pub=(SELECT coin_pub FROM rc)"
|
|
||||||
" AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)"
|
|
||||||
") dep"
|
|
||||||
" JOIN wire_targets wt"
|
|
||||||
" ON (dep.wire_target_h_payto = wt.wire_target_h_payto)"
|
|
||||||
" JOIN rc"
|
|
||||||
" ON (dep.coin_pub=rc.coin_pub)"
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
query="deposits_get_ready_v4";
|
|
||||||
PREPARE (pg,
|
|
||||||
query,
|
|
||||||
"WITH rc AS MATERIALIZED ("
|
|
||||||
" SELECT"
|
|
||||||
" coin_pub"
|
|
||||||
",deposit_serial_id"
|
|
||||||
" FROM deposits_by_ready"
|
|
||||||
" WHERE"
|
|
||||||
" wire_deadline<=$1"
|
|
||||||
" AND shard >= $2"
|
|
||||||
" AND shard <= $3"
|
|
||||||
" ORDER BY "
|
|
||||||
" wire_deadline ASC"
|
|
||||||
" ,shard ASC"
|
|
||||||
" LIMIT 1"
|
|
||||||
"),"
|
|
||||||
"WITH rv AS MATERIALIZED ("
|
|
||||||
" SELECT"
|
|
||||||
" payto_uri"
|
|
||||||
",wire_target_h_payto"
|
",wire_target_h_payto"
|
||||||
" FROM wire_targets"
|
" FROM deposits"
|
||||||
|
" WHERE NOT (done OR policy_blocked)"
|
||||||
|
" AND wire_deadline<=$1"
|
||||||
|
" AND shard >= $2"
|
||||||
|
" AND shard <= $3"
|
||||||
|
" ORDER BY wire_deadline ASC"
|
||||||
|
" ,shard ASC"
|
||||||
|
" LIMIT 1"
|
||||||
")"
|
")"
|
||||||
"SELECT"
|
"SELECT"
|
||||||
" rv.payto_uri"
|
" wt.payto_uri"
|
||||||
",dep.merchant_pub"
|
",rc.merchant_pub"
|
||||||
" FROM ("
|
" FROM wire_targets wt"
|
||||||
" SELECT"
|
" JOIN rc"
|
||||||
" wire_target_h_payto"
|
" USING (wire_target_h_payto);");
|
||||||
",merchant_pub"
|
|
||||||
" FROM deposits"
|
|
||||||
" WHERE coin_pub=(SELECT coin_pub FROM rc)"
|
|
||||||
" AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)"
|
|
||||||
") dep"
|
|
||||||
" JOIN rv"
|
|
||||||
" ON (rv.wire_target_h_payto=dep.wire_target_h_payto)"
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -24,28 +24,26 @@
|
|||||||
#include "taler_util.h"
|
#include "taler_util.h"
|
||||||
#include "taler_json_lib.h"
|
#include "taler_json_lib.h"
|
||||||
#include "taler_exchangedb_plugin.h"
|
#include "taler_exchangedb_plugin.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert an incoming transaction into reserves. New reserves are also
|
* Insert an incoming transaction into reserves. New reserves are also
|
||||||
* created through this function. Started within the scope of an ongoing
|
* created through this function. Runs its own transaction(s).
|
||||||
* transaction.
|
|
||||||
*
|
*
|
||||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||||
* @param reserve_pub public key of the reserve
|
* @param reserves array of reserves to insert
|
||||||
* @param balance the amount that has to be added to the reserve
|
* @param reserves_length length of the @a reserves array
|
||||||
* @param execution_time when was the amount added
|
* @param batch_size how many inserts to do in one go
|
||||||
* @param sender_account_details account information for the sender (payto://-URL)
|
* @param[out] results set to query status per reserve, must be of length @a reserves_length
|
||||||
* @param exchange_account_section name of the section in the configuration for the exchange's
|
|
||||||
* account into which the deposit was made
|
|
||||||
* @param wire_ref unique reference identifying the wire transfer
|
|
||||||
* @return transaction status code
|
* @return transaction status code
|
||||||
*/
|
*/
|
||||||
enum GNUNET_DB_QueryStatus
|
enum GNUNET_DB_QueryStatus
|
||||||
TEH_PG_reserves_in_insert (void *cls,
|
TEH_PG_reserves_in_insert (
|
||||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
void *cls,
|
||||||
const struct TALER_Amount *balance,
|
const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
|
||||||
struct GNUNET_TIME_Timestamp execution_time,
|
unsigned int reserves_length,
|
||||||
const char *sender_account_details,
|
unsigned int batch_size,
|
||||||
const char *exchange_account_section,
|
enum GNUNET_DB_QueryStatus *results);
|
||||||
uint64_t wire_ref);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -129,7 +129,7 @@ TEH_PG_select_refunds_by_coin (
|
|||||||
|
|
||||||
if (-2 == percent_refund)
|
if (-2 == percent_refund)
|
||||||
{
|
{
|
||||||
const char *mode = getenv ("NEW_LOGIC");
|
const char *mode = getenv ("TALER_POSTGRES_SELECT_REFUNDS_BY_COIN_LOGIC");
|
||||||
char dummy;
|
char dummy;
|
||||||
|
|
||||||
if ( (NULL==mode) ||
|
if ( (NULL==mode) ||
|
||||||
@ -137,14 +137,13 @@ TEH_PG_select_refunds_by_coin (
|
|||||||
"%d%c",
|
"%d%c",
|
||||||
&percent_refund,
|
&percent_refund,
|
||||||
&dummy)) )
|
&dummy)) )
|
||||||
{
|
{
|
||||||
if (NULL != mode)
|
if (NULL != mode)
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Bad mode `%s' specified\n",
|
"Bad mode `%s' specified\n",
|
||||||
mode);
|
mode);
|
||||||
}
|
percent_refund = 0;
|
||||||
if (NULL==mode)
|
}
|
||||||
percent_refund=0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (percent_refund)
|
switch (percent_refund)
|
||||||
|
@ -203,8 +203,6 @@
|
|||||||
#include "pg_reserves_update.h"
|
#include "pg_reserves_update.h"
|
||||||
#include "pg_setup_wire_target.h"
|
#include "pg_setup_wire_target.h"
|
||||||
#include "pg_compute_shard.h"
|
#include "pg_compute_shard.h"
|
||||||
#include "pg_batch_reserves_in_insert.h"
|
|
||||||
#include "pg_batch2_reserves_in_insert.h"
|
|
||||||
#include "pg_insert_kyc_attributes.h"
|
#include "pg_insert_kyc_attributes.h"
|
||||||
#include "pg_update_kyc_attributes.h"
|
#include "pg_update_kyc_attributes.h"
|
||||||
#include "pg_select_similar_kyc_attributes.h"
|
#include "pg_select_similar_kyc_attributes.h"
|
||||||
@ -747,10 +745,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
|
|||||||
= &TEH_PG_select_purse_by_merge_pub;
|
= &TEH_PG_select_purse_by_merge_pub;
|
||||||
plugin->set_purse_balance
|
plugin->set_purse_balance
|
||||||
= &TEH_PG_set_purse_balance;
|
= &TEH_PG_set_purse_balance;
|
||||||
plugin->batch_reserves_in_insert
|
|
||||||
= &TEH_PG_batch_reserves_in_insert;
|
|
||||||
plugin->batch2_reserves_in_insert
|
|
||||||
= &TEH_PG_batch2_reserves_in_insert;
|
|
||||||
plugin->insert_kyc_attributes
|
plugin->insert_kyc_attributes
|
||||||
= &TEH_PG_insert_kyc_attributes;
|
= &TEH_PG_insert_kyc_attributes;
|
||||||
plugin->update_kyc_attributes
|
plugin->update_kyc_attributes
|
||||||
|
@ -1,196 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of TALER
|
|
||||||
Copyright (C) 2014-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 as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @file exchangedb/test_exchangedb_by_j.c
|
|
||||||
* @brief test cases for DB interaction functions
|
|
||||||
* @author Joseph Xu
|
|
||||||
*/
|
|
||||||
#include "platform.h"
|
|
||||||
#include "taler_exchangedb_lib.h"
|
|
||||||
#include "taler_json_lib.h"
|
|
||||||
#include "taler_exchangedb_plugin.h"
|
|
||||||
|
|
||||||
/**o
|
|
||||||
* Global result from the testcase.
|
|
||||||
*/
|
|
||||||
static int result;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Report line of error if @a cond is true, and jump to label "drop".
|
|
||||||
*/
|
|
||||||
#define FAILIF(cond) \
|
|
||||||
do { \
|
|
||||||
if (! (cond)) {break;} \
|
|
||||||
GNUNET_break (0); \
|
|
||||||
goto drop; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes @a ptr with random data.
|
|
||||||
*/
|
|
||||||
#define RND_BLK(ptr) \
|
|
||||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes @a ptr with zeros.
|
|
||||||
*/
|
|
||||||
#define ZR_BLK(ptr) \
|
|
||||||
memset (ptr, 0, sizeof (*ptr))
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Currency we use. Must match test-exchange-db-*.conf.
|
|
||||||
*/
|
|
||||||
#define CURRENCY "EUR"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Database plugin under test.
|
|
||||||
*/
|
|
||||||
static struct TALER_EXCHANGEDB_Plugin *plugin;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main function that will be run by the scheduler.
|
|
||||||
*
|
|
||||||
* @param cls closure with config
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
run (void *cls)
|
|
||||||
{
|
|
||||||
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
|
|
||||||
const uint32_t num_partitions = 10;
|
|
||||||
|
|
||||||
if (NULL ==
|
|
||||||
(plugin = TALER_EXCHANGEDB_plugin_load (cfg)))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
result = 77;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
(void) plugin->drop_tables (plugin->cls);
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
plugin->create_tables (plugin->cls,
|
|
||||||
true,
|
|
||||||
num_partitions))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
result = 77;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i< 8; i++)
|
|
||||||
{
|
|
||||||
static unsigned int batches[] = {1, 1, 2, 3, 4, 16, 64, 256};
|
|
||||||
const char *sndr = "payto://x-taler-bank/localhost:8080/1";
|
|
||||||
struct TALER_Amount value;
|
|
||||||
unsigned int batch_size = batches[i];
|
|
||||||
struct GNUNET_TIME_Absolute now;
|
|
||||||
struct GNUNET_TIME_Timestamp ts;
|
|
||||||
struct GNUNET_TIME_Relative duration;
|
|
||||||
struct TALER_ReservePublicKeyP reserve_pubs[batch_size];
|
|
||||||
struct TALER_EXCHANGEDB_ReserveInInfo reserves[batch_size];
|
|
||||||
enum GNUNET_DB_QueryStatus results[batch_size];
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_string_to_amount (CURRENCY ":1.000010",
|
|
||||||
&value));
|
|
||||||
now = GNUNET_TIME_absolute_get ();
|
|
||||||
ts = GNUNET_TIME_timestamp_get ();
|
|
||||||
|
|
||||||
|
|
||||||
for (unsigned int k = 0; k<batch_size; k++)
|
|
||||||
{
|
|
||||||
RND_BLK (&reserve_pubs[k]);
|
|
||||||
reserves[k].reserve_pub = &reserve_pubs[k];
|
|
||||||
reserves[k].balance = &value;
|
|
||||||
reserves[k].execution_time = ts;
|
|
||||||
reserves[k].sender_account_details = sndr;
|
|
||||||
reserves[k].exchange_account_name = "name";
|
|
||||||
reserves[k].wire_reference = k;
|
|
||||||
}
|
|
||||||
FAILIF (batch_size !=
|
|
||||||
plugin->batch_reserves_in_insert (plugin->cls,
|
|
||||||
reserves,
|
|
||||||
batch_size,
|
|
||||||
results));
|
|
||||||
|
|
||||||
|
|
||||||
duration = GNUNET_TIME_absolute_get_duration (now);
|
|
||||||
fprintf (stdout,
|
|
||||||
"for a batchsize equal to %d it took %s\n",
|
|
||||||
batch_size,
|
|
||||||
GNUNET_STRINGS_relative_time_to_string (duration,
|
|
||||||
GNUNET_NO) );
|
|
||||||
|
|
||||||
}
|
|
||||||
result = 0;
|
|
||||||
drop:
|
|
||||||
GNUNET_break (GNUNET_OK ==
|
|
||||||
plugin->drop_tables (plugin->cls));
|
|
||||||
cleanup:
|
|
||||||
TALER_EXCHANGEDB_plugin_unload (plugin);
|
|
||||||
plugin = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
main (int argc,
|
|
||||||
char *const argv[])
|
|
||||||
{
|
|
||||||
const char *plugin_name;
|
|
||||||
char *config_filename;
|
|
||||||
char *testname;
|
|
||||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
|
||||||
(void) argc;
|
|
||||||
result = -1;
|
|
||||||
if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
GNUNET_log_setup (argv[0],
|
|
||||||
"WARNING",
|
|
||||||
NULL);
|
|
||||||
plugin_name++;
|
|
||||||
(void) GNUNET_asprintf (&testname,
|
|
||||||
"test-exchange-db-%s",
|
|
||||||
plugin_name);
|
|
||||||
(void) GNUNET_asprintf (&config_filename,
|
|
||||||
"%s.conf",
|
|
||||||
testname);
|
|
||||||
fprintf (stdout,
|
|
||||||
"Using config: %s\n",
|
|
||||||
config_filename);
|
|
||||||
cfg = GNUNET_CONFIGURATION_create ();
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
GNUNET_CONFIGURATION_parse (cfg,
|
|
||||||
config_filename))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
GNUNET_free (config_filename);
|
|
||||||
GNUNET_free (testname);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
GNUNET_SCHEDULER_run (&run,
|
|
||||||
cfg);
|
|
||||||
GNUNET_CONFIGURATION_destroy (cfg);
|
|
||||||
GNUNET_free (config_filename);
|
|
||||||
GNUNET_free (testname);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* end of test_exchangedb_by_j.c */
|
|
@ -3479,28 +3479,6 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
struct TALER_PaytoHashP *h_payto);
|
struct TALER_PaytoHashP *h_payto);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert a incoming transaction into reserves. New reserves are
|
|
||||||
* also created through this function.
|
|
||||||
*
|
|
||||||
* @param cls the @e cls of this struct with the plugin-specific state
|
|
||||||
* @param reserve_pub public key of the reserve
|
|
||||||
* @param balance the amount that has to be added to the reserve
|
|
||||||
* @param execution_time when was the amount added
|
|
||||||
* @param sender_account_details information about the sender's bank account, in payto://-format
|
|
||||||
* @param wire_reference unique reference identifying the wire transfer
|
|
||||||
* @return transaction status code
|
|
||||||
*/
|
|
||||||
enum GNUNET_DB_QueryStatus
|
|
||||||
(*reserves_in_insert)(void *cls,
|
|
||||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
|
||||||
const struct TALER_Amount *balance,
|
|
||||||
struct GNUNET_TIME_Timestamp execution_time,
|
|
||||||
const char *sender_account_details,
|
|
||||||
const char *exchange_account_name,
|
|
||||||
uint64_t wire_reference);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert a batch of incoming transaction into reserves. New reserves are
|
* Insert a batch of incoming transaction into reserves. New reserves are
|
||||||
* also created through this function.
|
* also created through this function.
|
||||||
@ -3512,25 +3490,7 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
* set to the status of the
|
* set to the status of the
|
||||||
*/
|
*/
|
||||||
enum GNUNET_DB_QueryStatus
|
enum GNUNET_DB_QueryStatus
|
||||||
(*batch_reserves_in_insert)(
|
(*reserves_in_insert)(
|
||||||
void *cls,
|
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
|
|
||||||
unsigned int reserves_length,
|
|
||||||
enum GNUNET_DB_QueryStatus *results);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert a batch of incoming transaction into reserves. New reserves are
|
|
||||||
* also created through this function.
|
|
||||||
*
|
|
||||||
* @param cls the @e cls of this struct with the plugin-specific state
|
|
||||||
* @param reserves
|
|
||||||
* @param reserves_length length of the @a reserves array
|
|
||||||
* @param[out] results array of transaction status codes of length @a reserves_length,
|
|
||||||
* set to the status of the
|
|
||||||
*/
|
|
||||||
enum GNUNET_DB_QueryStatus
|
|
||||||
(*batch2_reserves_in_insert)(
|
|
||||||
void *cls,
|
void *cls,
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
|
const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
|
||||||
unsigned int reserves_length,
|
unsigned int reserves_length,
|
||||||
@ -4102,13 +4062,6 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
char **payto_uri);
|
char **payto_uri);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum number of results we return from iterate_matching_deposits().
|
|
||||||
*
|
|
||||||
* Limit on the number of transactions we aggregate at once.
|
|
||||||
*/
|
|
||||||
#define TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT 10000
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aggregate all matching deposits for @a h_payto and
|
* Aggregate all matching deposits for @a h_payto and
|
||||||
* @a merchant_pub, returning the total amounts.
|
* @a merchant_pub, returning the total amounts.
|
||||||
|
Loading…
Reference in New Issue
Block a user