implementing #4929
This commit is contained in:
parent
f406f96129
commit
6ab67a3a76
@ -87,12 +87,14 @@ check_track_transfer_response_ok (struct TALER_EXCHANGE_TrackTransferHandle *wdh
|
||||
struct GNUNET_HashCode h_wire;
|
||||
struct GNUNET_TIME_Absolute exec_time;
|
||||
struct TALER_Amount total_amount;
|
||||
struct TALER_Amount wire_fee;
|
||||
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||
unsigned int num_details;
|
||||
struct TALER_ExchangePublicKeyP exchange_pub;
|
||||
struct TALER_ExchangeSignatureP exchange_sig;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
TALER_JSON_spec_amount ("total", &total_amount),
|
||||
TALER_JSON_spec_amount ("wire_fee", &wire_fee),
|
||||
GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub),
|
||||
GNUNET_JSON_spec_fixed_auto ("H_wire", &h_wire),
|
||||
GNUNET_JSON_spec_absolute_time ("execution_time", &exec_time),
|
||||
@ -158,6 +160,8 @@ check_track_transfer_response_ok (struct TALER_EXCHANGE_TrackTransferHandle *wdh
|
||||
wdp.purpose.size = htonl (sizeof (struct TALER_WireDepositDataPS));
|
||||
TALER_amount_hton (&wdp.total,
|
||||
&total_amount);
|
||||
TALER_amount_hton (&wdp.wire_fee,
|
||||
&wire_fee);
|
||||
wdp.merchant_pub = merchant_pub;
|
||||
wdp.h_wire = h_wire;
|
||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||
@ -186,6 +190,7 @@ check_track_transfer_response_ok (struct TALER_EXCHANGE_TrackTransferHandle *wdh
|
||||
&h_wire,
|
||||
exec_time,
|
||||
&total_amount,
|
||||
&wire_fee,
|
||||
num_details,
|
||||
details);
|
||||
}
|
||||
@ -257,6 +262,7 @@ handle_track_transfer_finished (void *cls,
|
||||
NULL,
|
||||
GNUNET_TIME_UNIT_ZERO_ABS,
|
||||
NULL,
|
||||
NULL,
|
||||
0, NULL);
|
||||
TALER_EXCHANGE_track_transfer_cancel (wdh);
|
||||
}
|
||||
|
@ -540,6 +540,12 @@ struct Command
|
||||
*/
|
||||
const char *total_amount_expected;
|
||||
|
||||
/**
|
||||
* What is the expected wire fee? Only used if
|
||||
* @e expected_response_code was #MHD_HTTP_OK.
|
||||
*/
|
||||
const char *wire_fee_expected;
|
||||
|
||||
|
||||
/* TODO: may want to add list of deposits we expected
|
||||
to see aggregated here in the future. */
|
||||
@ -1417,6 +1423,7 @@ wire_cb (void *cls,
|
||||
* @param execution_time time when the exchange claims to have performed the wire transfer
|
||||
* @param total_amount total amount of the wire transfer, or NULL if the exchange could
|
||||
* not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK)
|
||||
* @param wire_fee wire fee that was charged by the exchange
|
||||
* @param details_length length of the @a details array
|
||||
* @param details array with details about the combined transactions
|
||||
*/
|
||||
@ -1429,6 +1436,7 @@ wire_deposits_cb (void *cls,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
struct GNUNET_TIME_Absolute execution_time,
|
||||
const struct TALER_Amount *total_amount,
|
||||
const struct TALER_Amount *wire_fee,
|
||||
unsigned int details_length,
|
||||
const struct TALER_TrackTransferDetails *details)
|
||||
{
|
||||
@ -1469,6 +1477,24 @@ wire_deposits_cb (void *cls,
|
||||
fail (is);
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_string_to_amount (cmd->details.wire_deposits.wire_fee_expected,
|
||||
&expected_amount))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
fail (is);
|
||||
return;
|
||||
}
|
||||
if (0 != TALER_amount_cmp (wire_fee,
|
||||
&expected_amount))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Wire fee missmatch to command %s\n",
|
||||
cmd->label);
|
||||
json_dumpf (json, stderr, 0);
|
||||
fail (is);
|
||||
return;
|
||||
}
|
||||
ref = find_command (is,
|
||||
cmd->details.wire_deposits.wtid_ref);
|
||||
GNUNET_assert (NULL != ref);
|
||||
@ -2923,28 +2949,28 @@ run (void *cls)
|
||||
{ .oc = OC_CHECK_BANK_TRANSFER,
|
||||
.label = "check_bank_transfer-499c",
|
||||
.details.check_bank_transfer.exchange_base_url = "https://exchange.com/",
|
||||
.details.check_bank_transfer.amount = "EUR:4.99",
|
||||
.details.check_bank_transfer.amount = "EUR:4.98",
|
||||
.details.check_bank_transfer.account_debit = 2,
|
||||
.details.check_bank_transfer.account_credit = 42
|
||||
},
|
||||
{ .oc = OC_CHECK_BANK_TRANSFER,
|
||||
.label = "check_bank_transfer-99c1",
|
||||
.details.check_bank_transfer.exchange_base_url = "https://exchange.com/",
|
||||
.details.check_bank_transfer.amount = "EUR:0.99",
|
||||
.details.check_bank_transfer.amount = "EUR:0.98",
|
||||
.details.check_bank_transfer.account_debit = 2,
|
||||
.details.check_bank_transfer.account_credit = 42
|
||||
},
|
||||
{ .oc = OC_CHECK_BANK_TRANSFER,
|
||||
.label = "check_bank_transfer-99c2",
|
||||
.details.check_bank_transfer.exchange_base_url = "https://exchange.com/",
|
||||
.details.check_bank_transfer.amount = "EUR:0.99",
|
||||
.details.check_bank_transfer.amount = "EUR:0.98",
|
||||
.details.check_bank_transfer.account_debit = 2,
|
||||
.details.check_bank_transfer.account_credit = 42
|
||||
},
|
||||
{ .oc = OC_CHECK_BANK_TRANSFER,
|
||||
.label = "check_bank_transfer-9c",
|
||||
.details.check_bank_transfer.exchange_base_url = "https://exchange.com/",
|
||||
.details.check_bank_transfer.amount = "EUR:0.09",
|
||||
.details.check_bank_transfer.amount = "EUR:0.08",
|
||||
.details.check_bank_transfer.account_debit = 2,
|
||||
.details.check_bank_transfer.account_credit = 43
|
||||
},
|
||||
@ -2959,16 +2985,18 @@ run (void *cls)
|
||||
.details.deposit_wtid.bank_transfer_ref = "check_bank_transfer-499c" },
|
||||
|
||||
{ .oc = OC_WIRE_DEPOSITS,
|
||||
.label = "wire-deposits-sucess-bank",
|
||||
.label = "wire-deposits-success-bank",
|
||||
.expected_response_code = MHD_HTTP_OK,
|
||||
.details.wire_deposits.wtid_ref = "check_bank_transfer-99c1",
|
||||
.details.wire_deposits.total_amount_expected = "EUR:0.99" },
|
||||
.details.wire_deposits.total_amount_expected = "EUR:0.98",
|
||||
.details.wire_deposits.wire_fee_expected = "EUR:0.01" },
|
||||
|
||||
{ .oc = OC_WIRE_DEPOSITS,
|
||||
.label = "wire-deposits-sucess-wtid",
|
||||
.label = "wire-deposits-success-wtid",
|
||||
.expected_response_code = MHD_HTTP_OK,
|
||||
.details.wire_deposits.wtid_ref = "deposit-wtid-ok",
|
||||
.details.wire_deposits.total_amount_expected = "EUR:4.99" },
|
||||
.details.wire_deposits.total_amount_expected = "EUR:4.98",
|
||||
.details.wire_deposits.wire_fee_expected = "EUR:0.01" },
|
||||
|
||||
/* ************** End of tracking API testing************* */
|
||||
|
||||
@ -3030,7 +3058,7 @@ run (void *cls)
|
||||
{ .oc = OC_CHECK_BANK_TRANSFER,
|
||||
.label = "check_bank_transfer-pre-refund",
|
||||
.details.check_bank_transfer.exchange_base_url = "https://exchange.com/",
|
||||
.details.check_bank_transfer.amount = "EUR:4.98",
|
||||
.details.check_bank_transfer.amount = "EUR:4.97",
|
||||
.details.check_bank_transfer.account_debit = 2,
|
||||
.details.check_bank_transfer.account_credit = 42
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2016 GNUnet e.V.
|
||||
Copyright (C) 2016, 2017 GNUnet e.V.
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
@ -53,6 +53,12 @@ struct WirePlugin
|
||||
* Name of the plugin.
|
||||
*/
|
||||
char *type;
|
||||
|
||||
/**
|
||||
* Wire transfer fee structure.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -102,6 +108,11 @@ struct AggregationUnit
|
||||
*/
|
||||
struct TALER_Amount total_amount;
|
||||
|
||||
/**
|
||||
* Wire fee we charge for @e wp at @e execution_time.
|
||||
*/
|
||||
struct TALER_Amount wire_fee;
|
||||
|
||||
/**
|
||||
* Hash of @e wire.
|
||||
*/
|
||||
@ -259,6 +270,83 @@ extract_type (const json_t *wire)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Advance the "af" pointer in @a wp to point to the
|
||||
* currently valid record.
|
||||
*
|
||||
* @param wp wire transfer fee data structure to update
|
||||
* @param now timestamp to update fees to
|
||||
*/
|
||||
static void
|
||||
advance_fees (struct WirePlugin *wp,
|
||||
struct GNUNET_TIME_Absolute now)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af;
|
||||
|
||||
/* First, try to see if we have current fee information in memory */
|
||||
af = wp->af;
|
||||
while ( (NULL != af) &&
|
||||
(af->end_date.abs_value_us < now.abs_value_us) )
|
||||
{
|
||||
struct TALER_EXCHANGEDB_AggregateFees *n = af->next;
|
||||
|
||||
GNUNET_free (af);
|
||||
af = n;
|
||||
}
|
||||
wp->af = af;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update wire transfer fee data structure in @a wp.
|
||||
*
|
||||
* @param wp wire transfer fee data structure to update
|
||||
* @param now timestamp to update fees to
|
||||
* @param session DB session to use
|
||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR if we
|
||||
* lack current fee information (and need to exit)
|
||||
*/
|
||||
static int
|
||||
update_fees (struct WirePlugin *wp,
|
||||
struct GNUNET_TIME_Absolute now,
|
||||
struct TALER_EXCHANGEDB_Session *session)
|
||||
{
|
||||
advance_fees (wp,
|
||||
now);
|
||||
if (NULL != wp->af)
|
||||
return GNUNET_OK;
|
||||
/* Let's try to load it from disk... */
|
||||
wp->af = TALER_EXCHANGEDB_fees_read (cfg,
|
||||
wp->type);
|
||||
advance_fees (wp,
|
||||
now);
|
||||
for (struct TALER_EXCHANGEDB_AggregateFees *p = wp->af;
|
||||
NULL != p;
|
||||
p = p->next)
|
||||
{
|
||||
if (GNUNET_SYSERR ==
|
||||
db_plugin->insert_wire_fee (db_plugin->cls,
|
||||
session,
|
||||
wp->type,
|
||||
p->start_date,
|
||||
p->end_date,
|
||||
&p->wire_fee,
|
||||
&p->master_sig))
|
||||
{
|
||||
TALER_EXCHANGEDB_fees_free (wp->af);
|
||||
wp->af = NULL;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
if (NULL != wp->af)
|
||||
return GNUNET_OK;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to find current wire transfer fees for `%s'\n",
|
||||
wp->type);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the wire plugin for the given wire address.
|
||||
*
|
||||
@ -345,6 +433,7 @@ shutdown_task (void *cls)
|
||||
wp_tail,
|
||||
wp);
|
||||
TALER_WIRE_plugin_unload (wp->wire_plugin);
|
||||
TALER_EXCHANGEDB_fees_free (wp->af);
|
||||
GNUNET_free (wp->type);
|
||||
GNUNET_free (wp);
|
||||
}
|
||||
@ -433,9 +522,8 @@ deposit_cb (void *cls,
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
au->row_id = row_id;
|
||||
GNUNET_assert (NULL == au->wire);
|
||||
au->wire = json_incref ((json_t *) wire);
|
||||
au->execution_time = GNUNET_TIME_absolute_get ();
|
||||
(void) GNUNET_TIME_round_abs (&au->execution_time);
|
||||
TALER_JSON_hash (au->wire,
|
||||
&au->h_wire);
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||
@ -444,6 +532,21 @@ deposit_cb (void *cls,
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Starting aggregation under H(WTID)=%s\n",
|
||||
TALER_B2S (&au->wtid));
|
||||
|
||||
au->wp = find_plugin (extract_type (au->wire));
|
||||
if (NULL == au->wp)
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
/* make sure we have current fees */
|
||||
au->execution_time = GNUNET_TIME_absolute_get ();
|
||||
(void) GNUNET_TIME_round_abs (&au->execution_time);
|
||||
if (GNUNET_OK !=
|
||||
update_fees (au->wp,
|
||||
au->execution_time,
|
||||
au->session))
|
||||
return GNUNET_SYSERR;
|
||||
au->wire_fee = au->wp->af->wire_fee;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
db_plugin->insert_aggregation_tracking (db_plugin->cls,
|
||||
au->session,
|
||||
@ -585,7 +688,7 @@ run_aggregation (void *cls)
|
||||
unsigned int i;
|
||||
int ret;
|
||||
const struct GNUNET_SCHEDULER_TaskContext *tc;
|
||||
struct WirePlugin *wp;
|
||||
struct TALER_Amount final_amount;
|
||||
|
||||
task = NULL;
|
||||
tc = GNUNET_SCHEDULER_get_task_context ();
|
||||
@ -650,18 +753,6 @@ run_aggregation (void *cls)
|
||||
return;
|
||||
}
|
||||
|
||||
wp = find_plugin (extract_type (au->wire));
|
||||
if (NULL == wp)
|
||||
{
|
||||
json_decref (au->wire);
|
||||
GNUNET_free (au);
|
||||
au = NULL;
|
||||
db_plugin->rollback (db_plugin->cls,
|
||||
session);
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now try to find other deposits to aggregate */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Found ready deposit for %s, aggregating\n",
|
||||
@ -689,13 +780,18 @@ run_aggregation (void *cls)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Round to the unit supported by the wire transfer method */
|
||||
GNUNET_assert (GNUNET_SYSERR !=
|
||||
wp->wire_plugin->amount_round (wp->wire_plugin->cls,
|
||||
&au->total_amount));
|
||||
/* Check if after rounding down, we still have an amount to transfer */
|
||||
if ( (0 == au->total_amount.value) &&
|
||||
(0 == au->total_amount.fraction) )
|
||||
/* Subtract wire transfer fee and round to the unit supported by the
|
||||
wire transfer method; Check if after rounding down, we still have
|
||||
an amount to transfer, and if not mark as 'tiny'. */
|
||||
if ( (GNUNET_OK !=
|
||||
TALER_amount_subtract (&final_amount,
|
||||
&au->total_amount,
|
||||
&au->wire_fee)) ||
|
||||
(GNUNET_SYSERR ==
|
||||
au->wp->wire_plugin->amount_round (au->wp->wire_plugin->cls,
|
||||
&final_amount)) ||
|
||||
( (0 == final_amount.value) &&
|
||||
(0 == final_amount.fraction) ) )
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Aggregate value too low for transfer\n");
|
||||
@ -755,21 +851,20 @@ run_aggregation (void *cls)
|
||||
{
|
||||
char *amount_s;
|
||||
|
||||
amount_s = TALER_amount_to_string (&au->total_amount);
|
||||
amount_s = TALER_amount_to_string (&final_amount);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Preparing wire transfer of %s to %s\n",
|
||||
amount_s,
|
||||
TALER_B2S (&au->merchant_pub));
|
||||
GNUNET_free (amount_s);
|
||||
}
|
||||
au->wp = wp;
|
||||
au->ph = wp->wire_plugin->prepare_wire_transfer (wp->wire_plugin->cls,
|
||||
au->wire,
|
||||
&au->total_amount,
|
||||
exchange_base_url,
|
||||
&au->wtid,
|
||||
&prepare_cb,
|
||||
au);
|
||||
au->ph = au->wp->wire_plugin->prepare_wire_transfer (au->wp->wire_plugin->cls,
|
||||
au->wire,
|
||||
&final_amount,
|
||||
exchange_base_url,
|
||||
&au->wtid,
|
||||
&prepare_cb,
|
||||
au);
|
||||
if (NULL == au->ph)
|
||||
{
|
||||
GNUNET_break (0); /* why? how to best recover? */
|
||||
|
@ -1864,6 +1864,11 @@ struct WtidTransactionContext
|
||||
*/
|
||||
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||
|
||||
/**
|
||||
* Which method was used to wire the funds?
|
||||
*/
|
||||
char *wire_method;
|
||||
|
||||
/**
|
||||
* Hash of the wire details of the merchant (identical for all
|
||||
* deposits), only valid if @e is_valid is #GNUNET_YES.
|
||||
@ -1918,6 +1923,7 @@ struct WtidTransactionContext
|
||||
static void
|
||||
handle_transaction_data (void *cls,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const char *wire_method,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
struct GNUNET_TIME_Absolute exec_time,
|
||||
const struct GNUNET_HashCode *h_proposal_data,
|
||||
@ -1936,6 +1942,7 @@ handle_transaction_data (void *cls,
|
||||
ctx->merchant_pub = *merchant_pub;
|
||||
ctx->h_wire = *h_wire;
|
||||
ctx->exec_time = exec_time;
|
||||
ctx->wire_method = GNUNET_strdup (wire_method);
|
||||
ctx->is_valid = GNUNET_YES;
|
||||
if (GNUNET_OK !=
|
||||
TALER_amount_subtract (&ctx->total,
|
||||
@ -1952,6 +1959,8 @@ handle_transaction_data (void *cls,
|
||||
if ( (0 != memcmp (&ctx->merchant_pub,
|
||||
merchant_pub,
|
||||
sizeof (struct TALER_MerchantPublicKeyP))) ||
|
||||
(0 != strcmp (wire_method,
|
||||
ctx->wire_method)) ||
|
||||
(0 != memcmp (&ctx->h_wire,
|
||||
h_wire,
|
||||
sizeof (struct GNUNET_HashCode))) )
|
||||
@ -2006,6 +2015,10 @@ TEH_DB_execute_track_transfer (struct MHD_Connection *connection,
|
||||
struct WtidTransactionContext ctx;
|
||||
struct TALER_EXCHANGEDB_Session *session;
|
||||
struct TEH_TrackTransferDetail *wdd;
|
||||
struct GNUNET_TIME_Absolute wire_fee_start_date;
|
||||
struct GNUNET_TIME_Absolute wire_fee_end_date;
|
||||
struct TALER_Amount wire_fee;
|
||||
struct TALER_MasterSignatureP wire_fee_master_sig;
|
||||
|
||||
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||
{
|
||||
@ -2016,6 +2029,7 @@ TEH_DB_execute_track_transfer (struct MHD_Connection *connection,
|
||||
ctx.is_valid = GNUNET_NO;
|
||||
ctx.wdd_head = NULL;
|
||||
ctx.wdd_tail = NULL;
|
||||
ctx.wire_method = NULL;
|
||||
ret = TEH_plugin->lookup_wire_transfer (TEH_plugin->cls,
|
||||
session,
|
||||
wtid,
|
||||
@ -2042,10 +2056,36 @@ TEH_DB_execute_track_transfer (struct MHD_Connection *connection,
|
||||
"wtid");
|
||||
goto cleanup;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TEH_plugin->get_wire_fee (TEH_plugin->cls,
|
||||
session,
|
||||
ctx.wire_method,
|
||||
ctx.exec_time,
|
||||
&wire_fee_start_date,
|
||||
&wire_fee_end_date,
|
||||
&wire_fee,
|
||||
&wire_fee_master_sig))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ret = TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_TRACK_TRANSFER_WIRE_FEE_NOT_FOUND);
|
||||
goto cleanup;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_amount_subtract (&ctx.total,
|
||||
&ctx.total,
|
||||
&wire_fee))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ret = TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_TRACK_TRANSFER_WIRE_FEE_INCONSISTENT);
|
||||
goto cleanup;
|
||||
}
|
||||
ret = TEH_RESPONSE_reply_track_transfer_details (connection,
|
||||
&ctx.total,
|
||||
&ctx.merchant_pub,
|
||||
&ctx.h_wire,
|
||||
&wire_fee,
|
||||
ctx.exec_time,
|
||||
ctx.wdd_head);
|
||||
cleanup:
|
||||
@ -2056,6 +2096,7 @@ TEH_DB_execute_track_transfer (struct MHD_Connection *connection,
|
||||
wdd);
|
||||
GNUNET_free (wdd);
|
||||
}
|
||||
GNUNET_free_non_null (ctx.wire_method);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1214,6 +1214,7 @@ TEH_RESPONSE_reply_track_transaction (struct MHD_Connection *connection,
|
||||
* @param total total amount that was transferred
|
||||
* @param merchant_pub public key of the merchant
|
||||
* @param h_wire destination account
|
||||
* @param wire_fee wire fee that was charged
|
||||
* @param exec_time execution time of the wire transfer
|
||||
* @param wdd_head linked list with details about the combined deposits
|
||||
* @return MHD result code
|
||||
@ -1223,6 +1224,7 @@ TEH_RESPONSE_reply_track_transfer_details (struct MHD_Connection *connection,
|
||||
const struct TALER_Amount *total,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
const struct TALER_Amount *wire_fee,
|
||||
struct GNUNET_TIME_Absolute exec_time,
|
||||
const struct TEH_TrackTransferDetail *wdd_head)
|
||||
{
|
||||
@ -1261,6 +1263,8 @@ TEH_RESPONSE_reply_track_transfer_details (struct MHD_Connection *connection,
|
||||
wdp.purpose.size = htonl (sizeof (struct TALER_WireDepositDataPS));
|
||||
TALER_amount_hton (&wdp.total,
|
||||
total);
|
||||
TALER_amount_hton (&wdp.wire_fee,
|
||||
wire_fee);
|
||||
wdp.merchant_pub = *merchant_pub;
|
||||
wdp.h_wire = *h_wire;
|
||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||
@ -1270,8 +1274,9 @@ TEH_RESPONSE_reply_track_transfer_details (struct MHD_Connection *connection,
|
||||
&sig);
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_OK,
|
||||
"{s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
|
||||
"{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
|
||||
"total", TALER_JSON_from_amount (total),
|
||||
"wire_fee", TALER_JSON_from_amount (wire_fee),
|
||||
"merchant_pub", GNUNET_JSON_from_data_auto (merchant_pub),
|
||||
"H_wire", GNUNET_JSON_from_data_auto (h_wire),
|
||||
"execution_time", GNUNET_JSON_from_time_abs (exec_time),
|
||||
|
@ -399,6 +399,7 @@ struct TEH_TrackTransferDetail
|
||||
* @param total total amount that was transferred
|
||||
* @param merchant_pub public key of the merchant
|
||||
* @param h_wire destination account
|
||||
* @param wire_fee wire fee that was charged
|
||||
* @param exec_time execution time of the wire transfer
|
||||
* @param wdd_head linked list with details about the combined deposits
|
||||
* @return MHD result code
|
||||
@ -408,6 +409,7 @@ TEH_RESPONSE_reply_track_transfer_details (struct MHD_Connection *connection,
|
||||
const struct TALER_Amount *total,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
const struct TALER_Amount *wire_fee,
|
||||
struct GNUNET_TIME_Absolute exec_time,
|
||||
const struct TEH_TrackTransferDetail *wdd_head);
|
||||
|
||||
|
@ -29,6 +29,20 @@ DB_CONN_STR = postgres:///talercheck
|
||||
# Enable 'test' for testing of the actual coin operations.
|
||||
ENABLE = YES
|
||||
|
||||
# Fees for the forseeable future...
|
||||
# If you see this after 2017, update to match the next 10 years...
|
||||
WIRE-FEE-2017 = EUR:0.01
|
||||
WIRE-FEE-2018 = EUR:0.01
|
||||
WIRE-FEE-2019 = EUR:0.01
|
||||
WIRE-FEE-2020 = EUR:0.01
|
||||
WIRE-FEE-2021 = EUR:0.01
|
||||
WIRE-FEE-2022 = EUR:0.01
|
||||
WIRE-FEE-2023 = EUR:0.01
|
||||
WIRE-FEE-2024 = EUR:0.01
|
||||
WIRE-FEE-2025 = EUR:0.01
|
||||
WIRE-FEE-2026 = EUR:0.01
|
||||
|
||||
|
||||
[exchange-wire-outgoing-test]
|
||||
# What is the main website of the bank?
|
||||
BANK_URI = "http://localhost:8082/"
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
(C) 2016 Inria and GNUnet e.V.
|
||||
(C) 2016, 2017 Inria and GNUnet e.V.
|
||||
|
||||
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
|
||||
@ -621,7 +621,7 @@ run_test ()
|
||||
.details.expect_transaction.debit_account = 3,
|
||||
.details.expect_transaction.credit_account = 4,
|
||||
.details.expect_transaction.exchange_base_url = "https://exchange.taler.net/",
|
||||
.details.expect_transaction.amount = "EUR:0.9"
|
||||
.details.expect_transaction.amount = "EUR:0.89"
|
||||
},
|
||||
|
||||
{
|
||||
@ -668,7 +668,7 @@ run_test ()
|
||||
.details.expect_transaction.debit_account = 3,
|
||||
.details.expect_transaction.credit_account = 4,
|
||||
.details.expect_transaction.exchange_base_url = "https://exchange.taler.net/",
|
||||
.details.expect_transaction.amount = "EUR:1.8"
|
||||
.details.expect_transaction.amount = "EUR:1.79"
|
||||
},
|
||||
|
||||
{
|
||||
@ -714,7 +714,7 @@ run_test ()
|
||||
.details.expect_transaction.debit_account = 3,
|
||||
.details.expect_transaction.credit_account = 4,
|
||||
.details.expect_transaction.exchange_base_url = "https://exchange.taler.net/",
|
||||
.details.expect_transaction.amount = "EUR:0.9"
|
||||
.details.expect_transaction.amount = "EUR:0.89"
|
||||
},
|
||||
{
|
||||
.opcode = OPCODE_EXPECT_TRANSACTION,
|
||||
@ -722,7 +722,7 @@ run_test ()
|
||||
.details.expect_transaction.debit_account = 3,
|
||||
.details.expect_transaction.credit_account = 4,
|
||||
.details.expect_transaction.exchange_base_url = "https://exchange.taler.net/",
|
||||
.details.expect_transaction.amount = "EUR:0.9"
|
||||
.details.expect_transaction.amount = "EUR:0.89"
|
||||
},
|
||||
{
|
||||
.opcode = OPCODE_EXPECT_TRANSACTION,
|
||||
@ -730,7 +730,7 @@ run_test ()
|
||||
.details.expect_transaction.debit_account = 3,
|
||||
.details.expect_transaction.credit_account = 5,
|
||||
.details.expect_transaction.exchange_base_url = "https://exchange.taler.net/",
|
||||
.details.expect_transaction.amount = "EUR:0.9"
|
||||
.details.expect_transaction.amount = "EUR:0.89"
|
||||
},
|
||||
{
|
||||
.opcode = OPCODE_EXPECT_TRANSACTIONS_EMPTY,
|
||||
@ -779,7 +779,7 @@ run_test ()
|
||||
.details.expect_transaction.debit_account = 3,
|
||||
.details.expect_transaction.credit_account = 4,
|
||||
.details.expect_transaction.exchange_base_url = "https://exchange.taler.net/",
|
||||
.details.expect_transaction.amount = "EUR:0.2"
|
||||
.details.expect_transaction.amount = "EUR:0.19"
|
||||
},
|
||||
|
||||
/* test picking all deposits at earliest deadline */
|
||||
@ -824,7 +824,7 @@ run_test ()
|
||||
.details.expect_transaction.debit_account = 3,
|
||||
.details.expect_transaction.credit_account = 4,
|
||||
.details.expect_transaction.exchange_base_url = "https://exchange.taler.net/",
|
||||
.details.expect_transaction.amount = "EUR:0.2"
|
||||
.details.expect_transaction.amount = "EUR:0.19"
|
||||
},
|
||||
|
||||
/* Test NEVER running 'tiny' unless they make up minimum unit */
|
||||
@ -894,7 +894,7 @@ run_test ()
|
||||
.details.deposit.merchant_name = "bob",
|
||||
.details.deposit.merchant_account = 4,
|
||||
.details.deposit.wire_deadline = { 1000LL * 1000 * 0 }, /* 0s */
|
||||
.details.deposit.amount_with_fee = "EUR:0.102",
|
||||
.details.deposit.amount_with_fee = "EUR:0.112",
|
||||
.details.deposit.deposit_fee = "EUR:0.1"
|
||||
},
|
||||
{
|
||||
@ -934,7 +934,7 @@ run_test ()
|
||||
.details.deposit.merchant_name = "bob",
|
||||
.details.deposit.merchant_account = 4,
|
||||
.details.deposit.wire_deadline = { 1000LL * 1000 * 0 }, /* 0s */
|
||||
.details.deposit.amount_with_fee = "EUR:0.109",
|
||||
.details.deposit.amount_with_fee = "EUR:0.119",
|
||||
.details.deposit.deposit_fee = "EUR:0.1"
|
||||
},
|
||||
{
|
||||
@ -969,7 +969,7 @@ run_test ()
|
||||
.details.expect_transaction.debit_account = 3,
|
||||
.details.expect_transaction.credit_account = 4,
|
||||
.details.expect_transaction.exchange_base_url = "https://exchange.taler.net/",
|
||||
.details.expect_transaction.amount = "EUR:0.02"
|
||||
.details.expect_transaction.amount = "EUR:0.01"
|
||||
},
|
||||
|
||||
/* Test that aggregation would happen fully if wire deadline is long */
|
||||
@ -1027,7 +1027,7 @@ run_test ()
|
||||
.details.expect_transaction.debit_account = 3,
|
||||
.details.expect_transaction.credit_account = 4,
|
||||
.details.expect_transaction.exchange_base_url = "https://exchange.taler.net/",
|
||||
.details.expect_transaction.amount = "EUR:0.04"
|
||||
.details.expect_transaction.amount = "EUR:0.03"
|
||||
},
|
||||
|
||||
|
||||
@ -1087,7 +1087,7 @@ run_test ()
|
||||
.details.expect_transaction.debit_account = 3,
|
||||
.details.expect_transaction.credit_account = 4,
|
||||
.details.expect_transaction.exchange_base_url = "https://exchange.taler.net/",
|
||||
.details.expect_transaction.amount = "EUR:0.02"
|
||||
.details.expect_transaction.amount = "EUR:0.01"
|
||||
},
|
||||
|
||||
/* Everything tested, terminate with success */
|
||||
@ -1203,6 +1203,7 @@ main (int argc,
|
||||
{
|
||||
const char *plugin_name;
|
||||
char *testname;
|
||||
struct GNUNET_OS_Process *proc;
|
||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||
struct GNUNET_SIGNAL_Context *shc_chld;
|
||||
|
||||
@ -1225,6 +1226,21 @@ main (int argc,
|
||||
GNUNET_log_setup ("test_taler_exchange_aggregator",
|
||||
"WARNING",
|
||||
NULL);
|
||||
proc = GNUNET_OS_start_process (GNUNET_NO,
|
||||
GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-keyup",
|
||||
"taler-exchange-keyup",
|
||||
"-c", config_filename,
|
||||
NULL);
|
||||
if (NULL == proc)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to run `taler-exchange-keyup`, is your PATH correct?\n");
|
||||
return 77;
|
||||
}
|
||||
GNUNET_OS_process_wait (proc);
|
||||
GNUNET_OS_process_destroy (proc);
|
||||
cfg = GNUNET_CONFIGURATION_create ();
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_parse (cfg,
|
||||
|
@ -11,4 +11,4 @@ AUDITOR_BASE_DIR = ${TALER_DATA_HOME}/auditors/
|
||||
# the merchant per wire transfer. The directory is expected to
|
||||
# contain files "$METHOD.fee" with the cost structure, where
|
||||
# $METHOD corresponds to a wire transfer method.
|
||||
WIREFEE_BASE_DIR = ${TALER_DATA_HOME}/wirefees/
|
||||
WIREFEE_BASE_DIR = ${TALER_DATA_HOME}/exchange/wirefees/
|
||||
|
@ -215,6 +215,8 @@ postgres_drop_tables (void *cls)
|
||||
"DROP TABLE IF EXISTS prewire;");
|
||||
SQLEXEC_ (conn,
|
||||
"DROP TABLE IF EXISTS aggregation_tracking;");
|
||||
SQLEXEC_ (conn,
|
||||
"DROP TABLE IF EXISTS wire_fee;");
|
||||
SQLEXEC_ (conn,
|
||||
"DROP TABLE IF EXISTS deposits;");
|
||||
SQLEXEC_ (conn,
|
||||
@ -472,6 +474,23 @@ postgres_create_tables (void *cls)
|
||||
SQLEXEC_INDEX("CREATE INDEX aggregation_tracking_wtid_index "
|
||||
"ON aggregation_tracking(wtid_raw)");
|
||||
|
||||
|
||||
/* Table for the wire fees. */
|
||||
SQLEXEC("CREATE TABLE IF NOT EXISTS wire_fee "
|
||||
"(wire_method VARCHAR NOT NULL"
|
||||
",start_date INT8 NOT NULL"
|
||||
",end_date INT8 NOT NULL"
|
||||
",wire_fee_val INT8 NOT NULL"
|
||||
",wire_fee_frac INT4 NOT NULL"
|
||||
",wire_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
|
||||
",master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)"
|
||||
",PRIMARY KEY (wire_method, start_date)" /* this combo must be unique */
|
||||
")");
|
||||
/* Index for lookup_transactions statement on wtid */
|
||||
SQLEXEC_INDEX("CREATE INDEX aggregation_tracking_wtid_index "
|
||||
"ON aggregation_tracking(wtid_raw)");
|
||||
|
||||
|
||||
/* This table contains the pre-commit data for
|
||||
wire transfers the exchange is about to execute. */
|
||||
SQLEXEC("CREATE TABLE IF NOT EXISTS prewire "
|
||||
@ -1193,6 +1212,7 @@ postgres_prepare (PGconn *db_conn)
|
||||
PREPARE ("lookup_transactions",
|
||||
"SELECT"
|
||||
" deposits.h_proposal_data"
|
||||
",deposits.wire"
|
||||
",deposits.h_wire"
|
||||
",deposits.coin_pub"
|
||||
",deposits.merchant_pub"
|
||||
@ -1241,6 +1261,35 @@ postgres_prepare (PGconn *db_conn)
|
||||
"($1, $2, $3)",
|
||||
3, NULL);
|
||||
|
||||
/* Used in #postgres_get_wire_fee() */
|
||||
PREPARE ("get_wire_fee",
|
||||
"SELECT "
|
||||
" start_date"
|
||||
",end_date"
|
||||
",wire_fee_val"
|
||||
",wire_fee_frac"
|
||||
",wire_fee_curr"
|
||||
",master_sig"
|
||||
" FROM wire_fee"
|
||||
" WHERE wire_method=$1"
|
||||
" AND start_date <= $2"
|
||||
" AND end_date > $2",
|
||||
2, NULL);
|
||||
|
||||
/* Used in #postgres_insert_wire_fee */
|
||||
PREPARE ("insert_wire_fee",
|
||||
"INSERT INTO wire_fee "
|
||||
"(wire_method"
|
||||
",start_date"
|
||||
",end_date"
|
||||
",wire_fee_val"
|
||||
",wire_fee_frac"
|
||||
",wire_fee_curr"
|
||||
",master_sig"
|
||||
") VALUES "
|
||||
"($1, $2, $3, $4, $5, $6, $7)",
|
||||
7, NULL);
|
||||
|
||||
|
||||
/* Used in #postgres_wire_prepare_data_insert() to store
|
||||
wire transfer information before actually committing it with the bank */
|
||||
@ -3980,15 +4029,19 @@ postgres_lookup_wire_transfer (void *cls,
|
||||
struct GNUNET_TIME_Absolute exec_time;
|
||||
struct TALER_Amount amount_with_fee;
|
||||
struct TALER_Amount deposit_fee;
|
||||
json_t *wire;
|
||||
json_t *t;
|
||||
const char *wire_method;
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_proposal_data", &h_proposal_data),
|
||||
TALER_PQ_result_spec_json ("wire", &wire),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_wire", &h_wire),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("coin_pub", &coin_pub),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", &merchant_pub),
|
||||
GNUNET_PQ_result_spec_absolute_time ("execution_time", &exec_time),
|
||||
TALER_PQ_result_spec_amount ("amount_with_fee", &amount_with_fee),
|
||||
TALER_PQ_result_spec_amount ("fee_deposit", &deposit_fee),
|
||||
GNUNET_PQ_result_spec_end
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result,
|
||||
@ -3999,8 +4052,23 @@ postgres_lookup_wire_transfer (void *cls,
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
t = json_object_get (wire, "type");
|
||||
if (NULL == t)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
wire_method = json_string_value (t);
|
||||
if (NULL == wire_method)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cb (cb_cls,
|
||||
&merchant_pub,
|
||||
wire_method,
|
||||
&h_wire,
|
||||
exec_time,
|
||||
&h_proposal_data,
|
||||
@ -4210,6 +4278,170 @@ postgres_insert_aggregation_tracking (void *cls,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain wire fee from database.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param session database connection
|
||||
* @param type type of wire transfer the fee applies for
|
||||
* @param date for which date do we want the fee?
|
||||
* @param[out] start_date when does the fee go into effect
|
||||
* @param[out] end_date when does the fee end being valid
|
||||
* @param[out] wire_fee how high is the wire transfer fee
|
||||
* @param[out] master_sig signature over the above by the exchange master key
|
||||
* @return #GNUNET_OK on success, #GNUNET_NO if no fee is known
|
||||
* #GNUNET_SYSERR on failure
|
||||
*/
|
||||
static int
|
||||
postgres_get_wire_fee (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const char *type,
|
||||
struct GNUNET_TIME_Absolute date,
|
||||
struct GNUNET_TIME_Absolute *start_date,
|
||||
struct GNUNET_TIME_Absolute *end_date,
|
||||
struct TALER_Amount *wire_fee,
|
||||
struct TALER_MasterSignatureP *master_sig)
|
||||
{
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_string (type),
|
||||
GNUNET_PQ_query_param_absolute_time (&date),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_absolute_time ("start_date", start_date),
|
||||
GNUNET_PQ_result_spec_absolute_time ("end_date", end_date),
|
||||
TALER_PQ_result_spec_amount ("wire_fee", wire_fee),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("master_sig", master_sig),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
PGresult *result;
|
||||
int nrows;
|
||||
|
||||
result = GNUNET_PQ_exec_prepared (session->conn,
|
||||
"get_wire_fee",
|
||||
params);
|
||||
if (PGRES_TUPLES_OK !=
|
||||
PQresultStatus (result))
|
||||
{
|
||||
BREAK_DB_ERR (result);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
nrows = PQntuples (result);
|
||||
if (0 == nrows)
|
||||
{
|
||||
/* no matches found */
|
||||
PQclear (result);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
if (1 != nrows)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result,
|
||||
rs,
|
||||
0))
|
||||
{
|
||||
PQclear (result);
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
PQclear (result);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert wire transfer fee into database.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param session database connection
|
||||
* @param type type of wire transfer this fee applies for
|
||||
* @param start_date when does the fee go into effect
|
||||
* @param end_date when does the fee end being valid
|
||||
* @param wire_fee how high is the wire transfer fee
|
||||
* @param master_sig signature over the above by the exchange master key
|
||||
* @return #GNUNET_OK on success, #GNUNET_NO if the record exists,
|
||||
* #GNUNET_SYSERR on failure
|
||||
*/
|
||||
static int
|
||||
postgres_insert_wire_fee (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const char *type,
|
||||
struct GNUNET_TIME_Absolute start_date,
|
||||
struct GNUNET_TIME_Absolute end_date,
|
||||
const struct TALER_Amount *wire_fee,
|
||||
const struct TALER_MasterSignatureP *master_sig)
|
||||
{
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_string (type),
|
||||
GNUNET_PQ_query_param_absolute_time (&start_date),
|
||||
GNUNET_PQ_query_param_absolute_time (&end_date),
|
||||
TALER_PQ_query_param_amount (wire_fee),
|
||||
GNUNET_PQ_query_param_auto_from_type (master_sig),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
PGresult *result;
|
||||
struct TALER_Amount wf;
|
||||
struct TALER_MasterSignatureP sig;
|
||||
struct GNUNET_TIME_Absolute sd;
|
||||
struct GNUNET_TIME_Absolute ed;
|
||||
|
||||
if (GNUNET_OK ==
|
||||
postgres_get_wire_fee (cls,
|
||||
session,
|
||||
type,
|
||||
start_date,
|
||||
&sd,
|
||||
&ed,
|
||||
&wf,
|
||||
&sig))
|
||||
{
|
||||
if (0 != memcmp (&sig,
|
||||
master_sig,
|
||||
sizeof (sig)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 != TALER_amount_cmp (wire_fee,
|
||||
&wf))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if ( (sd.abs_value_us != start_date.abs_value_us) ||
|
||||
(ed.abs_value_us != end_date.abs_value_us) )
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
/* equal record already exists */
|
||||
return GNUNET_NO;
|
||||
}
|
||||
|
||||
result = GNUNET_PQ_exec_prepared (session->conn,
|
||||
"insert_wire_fee",
|
||||
params);
|
||||
if (PGRES_COMMAND_OK != PQresultStatus (result))
|
||||
{
|
||||
BREAK_DB_ERR (result);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 != strcmp ("1", PQcmdTuples (result)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
PQclear (result);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called to insert wire transfer commit data into the DB.
|
||||
*
|
||||
@ -5090,6 +5322,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
|
||||
plugin->lookup_wire_transfer = &postgres_lookup_wire_transfer;
|
||||
plugin->wire_lookup_deposit_wtid = &postgres_wire_lookup_deposit_wtid;
|
||||
plugin->insert_aggregation_tracking = &postgres_insert_aggregation_tracking;
|
||||
plugin->insert_wire_fee = &postgres_insert_wire_fee;
|
||||
plugin->get_wire_fee = &postgres_get_wire_fee;
|
||||
plugin->wire_prepare_data_insert = &postgres_wire_prepare_data_insert;
|
||||
plugin->wire_prepare_data_mark_finished = &postgres_wire_prepare_data_mark_finished;
|
||||
plugin->wire_prepare_data_get = &postgres_wire_prepare_data_get;
|
||||
|
@ -783,6 +783,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
|
||||
static void
|
||||
cb_wt_never (void *cls,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const char *wire_method,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
struct GNUNET_TIME_Absolute exec_time,
|
||||
const struct GNUNET_HashCode *h_proposal_data,
|
||||
@ -825,6 +826,7 @@ static struct TALER_WireTransferIdentifierRawP wtid_wt;
|
||||
static void
|
||||
cb_wt_check (void *cls,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const char *wire_method,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
struct GNUNET_TIME_Absolute exec_time,
|
||||
const struct GNUNET_HashCode *h_proposal_data,
|
||||
@ -836,6 +838,8 @@ cb_wt_check (void *cls,
|
||||
GNUNET_assert (0 == memcmp (merchant_pub,
|
||||
&merchant_pub_wt,
|
||||
sizeof (struct TALER_MerchantPublicKeyP)));
|
||||
GNUNET_assert (0 == strcmp (wire_method,
|
||||
"SEPA"));
|
||||
GNUNET_assert (0 == memcmp (h_wire,
|
||||
&h_wire_wt,
|
||||
sizeof (struct GNUNET_HashCode)));
|
||||
|
@ -779,6 +779,19 @@ enum TALER_ErrorCode
|
||||
*/
|
||||
TALER_EC_TRACK_TRANSFER_WTID_NOT_FOUND = 1702,
|
||||
|
||||
/**
|
||||
* The exchange did not find information about the wire transfer
|
||||
* fees it charged. This response is
|
||||
* provided with HTTP status code MHD_HTTP_INTERNAL_SERVER_ERROR.
|
||||
*/
|
||||
TALER_EC_TRACK_TRANSFER_WIRE_FEE_NOT_FOUND = 1703,
|
||||
|
||||
/**
|
||||
* The exchange found a wire fee that was above the total transfer
|
||||
* value (and thus could not have been charged). This response is
|
||||
* provided with HTTP status code MHD_HTTP_INTERNAL_SERVER_ERROR.
|
||||
*/
|
||||
TALER_EC_TRACK_TRANSFER_WIRE_FEE_INCONSISTENT = 1704,
|
||||
|
||||
/**
|
||||
* The exchange found internally inconsistent fee data when
|
||||
@ -1145,7 +1158,7 @@ enum TALER_ErrorCode
|
||||
|
||||
/**
|
||||
* The backend encountered an error while trying to store the
|
||||
* h_proposal_data into the database.
|
||||
* h_proposal_data into the database.
|
||||
* The response is provided with HTTP status code MHD_HTTP_INTERNAL_SERVER_ERROR.
|
||||
*/
|
||||
TALER_EC_PROPOSAL_STORE_DB_ERROR = 2501,
|
||||
|
@ -1130,6 +1130,7 @@ struct TALER_EXCHANGE_TrackTransferHandle;
|
||||
* @param execution_time time when the exchange claims to have performed the wire transfer
|
||||
* @param total_amount total amount of the wire transfer, or NULL if the exchange could
|
||||
* not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK)
|
||||
* @param wire_fee wire fee that was charged by the exchange
|
||||
* @param details_length length of the @a details array
|
||||
* @param details array with details about the combined transactions
|
||||
*/
|
||||
@ -1142,6 +1143,7 @@ typedef void
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
struct GNUNET_TIME_Absolute execution_time,
|
||||
const struct TALER_Amount *total_amount,
|
||||
const struct TALER_Amount *wire_fee,
|
||||
unsigned int details_length,
|
||||
const struct TALER_TrackTransferDetails *details);
|
||||
|
||||
|
@ -762,6 +762,7 @@ typedef void
|
||||
*
|
||||
* @param cls closure
|
||||
* @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls)
|
||||
* @param wire_method which wire plugin was used for the transfer?
|
||||
* @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls)
|
||||
* @param exec_time execution time of the wire transfer (should be same for all callbacks with the same @e cls)
|
||||
* @param h_proposal_data which proposal was this payment about
|
||||
@ -772,6 +773,7 @@ typedef void
|
||||
typedef void
|
||||
(*TALER_EXCHANGEDB_WireTransferDataCallback)(void *cls,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const char *wire_method,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
struct GNUNET_TIME_Absolute exec_time,
|
||||
const struct GNUNET_HashCode *h_proposal_data,
|
||||
@ -1520,6 +1522,54 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
struct GNUNET_TIME_Absolute execution_time);
|
||||
|
||||
|
||||
/**
|
||||
* Insert wire transfer fee into database.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param session database connection
|
||||
* @param wire_method which wire method is the fee about?
|
||||
* @param start_date when does the fee go into effect
|
||||
* @param end_date when does the fee end being valid
|
||||
* @param wire_fee how high is the wire transfer fee
|
||||
* @param master_sig signature over the above by the exchange master key
|
||||
* @return #GNUNET_OK on success, #GNUNET_NO if the record exists,
|
||||
* #GNUNET_SYSERR on failure
|
||||
*/
|
||||
int
|
||||
(*insert_wire_fee)(void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const char *wire_method,
|
||||
struct GNUNET_TIME_Absolute start_date,
|
||||
struct GNUNET_TIME_Absolute end_date,
|
||||
const struct TALER_Amount *wire_fee,
|
||||
const struct TALER_MasterSignatureP *master_sig);
|
||||
|
||||
|
||||
/**
|
||||
* Obtain wire fee from database.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param session database connection
|
||||
* @param type type of wire transfer the fee applies for
|
||||
* @param date for which date do we want the fee?
|
||||
* @param[out] start_date when does the fee go into effect
|
||||
* @param[out] end_date when does the fee end being valid
|
||||
* @param[out] wire_fee how high is the wire transfer fee
|
||||
* @param[out] master_sig signature over the above by the exchange master key
|
||||
* @return #GNUNET_OK on success, #GNUNET_NO if no fee is known
|
||||
* #GNUNET_SYSERR on failure
|
||||
*/
|
||||
int
|
||||
(*get_wire_fee) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const char *type,
|
||||
struct GNUNET_TIME_Absolute date,
|
||||
struct GNUNET_TIME_Absolute *start_date,
|
||||
struct GNUNET_TIME_Absolute *end_date,
|
||||
struct TALER_Amount *wire_fee,
|
||||
struct TALER_MasterSignatureP *master_sig);
|
||||
|
||||
|
||||
/**
|
||||
* Function called to insert wire transfer commit data into the DB.
|
||||
*
|
||||
|
@ -1003,6 +1003,11 @@ struct TALER_WireDepositDataPS
|
||||
*/
|
||||
struct TALER_AmountNBO total;
|
||||
|
||||
/**
|
||||
* Wire fee that was charged.
|
||||
*/
|
||||
struct TALER_AmountNBO wire_fee;
|
||||
|
||||
/**
|
||||
* Public key of the merchant (for all aggregated transactions).
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user