towards changing timestamp in deposit confirmation (tests failing)

This commit is contained in:
Christian Grothoff 2020-05-07 20:22:02 +02:00
parent 0dfe7c23cb
commit 7217b8d065
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
25 changed files with 412 additions and 211 deletions

View File

@ -155,7 +155,7 @@ verify_and_execute_deposit_confirmation (
.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)),
.h_contract_terms = dc->h_contract_terms,
.h_wire = dc->h_wire,
.timestamp = GNUNET_TIME_absolute_hton (dc->timestamp),
.exchange_timestamp = GNUNET_TIME_absolute_hton (dc->exchange_timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (dc->refund_deadline),
.coin_pub = dc->coin_pub,
.merchant = dc->merchant
@ -224,7 +224,8 @@ TAH_DEPOSIT_CONFIRMATION_handler (struct TAH_RequestHandler *rh,
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &dc.h_contract_terms),
GNUNET_JSON_spec_fixed_auto ("h_wire", &dc.h_wire),
GNUNET_JSON_spec_absolute_time ("timestamp", &dc.timestamp),
GNUNET_JSON_spec_absolute_time ("exchange_timestamp",
&dc.exchange_timestamp),
GNUNET_JSON_spec_absolute_time ("refund_deadline", &dc.refund_deadline),
TALER_JSON_spec_amount ("amount_without_fee", &dc.amount_without_fee),
GNUNET_JSON_spec_fixed_auto ("coin_pub", &dc.coin_pub),

View File

@ -1535,7 +1535,8 @@ refresh_session_cb (void *cls,
*
* @param cls closure
* @param rowid unique serial ID for the deposit in our DB
* @param timestamp when did the deposit happen
* @param exchange_timestamp when did the exchange get the deposit
* @param wallet_timestamp when did the contract signing happen
* @param merchant_pub public key of the merchant
* @param denom_pub denomination public key of @a coin_pub
* @param coin_pub public key of the coin
@ -1553,7 +1554,8 @@ refresh_session_cb (void *cls,
static int
deposit_cb (void *cls,
uint64_t rowid,
struct GNUNET_TIME_Absolute timestamp,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@ -1611,7 +1613,7 @@ deposit_cb (void *cls,
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
.purpose.size = htonl (sizeof (dr)),
.h_contract_terms = *h_contract_terms,
.timestamp = GNUNET_TIME_absolute_hton (timestamp),
.wallet_timestamp = GNUNET_TIME_absolute_hton (wallet_timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
.deposit_fee = issue->fee_deposit,
.merchant = *merchant_pub,

View File

@ -114,11 +114,15 @@ test_dc (void *cls,
.h_wire = dc->h_wire,
.refund_deadline = dc->refund_deadline
};
struct GNUNET_TIME_Absolute exchange_timestamp;
struct TALER_Amount deposit_fee;
qs = TALER_ARL_edb->have_deposit (TALER_ARL_edb->cls,
TALER_ARL_esession,
&dep,
GNUNET_NO /* do not check refund deadline */);
GNUNET_NO /* do not check refund deadline */,
&deposit_fee,
&exchange_timestamp);
if (qs > 0)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@ -137,7 +141,8 @@ test_dc (void *cls,
TALER_ARL_report (report_deposit_confirmation_inconsistencies,
json_pack ("{s:o, s:o, s:I, s:o}",
"timestamp",
TALER_ARL_json_from_time_abs (dc->timestamp),
TALER_ARL_json_from_time_abs (
dc->exchange_timestamp),
"amount",
TALER_JSON_from_amount (&dc->amount_without_fee),
"rowid",

View File

@ -251,7 +251,7 @@ CREATE TABLE IF NOT EXISTS deposit_confirmations
,serial_id BIGSERIAL UNIQUE
,h_contract_terms BYTEA CHECK (LENGTH(h_contract_terms)=64)
,h_wire BYTEA CHECK (LENGTH(h_wire)=64)
,timestamp INT8 NOT NULL
,exchange_timestamp INT8 NOT NULL
,refund_deadline INT8 NOT NULL
,amount_without_fee_val INT8 NOT NULL
,amount_without_fee_frac INT4 NOT NULL

View File

@ -269,7 +269,7 @@ postgres_get_session (void *cls)
"(master_pub"
",h_contract_terms"
",h_wire"
",timestamp"
",exchange_timestamp"
",refund_deadline"
",amount_without_fee_val"
",amount_without_fee_frac"
@ -286,7 +286,7 @@ postgres_get_session (void *cls)
" serial_id"
",h_contract_terms"
",h_wire"
",timestamp"
",exchange_timestamp"
",refund_deadline"
",amount_without_fee_val"
",amount_without_fee_frac"
@ -1126,7 +1126,7 @@ postgres_insert_deposit_confirmation (
GNUNET_PQ_query_param_auto_from_type (&dc->master_public_key),
GNUNET_PQ_query_param_auto_from_type (&dc->h_contract_terms),
GNUNET_PQ_query_param_auto_from_type (&dc->h_wire),
TALER_PQ_query_param_absolute_time (&dc->timestamp),
TALER_PQ_query_param_absolute_time (&dc->exchange_timestamp),
TALER_PQ_query_param_absolute_time (&dc->refund_deadline),
TALER_PQ_query_param_amount (&dc->amount_without_fee),
GNUNET_PQ_query_param_auto_from_type (&dc->coin_pub),
@ -1207,8 +1207,8 @@ deposit_confirmation_cb (void *cls,
&dc.h_contract_terms),
GNUNET_PQ_result_spec_auto_from_type ("h_wire",
&dc.h_wire),
GNUNET_PQ_result_spec_absolute_time ("timestamp",
&dc.timestamp),
GNUNET_PQ_result_spec_absolute_time ("exchange_timestamp",
&dc.exchange_timestamp),
GNUNET_PQ_result_spec_absolute_time ("refund_deadline",
&dc.refund_deadline),
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_without_fee",

View File

@ -330,6 +330,8 @@ refund_by_coin_cb (void *cls,
*
* @param cls a `struct AggregationUnit`
* @param row_id identifies database entry
* @param exchange_timestamp when did the deposit happen
* @param wallet_timestamp when did the contract happen
* @param merchant_pub public key of the merchant
* @param coin_pub public key of the coin
* @param amount_with_fee amount that was deposited including fee
@ -343,6 +345,8 @@ refund_by_coin_cb (void *cls,
static enum GNUNET_DB_QueryStatus
deposit_cb (void *cls,
uint64_t row_id,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_Amount *amount_with_fee,
@ -358,6 +362,8 @@ deposit_cb (void *cls,
/* NOTE: potential optimization: use custom SQL API to not
fetch this one: */
(void) wire_deadline; /* already checked by SQL query */
(void) exchange_timestamp;
(void) wallet_timestamp;
au->merchant_pub = *merchant_pub;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Aggregator processing payment %s with amount %s\n",
@ -501,6 +507,8 @@ deposit_cb (void *cls,
*
* @param cls a `struct AggregationUnit`
* @param row_id identifies database entry
* @param exchange_timestamp when did the exchange receive the deposit
* @param wallet_timestamp when did the wallet sign the contract
* @param merchant_pub public key of the merchant
* @param coin_pub public key of the coin
* @param amount_with_fee amount that was deposited including fee
@ -514,6 +522,8 @@ deposit_cb (void *cls,
static enum GNUNET_DB_QueryStatus
aggregate_cb (void *cls,
uint64_t row_id,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_Amount *amount_with_fee,
@ -529,6 +539,8 @@ aggregate_cb (void *cls,
/* NOTE: potential optimization: use custom SQL API to not
fetch these: */
(void) wire_deadline; /* checked by SQL */
(void) exchange_timestamp;
(void) wallet_timestamp;
(void) wire; /* must match */
GNUNET_break (0 == GNUNET_memcmp (&au->merchant_pub,
merchant_pub));

View File

@ -47,7 +47,7 @@
* @param coin_pub public key of the coin
* @param h_wire hash of wire details
* @param h_contract_terms hash of contract details
* @param timestamp client's timestamp
* @param exchange_timestamp exchange's timestamp
* @param refund_deadline until when this deposit be refunded
* @param merchant merchant public key
* @param amount_without_fee fraction of coin value to deposit, without the fee
@ -58,7 +58,7 @@ reply_deposit_success (struct MHD_Connection *connection,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct GNUNET_HashCode *h_wire,
const struct GNUNET_HashCode *h_contract_terms,
struct GNUNET_TIME_Absolute timestamp,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute refund_deadline,
const struct TALER_MerchantPublicKeyP *merchant,
const struct TALER_Amount *amount_without_fee)
@ -70,7 +70,7 @@ reply_deposit_success (struct MHD_Connection *connection,
.purpose.size = htonl (sizeof (dc)),
.h_contract_terms = *h_contract_terms,
.h_wire = *h_wire,
.timestamp = GNUNET_TIME_absolute_hton (timestamp),
.exchange_timestamp = GNUNET_TIME_absolute_hton (exchange_timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
.coin_pub = *coin_pub,
.merchant = *merchant
@ -88,13 +88,16 @@ reply_deposit_success (struct MHD_Connection *connection,
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
"no keys");
}
return TALER_MHD_reply_json_pack (connection,
MHD_HTTP_OK,
"{s:o, s:o}",
"exchange_sig",
GNUNET_JSON_from_data_auto (&sig),
"exchange_pub",
GNUNET_JSON_from_data_auto (&pub));
return TALER_MHD_reply_json_pack (
connection,
MHD_HTTP_OK,
"{s:o, s:o, s:o}",
"exchange_timestamp",
GNUNET_JSON_from_time_abs (exchange_timestamp),
"exchange_sig",
GNUNET_JSON_from_data_auto (&sig),
"exchange_pub",
GNUNET_JSON_from_data_auto (&pub));
}
@ -108,6 +111,11 @@ struct DepositContext
*/
const struct TALER_EXCHANGEDB_Deposit *deposit;
/**
* Our timestamp (when we received the request).
*/
struct GNUNET_TIME_Absolute exchange_timestamp;
/**
* Value of the coin.
*/
@ -116,6 +124,74 @@ struct DepositContext
};
/**
* Check if /deposit is already in the database. IF it returns a non-error
* code, the transaction logic MUST NOT queue a MHD response. IF it returns
* an hard error, the transaction logic MUST queue a MHD response and set @a
* mhd_ret. We do return a "hard" error also if we found the deposit in the
* database and generated a regular response.
*
* @param cls a `struct DepositContext`
* @param connection MHD request context
* @param session database session and transaction to use
* @param[out] mhd_ret set to MHD status on error
* @return transaction status
*/
static enum GNUNET_DB_QueryStatus
deposit_precheck (void *cls,
struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session,
MHD_RESULT *mhd_ret)
{
struct DepositContext *dc = cls;
const struct TALER_EXCHANGEDB_Deposit *deposit = dc->deposit;
struct TALER_Amount deposit_fee;
enum GNUNET_DB_QueryStatus qs;
qs = TEH_plugin->have_deposit (TEH_plugin->cls,
session,
deposit,
GNUNET_YES /* check refund deadline */,
&deposit_fee,
&dc->exchange_timestamp);
if (qs < 0)
{
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{
*mhd_ret = TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_DEPOSIT_HISTORY_DB_ERROR,
"Could not check for existing identical deposit");
return GNUNET_DB_STATUS_HARD_ERROR;
}
return qs;
}
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
{
struct TALER_Amount amount_without_fee;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"/deposit replay, accepting again!\n");
GNUNET_assert (0 <=
TALER_amount_subtract (&amount_without_fee,
&deposit->amount_with_fee,
&deposit_fee));
*mhd_ret = reply_deposit_success (connection,
&deposit->coin.coin_pub,
&deposit->h_wire,
&deposit->h_contract_terms,
dc->exchange_timestamp,
deposit->refund_deadline,
&deposit->merchant_pub,
&amount_without_fee);
/* Treat as 'hard' DB error as we want to rollback and
never try again. */
return GNUNET_DB_STATUS_HARD_ERROR;
}
return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
}
/**
* Execute database transaction for /deposit. Runs the transaction
* logic; IF it returns a non-error code, the transaction logic MUST
@ -141,44 +217,15 @@ deposit_transaction (void *cls,
struct TALER_Amount spent;
enum GNUNET_DB_QueryStatus qs;
qs = TEH_plugin->have_deposit (TEH_plugin->cls,
session,
deposit,
GNUNET_YES /* check refund deadline */);
/* Theoretically, someone other threat may have received
and committed the deposit in the meantime. Check now
that we are in the transaction scope. */
qs = deposit_precheck (cls,
connection,
session,
mhd_ret);
if (qs < 0)
{
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{
*mhd_ret = TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_DEPOSIT_HISTORY_DB_ERROR,
"Could not check for existing identical deposit");
return GNUNET_DB_STATUS_HARD_ERROR;
}
return qs;
}
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
{
struct TALER_Amount amount_without_fee;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"/deposit replay, accepting again!\n");
GNUNET_assert (0 <=
TALER_amount_subtract (&amount_without_fee,
&deposit->amount_with_fee,
&deposit->deposit_fee));
*mhd_ret = reply_deposit_success (connection,
&deposit->coin.coin_pub,
&deposit->h_wire,
&deposit->h_contract_terms,
deposit->timestamp,
deposit->refund_deadline,
&deposit->merchant_pub,
&amount_without_fee);
/* Treat as 'hard' DB error as we want to rollback and
never try again. */
return GNUNET_DB_STATUS_HARD_ERROR;
}
/* Start with fee for THIS transaction */
spent = deposit->amount_with_fee;
@ -238,6 +285,7 @@ deposit_transaction (void *cls,
}
qs = TEH_plugin->insert_deposit (TEH_plugin->cls,
session,
dc->exchange_timestamp,
deposit);
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{
@ -251,45 +299,6 @@ deposit_transaction (void *cls,
}
/**
* Check that @a ts is reasonably close to our own RTC.
*
* @param ts timestamp to check
* @return #GNUNET_OK if @a ts is reasonable
*/
static int
check_timestamp_current (struct GNUNET_TIME_Absolute ts)
{
struct GNUNET_TIME_Relative r;
struct GNUNET_TIME_Relative tolerance;
/* Let's be VERY generous (after all, this is basically about
which year the deposit counts for in terms of tax purposes) */
tolerance = GNUNET_TIME_UNIT_MONTHS;
r = GNUNET_TIME_absolute_get_duration (ts);
if (r.rel_value_us > tolerance.rel_value_us)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Deposit timestamp too old: %llu vs %llu > %llu\n",
(unsigned long long) ts.abs_value_us,
(unsigned long long) GNUNET_TIME_absolute_get ().abs_value_us,
(unsigned long long) tolerance.rel_value_us);
return GNUNET_SYSERR;
}
r = GNUNET_TIME_absolute_get_remaining (ts);
if (r.rel_value_us > tolerance.rel_value_us)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Deposit timestamp too new: %llu vs %llu < - %llu\n",
(unsigned long long) ts.abs_value_us,
(unsigned long long) GNUNET_TIME_absolute_get ().abs_value_us,
(unsigned long long) tolerance.rel_value_us);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
/**
* Handle a "/coins/$COIN_PUB/deposit" request. Parses the JSON, and, if
* successful, passes the JSON data to #deposit_transaction() to
@ -367,17 +376,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
TALER_EC_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE,
"refund_deadline");
}
if (GNUNET_OK !=
check_timestamp_current (deposit.timestamp))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_DEPOSIT_INVALID_TIMESTAMP,
"timestamp");
}
if (GNUNET_OK !=
TALER_JSON_merchant_wire_signature_hash (wire,
&my_h_wire))
@ -401,6 +399,26 @@ TEH_handler_deposit (struct MHD_Connection *connection,
"h_wire");
}
/* Check for idempotency: did we get this request before? */
dc.deposit = &deposit;
{
MHD_RESULT mhd_ret;
if (GNUNET_OK !=
TEH_DB_run_transaction (connection,
"precheck deposit",
&mhd_ret,
&deposit_precheck,
&dc))
{
GNUNET_JSON_parse_free (spec);
return mhd_ret;
}
}
/* new deposit */
dc.exchange_timestamp = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&dc.exchange_timestamp);
/* check denomination exists and is valid */
{
struct TEH_KS_StateHandle *key_state;
@ -408,7 +426,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
enum TALER_ErrorCode ec;
unsigned int hc;
key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
key_state = TEH_KS_acquire (dc.exchange_timestamp);
if (NULL == key_state)
{
TALER_LOG_ERROR ("Lacking keys to operate\n");
@ -502,7 +520,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
.purpose.size = htonl (sizeof (dr)),
.h_contract_terms = deposit.h_contract_terms,
.h_wire = deposit.h_wire,
.timestamp = GNUNET_TIME_absolute_hton (deposit.timestamp),
.wallet_timestamp = GNUNET_TIME_absolute_hton (deposit.timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (deposit.refund_deadline),
.merchant = deposit.merchant_pub,
.coin_pub = deposit.coin.coin_pub
@ -528,7 +546,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
}
/* execute transaction */
dc.deposit = &deposit;
{
MHD_RESULT mhd_ret;
@ -557,7 +574,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
&deposit.coin.coin_pub,
&deposit.h_wire,
&deposit.h_contract_terms,
deposit.timestamp,
dc.exchange_timestamp,
deposit.refund_deadline,
&deposit.merchant_pub,
&amount_without_fee);

View File

@ -66,7 +66,7 @@ TEH_RESPONSE_compile_transaction_history (
.purpose.size = htonl (sizeof (dr)),
.h_contract_terms = deposit->h_contract_terms,
.h_wire = deposit->h_wire,
.timestamp = GNUNET_TIME_absolute_hton (deposit->timestamp),
.wallet_timestamp = GNUNET_TIME_absolute_hton (deposit->timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (
deposit->refund_deadline),
.merchant = deposit->merchant_pub,

View File

@ -254,7 +254,8 @@ CREATE TABLE IF NOT EXISTS deposits
,coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE
,amount_with_fee_val INT8 NOT NULL
,amount_with_fee_frac INT4 NOT NULL
,timestamp INT8 NOT NULL
,wallet_timestamp INT8 NOT NULL
,exchange_timestamp INT8 NOT NULL
,refund_deadline INT8 NOT NULL
,wire_deadline INT8 NOT NULL
,merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)

View File

@ -796,7 +796,7 @@ postgres_get_session (void *cls)
"(coin_pub"
",amount_with_fee_val"
",amount_with_fee_frac"
",timestamp"
",wallet_timestamp"
",refund_deadline"
",wire_deadline"
",merchant_pub"
@ -804,22 +804,28 @@ postgres_get_session (void *cls)
",h_wire"
",coin_sig"
",wire"
",exchange_timestamp"
") VALUES "
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
" $11);",
11),
" $11, $12);",
12),
/* Fetch an existing deposit request, used to ensure idempotency
during /deposit processing. Used in #postgres_have_deposit(). */
GNUNET_PQ_make_prepare ("get_deposit",
"SELECT"
" amount_with_fee_val"
",amount_with_fee_frac"
",timestamp"
",denominations.fee_deposit_val"
",denominations.fee_deposit_frac"
",wallet_timestamp"
",exchange_timestamp"
",refund_deadline"
",wire_deadline"
",h_contract_terms"
",h_wire"
" FROM deposits"
" JOIN known_coins USING (coin_pub)"
" JOIN denominations USING (denom_pub_hash)"
" WHERE ((coin_pub=$1)"
" AND (merchant_pub=$3)"
" AND (h_contract_terms=$2))"
@ -830,7 +836,8 @@ postgres_get_session (void *cls)
"SELECT"
" amount_with_fee_val"
",amount_with_fee_frac"
",timestamp"
",wallet_timestamp"
",exchange_timestamp"
",merchant_pub"
",denom.denom_pub"
",coin_pub"
@ -881,6 +888,8 @@ postgres_get_session (void *cls)
",wire"
",merchant_pub"
",coin_pub"
",exchange_timestamp"
",wallet_timestamp"
" FROM deposits"
" JOIN known_coins USING (coin_pub)"
" JOIN denominations denom USING (denom_pub_hash)"
@ -900,6 +909,8 @@ postgres_get_session (void *cls)
",denom.fee_deposit_val"
",denom.fee_deposit_frac"
",wire_deadline"
",exchange_timestamp"
",wallet_timestamp"
",h_contract_terms"
",coin_pub"
" FROM deposits"
@ -945,7 +956,7 @@ postgres_get_session (void *cls)
",amount_with_fee_frac"
",denom.fee_deposit_val"
",denom.fee_deposit_frac"
",timestamp"
",wallet_timestamp"
",refund_deadline"
",wire_deadline"
",merchant_pub"
@ -2571,6 +2582,8 @@ postgres_get_reserve_history (void *cls,
* @param session database connection
* @param deposit deposit to search for
* @param check_extras whether to check extra fields match or not
* @param[out] deposit_fee set to the deposit fee the exchange charged
* @param[out] exchange_timestamp set to the time when the exchange received the deposit
* @return 1 if we know this operation,
* 0 if this exact deposit is unknown to us,
* otherwise transaction error status
@ -2579,7 +2592,9 @@ static enum GNUNET_DB_QueryStatus
postgres_have_deposit (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct TALER_EXCHANGEDB_Deposit *deposit,
int check_extras)
int check_extras,
struct TALER_Amount *deposit_fee,
struct GNUNET_TIME_Absolute *exchange_timestamp)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
@ -2592,12 +2607,16 @@ postgres_have_deposit (void *cls,
struct GNUNET_PQ_ResultSpec rs[] = {
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
&deposit2.amount_with_fee),
TALER_PQ_result_spec_absolute_time ("timestamp",
TALER_PQ_result_spec_absolute_time ("wallet_timestamp",
&deposit2.timestamp),
TALER_PQ_result_spec_absolute_time ("exchange_timestamp",
exchange_timestamp),
TALER_PQ_result_spec_absolute_time ("refund_deadline",
&deposit2.refund_deadline),
TALER_PQ_result_spec_absolute_time ("wire_deadline",
&deposit2.wire_deadline),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
deposit_fee),
GNUNET_PQ_result_spec_auto_from_type ("h_wire",
&deposit2.h_wire),
GNUNET_PQ_result_spec_end
@ -2776,6 +2795,8 @@ postgres_get_ready_deposit (void *cls,
struct TALER_Amount amount_with_fee;
struct TALER_Amount deposit_fee;
struct GNUNET_TIME_Absolute wire_deadline;
struct GNUNET_TIME_Absolute wallet_timestamp;
struct GNUNET_TIME_Absolute exchange_timestamp;
struct GNUNET_HashCode h_contract_terms;
struct TALER_MerchantPublicKeyP merchant_pub;
struct TALER_CoinSpendPublicKeyP coin_pub;
@ -2788,6 +2809,10 @@ postgres_get_ready_deposit (void *cls,
&amount_with_fee),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
&deposit_fee),
TALER_PQ_result_spec_absolute_time ("exchange_timestamp",
&exchange_timestamp),
TALER_PQ_result_spec_absolute_time ("wallet_timestamp",
&wallet_timestamp),
TALER_PQ_result_spec_absolute_time ("wire_deadline",
&wire_deadline),
GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
@ -2817,6 +2842,8 @@ postgres_get_ready_deposit (void *cls,
qs = deposit_cb (deposit_cb_cls,
serial_id,
exchange_timestamp,
wallet_timestamp,
&merchant_pub,
&coin_pub,
&amount_with_fee,
@ -2898,6 +2925,8 @@ match_deposit_cb (void *cls,
{
struct TALER_Amount amount_with_fee;
struct TALER_Amount deposit_fee;
struct GNUNET_TIME_Absolute exchange_timestamp;
struct GNUNET_TIME_Absolute wallet_timestamp;
struct GNUNET_TIME_Absolute wire_deadline;
struct GNUNET_HashCode h_contract_terms;
struct TALER_CoinSpendPublicKeyP coin_pub;
@ -2912,6 +2941,10 @@ match_deposit_cb (void *cls,
&deposit_fee),
TALER_PQ_result_spec_absolute_time ("wire_deadline",
&wire_deadline),
TALER_PQ_result_spec_absolute_time ("exchange_timestamp",
&exchange_timestamp),
TALER_PQ_result_spec_absolute_time ("wallet_timestamp",
&wallet_timestamp),
GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
&h_contract_terms),
GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
@ -2930,6 +2963,8 @@ match_deposit_cb (void *cls,
}
qs = mdc->deposit_cb (mdc->deposit_cb_cls,
serial_id,
exchange_timestamp,
wallet_timestamp,
mdc->merchant_pub,
&coin_pub,
&amount_with_fee,
@ -3210,12 +3245,14 @@ postgres_ensure_coin_known (void *cls,
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param session connection to the database
* @param exchange_timestamp time the exchange received the deposit request
* @param deposit deposit information to store
* @return query result status
*/
static enum GNUNET_DB_QueryStatus
postgres_insert_deposit (void *cls,
struct TALER_EXCHANGEDB_Session *session,
struct GNUNET_TIME_Absolute exchange_timestamp,
const struct TALER_EXCHANGEDB_Deposit *deposit)
{
struct GNUNET_PQ_QueryParam params[] = {
@ -3229,6 +3266,7 @@ postgres_insert_deposit (void *cls,
GNUNET_PQ_query_param_auto_from_type (&deposit->h_wire),
GNUNET_PQ_query_param_auto_from_type (&deposit->csig),
TALER_PQ_query_param_json (deposit->receiver_wire_account),
TALER_PQ_query_param_absolute_time (&exchange_timestamp),
GNUNET_PQ_query_param_end
};
@ -4042,7 +4080,7 @@ add_coin_deposit (void *cls,
&deposit->amount_with_fee),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
&deposit->deposit_fee),
TALER_PQ_result_spec_absolute_time ("timestamp",
TALER_PQ_result_spec_absolute_time ("wallet_timestamp",
&deposit->timestamp),
TALER_PQ_result_spec_absolute_time ("refund_deadline",
&deposit->refund_deadline),
@ -5462,14 +5500,17 @@ deposit_serial_helper_cb (void *cls,
for (unsigned int i = 0; i<num_results; i++)
{
struct TALER_EXCHANGEDB_Deposit deposit;
struct GNUNET_TIME_Absolute exchange_timestamp;
struct TALER_DenominationPublicKey denom_pub;
uint8_t done = 0;
uint64_t rowid;
struct GNUNET_PQ_ResultSpec rs[] = {
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
&deposit.amount_with_fee),
TALER_PQ_result_spec_absolute_time ("timestamp",
TALER_PQ_result_spec_absolute_time ("wallet_timestamp",
&deposit.timestamp),
TALER_PQ_result_spec_absolute_time ("exchange_timestamp",
&exchange_timestamp),
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
&deposit.merchant_pub),
GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
@ -5505,6 +5546,7 @@ deposit_serial_helper_cb (void *cls,
}
ret = dsc->cb (dsc->cb_cls,
rowid,
exchange_timestamp,
deposit.timestamp,
&deposit.merchant_pub,
&denom_pub,

View File

@ -833,6 +833,8 @@ static uint64_t deposit_rowid;
* @param cls closure a `struct TALER_EXCHANGEDB_Deposit *`
* @param rowid unique ID for the deposit in our DB, used for marking
* it as 'tiny' or 'done'
* @param exchange_timestamp when did the deposit happen
* @param wallet_timestamp when did the wallet sign the contract
* @param merchant_pub public key of the merchant
* @param coin_pub public key of the coin
* @param amount_with_fee amount that was deposited including fee
@ -846,6 +848,8 @@ static uint64_t deposit_rowid;
static enum GNUNET_DB_QueryStatus
deposit_cb (void *cls,
uint64_t rowid,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_Amount *amount_with_fee,
@ -890,7 +894,8 @@ deposit_cb (void *cls,
*
* @param cls closure
* @param rowid unique serial ID for the deposit in our DB
* @param timestamp when did the deposit happen
* @param exchange_timestamp when did the deposit happen
* @param wallet_timestamp when did the wallet sign the contract
* @param merchant_pub public key of the merchant
* @param denom_pub denomination of the @a coin_pub
* @param coin_pub public key of the coin
@ -908,7 +913,8 @@ deposit_cb (void *cls,
static int
audit_deposit_cb (void *cls,
uint64_t rowid,
struct GNUNET_TIME_Absolute timestamp,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@ -1878,15 +1884,27 @@ run (void *cls)
plugin->ensure_coin_known (plugin->cls,
session,
&deposit.coin));
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->insert_deposit (plugin->cls,
{
struct GNUNET_TIME_Absolute now;
struct GNUNET_TIME_Absolute r;
struct TALER_Amount deposit_fee;
now = GNUNET_TIME_absolute_get ();
GNUNET_TIME_round_abs (&now);
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->insert_deposit (plugin->cls,
session,
now,
&deposit));
FAILIF (1 !=
plugin->have_deposit (plugin->cls,
session,
&deposit));
FAILIF (1 !=
plugin->have_deposit (plugin->cls,
session,
&deposit,
GNUNET_YES));
&deposit,
GNUNET_YES,
&deposit_fee,
&r));
FAILIF (now.abs_value_us != r.abs_value_us);
}
{
struct GNUNET_TIME_Absolute start_range;
struct GNUNET_TIME_Absolute end_range;
@ -1983,18 +2001,27 @@ run (void *cls)
session,
"test-2"));
RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
plugin->have_deposit (plugin->cls,
session,
&deposit2,
GNUNET_YES));
deposit2.merchant_pub = deposit.merchant_pub;
RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
plugin->have_deposit (plugin->cls,
session,
&deposit2,
GNUNET_YES));
{
struct GNUNET_TIME_Absolute r;
struct TALER_Amount deposit_fee;
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
plugin->have_deposit (plugin->cls,
session,
&deposit2,
GNUNET_YES,
&deposit_fee,
&r));
deposit2.merchant_pub = deposit.merchant_pub;
RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
plugin->have_deposit (plugin->cls,
session,
&deposit2,
GNUNET_YES,
&deposit_fee,
&r));
}
FAILIF (GNUNET_OK !=
test_melting (session));
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=

View File

@ -300,9 +300,9 @@ struct TALER_AUDITORDB_DepositConfirmation
struct GNUNET_HashCode h_wire;
/**
* Time when this confirmation was generated.
* Time when this deposit confirmation was generated by the exchange.
*/
struct GNUNET_TIME_Absolute timestamp;
struct GNUNET_TIME_Absolute exchange_timestamp;
/**
* How much time does the @e merchant have to issue a refund

View File

@ -1542,73 +1542,92 @@ enum TALER_ErrorCode
* This response is provided with HTTP status code
* #MHD_HTTP_SERVICE_UNAVAILABLE.
*/
TALER_EC_TRACK_TRANSFER_EXCHANGE_TIMEOUT = 2400,
TALER_EC_POST_TRANSFERS_EXCHANGE_TIMEOUT = 2400,
/**
* We failed to obtain an acceptable /keys response from the exchange
* for the /track/transfer request. This response is provided with
* HTTP status code #MHD_HTTP_FAILED_DEPENDENCY.
*/
TALER_EC_TRACK_TRANSFER_EXCHANGE_KEYS_FAILURE = 2401,
TALER_EC_POST_TRANSFERS_EXCHANGE_KEYS_FAILURE = 2401,
/**
* We failed to persist coin wire transfer information in our merchant
* database. The response is provided with HTTP status code
* #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
TALER_EC_TRACK_TRANSFER_DB_STORE_COIN_ERROR = 2402,
TALER_EC_POST_TRANSFERS_DB_STORE_COIN_ERROR = 2402,
/**
* We internally failed to execute the /track/transfer request. The
* response is provided with HTTP status code
* #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
TALER_EC_TRACK_TRANSFER_REQUEST_ERROR = 2403,
TALER_EC_POST_TRANSFERS_REQUEST_ERROR = 2403,
/**
* We failed to persist wire transfer information in our merchant
* database. The response is provided with HTTP status code
* #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
TALER_EC_TRACK_TRANSFER_DB_STORE_TRANSFER_ERROR = 2404,
TALER_EC_POST_TRANSFERS_DB_STORE_TRANSFER_ERROR = 2404,
/**
* The exchange returned an error from /track/transfer. The response
* is provided with HTTP status code #MHD_HTTP_FAILED_DEPENDENCY.
*/
TALER_EC_TRACK_TRANSFER_EXCHANGE_ERROR = 2405,
TALER_EC_POST_TRANSFERS_EXCHANGE_ERROR = 2405,
/**
* We failed to fetch deposit information from our merchant database.
* The response is provided with HTTP status code
* #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
TALER_EC_TRACK_TRANSFER_DB_FETCH_DEPOSIT_ERROR = 2406,
TALER_EC_POST_TRANSFERS_DB_FETCH_DEPOSIT_ERROR = 2406,
/**
* We encountered an internal logic error. The response is provided
* with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
TALER_EC_TRACK_TRANSFER_DB_INTERNAL_LOGIC_ERROR = 2407,
TALER_EC_POST_TRANSFERS_DB_INTERNAL_LOGIC_ERROR = 2407,
/**
* The exchange gave conflicting information about a coin which has
* been wire transferred. The response is provided with HTTP status
* code #MHD_HTTP_FAILED_DEPENDENCY.
*/
TALER_EC_TRACK_TRANSFER_CONFLICTING_REPORTS = 2408,
TALER_EC_POST_TRANSFERS_CONFLICTING_REPORTS = 2408,
/**
* The merchant backend had problems in creating the JSON response.
*/
TALER_EC_TRACK_TRANSFER_JSON_RESPONSE_ERROR = 2409,
TALER_EC_POST_TRANSFERS_JSON_RESPONSE_ERROR = 2409,
/**
* The exchange charged a different wire fee than what it originally
* advertised, and it is higher. The response is provied with an HTTP
* status of #MHD_HTTP_FAILED_DEPENDENCY.
* advertised, and it is higher. The response is provided with an
* HTTP status of #MHD_HTTP_FAILED_DEPENDENCY.
*/
TALER_EC_TRACK_TRANSFER_JSON_BAD_WIRE_FEE = 2410,
TALER_EC_POST_TRANSFERS_JSON_BAD_WIRE_FEE = 2410,
/**
* We did not find the account that the transfer was made to. The
* response is provided with an HTTP status of #MHD_HTTP_NOT_FOUND.
*/
TALER_EC_POST_TRANSFERS_ACCOUNT_NOT_FOUND = 2411,
/**
* We did failed to store information in our database. The response is
* provided with an HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
TALER_EC_POST_TRANSFERS_DB_STORE_ERROR = 2412,
/**
* We did failed to retrieve information from our database. The
* response is provided with an HTTP status of
* #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
TALER_EC_POST_TRANSFERS_DB_LOOKUP_ERROR = 2413,
/**
* The merchant backend cannot create an instance under the given

View File

@ -756,6 +756,7 @@ struct TALER_EXCHANGE_DepositHandle;
*
* @param cls closure
* @param hr HTTP response data
* @param deposit_timestamp time when the exchange generated the deposit confirmation
* @param exchange_sig signature provided by the exchange
* @param exchange_pub exchange key used to sign @a obj, or NULL
*/
@ -763,6 +764,7 @@ typedef void
(*TALER_EXCHANGE_DepositResultCallback) (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
struct GNUNET_TIME_Absolute deposit_timestamp,
const struct TALER_ExchangeSignatureP *exchange_sig,
const struct TALER_ExchangePublicKeyP *exchange_pub);

View File

@ -975,6 +975,8 @@ struct TALER_EXCHANGEDB_Session;
* @param cls closure
* @param rowid unique ID for the deposit in our DB, used for marking
* it as 'tiny' or 'done'
* @param exchange_timestamp when did the exchange receive the deposit
* @param wallet_timestamp when did the wallet sign the contract
* @param merchant_pub public key of the merchant
* @param coin_pub public key of the coin
* @param amount_with_fee amount that was deposited including fee
@ -990,6 +992,8 @@ typedef enum GNUNET_DB_QueryStatus
(*TALER_EXCHANGEDB_DepositIterator)(
void *cls,
uint64_t rowid,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_Amount *amount_with_fee,
@ -1022,7 +1026,8 @@ typedef void
*
* @param cls closure
* @param rowid unique serial ID for the deposit in our DB
* @param timestamp when did the deposit happen
* @param exchange_timestamp when did the deposit happen
* @param wallet_timestamp when did the contract happen
* @param merchant_pub public key of the merchant
* @param denom_pub denomination public key of @a coin_pub
* @param coin_pub public key of the coin
@ -1042,7 +1047,8 @@ typedef int
(*TALER_EXCHANGEDB_DepositCallback)(
void *cls,
uint64_t rowid,
struct GNUNET_TIME_Absolute timestamp,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@ -1841,6 +1847,8 @@ struct TALER_EXCHANGEDB_Plugin
* @param session database connection
* @param deposit deposit to search for
* @param check_extras whether to check extra fields or not
* @param[out] deposit_fee set to the deposit fee the exchange charged
* @param[out] exchange_timestamp set to the time when the exchange received the deposit
* @return 1 if we know this operation,
* 0 if this exact deposit is unknown to us,
* otherwise transaction error status
@ -1849,7 +1857,9 @@ struct TALER_EXCHANGEDB_Plugin
(*have_deposit)(void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct TALER_EXCHANGEDB_Deposit *deposit,
int check_extras);
int check_extras,
struct TALER_Amount *deposit_fee,
struct GNUNET_TIME_Absolute *exchange_timestamp);
/**
@ -1857,12 +1867,14 @@ struct TALER_EXCHANGEDB_Plugin
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param session connection to the database
* @param exchange_timestamp time the exchange received the deposit request
* @param deposit deposit information to store
* @return query result status
*/
enum GNUNET_DB_QueryStatus
(*insert_deposit)(void *cls,
struct TALER_EXCHANGEDB_Session *session,
struct GNUNET_TIME_Absolute exchange_timestamp,
const struct TALER_EXCHANGEDB_Deposit *deposit);

View File

@ -363,7 +363,7 @@ struct TALER_DepositRequestPS
* deposit request in a timely fashion (so back-dating is not
* prevented).
*/
struct GNUNET_TIME_AbsoluteNBO timestamp;
struct GNUNET_TIME_AbsoluteNBO wallet_timestamp;
/**
* How much time does the merchant have to issue a refund request?
@ -429,9 +429,10 @@ struct TALER_DepositConfirmationPS
struct GNUNET_HashCode h_wire GNUNET_PACKED;
/**
* Time when this confirmation was generated.
* Time when this confirmation was generated / when the exchange received
* the deposit request.
*/
struct GNUNET_TIME_AbsoluteNBO timestamp;
struct GNUNET_TIME_AbsoluteNBO exchange_timestamp;
/**
* How much time does the @e merchant have to issue a refund

View File

@ -1903,6 +1903,7 @@ TALER_TESTING_cmd_connect_with_state (const char *label,
* @param dbc collects plugin and session handles
* @param merchant_name Human-readable name of the merchant.
* @param merchant_account merchant's account name (NOT a payto:// URI)
* @param exchange_timestamp when did the exchange receive the deposit
* @param wire_deadline point in time where the aggregator should have
* wired money to the merchant.
* @param amount_with_fee amount to deposit (inclusive of deposit fee)
@ -1910,14 +1911,15 @@ TALER_TESTING_cmd_connect_with_state (const char *label,
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_insert_deposit (const char *label,
const struct
TALER_TESTING_DatabaseConnection *dbc,
const char *merchant_name,
const char *merchant_account,
struct GNUNET_TIME_Relative wire_deadline,
const char *amount_with_fee,
const char *deposit_fee);
TALER_TESTING_cmd_insert_deposit (
const char *label,
const struct TALER_TESTING_DatabaseConnection *dbc,
const char *merchant_name,
const char *merchant_account,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Relative wire_deadline,
const char *amount_with_fee,
const char *deposit_fee);
/**

View File

@ -148,7 +148,7 @@ handle_deposit_confirmation_finished (void *cls,
*
* @param h_wire hash of merchant wire details
* @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the auditor)
* @param timestamp timestamp when the contract was finalized, must not be too far in the future
* @param exchange_timestamp timestamp when the deposit was received by the wallet
* @param refund_deadline date until which the merchant can issue a refund to the customer via the auditor (can be zero if refunds are not allowed); must not be after the @a wire_deadline
* @param amount_without_fee the amount confirmed to be wired by the exchange to the merchant
* @param coin_pub coins public key
@ -165,7 +165,7 @@ handle_deposit_confirmation_finished (void *cls,
static int
verify_signatures (const struct GNUNET_HashCode *h_wire,
const struct GNUNET_HashCode *h_contract_terms,
struct GNUNET_TIME_Absolute timestamp,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute refund_deadline,
const struct TALER_Amount *amount_without_fee,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@ -184,7 +184,7 @@ verify_signatures (const struct GNUNET_HashCode *h_wire,
.purpose.size = htonl (sizeof (dc)),
.h_contract_terms = *h_contract_terms,
.h_wire = *h_wire,
.timestamp = GNUNET_TIME_absolute_hton (timestamp),
.exchange_timestamp = GNUNET_TIME_absolute_hton (exchange_timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
.coin_pub = *coin_pub,
.merchant = *merchant_pub
@ -256,7 +256,7 @@ verify_signatures (const struct GNUNET_HashCode *h_wire,
* @param auditor the auditor handle; the auditor must be ready to operate
* @param h_wire hash of merchant wire details
* @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the auditor)
* @param timestamp timestamp when the contract was finalized, must not be too far in the future
* @param exchange_timestamp timestamp when deposit was received by the exchange
* @param refund_deadline date until which the merchant can issue a refund to the customer via the auditor (can be zero if refunds are not allowed); must not be after the @a wire_deadline
* @param amount_without_fee the amount confirmed to be wired by the exchange to the merchant
* @param coin_pub coins public key
@ -278,7 +278,7 @@ TALER_AUDITOR_deposit_confirmation (
struct TALER_AUDITOR_Handle *auditor,
const struct GNUNET_HashCode *h_wire,
const struct GNUNET_HashCode *h_contract_terms,
struct GNUNET_TIME_Absolute timestamp,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute refund_deadline,
const struct TALER_Amount *amount_without_fee,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@ -298,7 +298,7 @@ TALER_AUDITOR_deposit_confirmation (
json_t *deposit_confirmation_obj;
CURL *eh;
(void) GNUNET_TIME_round_abs (&timestamp);
(void) GNUNET_TIME_round_abs (&exchange_timestamp);
(void) GNUNET_TIME_round_abs (&refund_deadline);
(void) GNUNET_TIME_round_abs (&ep_start);
(void) GNUNET_TIME_round_abs (&ep_expire);
@ -308,7 +308,7 @@ TALER_AUDITOR_deposit_confirmation (
if (GNUNET_OK !=
verify_signatures (h_wire,
h_contract_terms,
timestamp,
exchange_timestamp,
refund_deadline,
amount_without_fee,
coin_pub,
@ -336,7 +336,8 @@ TALER_AUDITOR_deposit_confirmation (
"h_wire", GNUNET_JSON_from_data_auto (h_wire),
"h_contract_terms", GNUNET_JSON_from_data_auto (
h_contract_terms),
"timestamp", GNUNET_JSON_from_time_abs (timestamp),
"exchange_timestamp", GNUNET_JSON_from_time_abs (
exchange_timestamp),
"refund_deadline", GNUNET_JSON_from_time_abs (refund_deadline),
"amount_without_fee", TALER_JSON_from_amount (
amount_without_fee),

View File

@ -524,7 +524,7 @@ TALER_EXCHANGE_verify_coin_history (
GNUNET_JSON_spec_fixed_auto ("h_wire",
&dr.h_wire),
GNUNET_JSON_spec_absolute_time_nbo ("timestamp",
&dr.timestamp),
&dr.wallet_timestamp),
GNUNET_JSON_spec_absolute_time_nbo ("refund_deadline",
&dr.refund_deadline),
TALER_JSON_spec_amount_nbo ("deposit_fee",

View File

@ -160,7 +160,7 @@ auditor_cb (void *cls,
ah,
&dh->depconf.h_wire,
&dh->depconf.h_contract_terms,
GNUNET_TIME_absolute_ntoh (dh->depconf.timestamp),
GNUNET_TIME_absolute_ntoh (dh->depconf.exchange_timestamp),
GNUNET_TIME_absolute_ntoh (dh->depconf.refund_deadline),
&amount_without_fee,
&dh->depconf.coin_pub,
@ -198,6 +198,8 @@ verify_deposit_signature_ok (struct TALER_EXCHANGE_DepositHandle *dh,
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("exchange_sig", exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub", exchange_pub),
GNUNET_JSON_spec_absolute_time_nbo ("exchange_timestamp",
&dh->depconf.exchange_timestamp),
GNUNET_JSON_spec_end ()
};
@ -386,6 +388,7 @@ handle_deposit_finished (void *cls,
}
dh->cb (dh->cb_cls,
&hr,
GNUNET_TIME_absolute_ntoh (dh->depconf.exchange_timestamp),
es,
ep);
TALER_EXCHANGE_deposit_cancel (dh);
@ -429,7 +432,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
.purpose.size = htonl (sizeof (dr)),
.h_contract_terms = *h_contract_terms,
.h_wire = *h_wire,
.timestamp = GNUNET_TIME_absolute_hton (timestamp),
.wallet_timestamp = GNUNET_TIME_absolute_hton (timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
.merchant = *merchant_pub,
.coin_pub = *coin_pub
@ -658,7 +661,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange,
TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT);
dh->depconf.h_contract_terms = *h_contract_terms;
dh->depconf.h_wire = h_wire;
dh->depconf.timestamp = GNUNET_TIME_absolute_hton (timestamp);
/* dh->depconf.exchange_timestamp; -- initialized later from exchange reply! */
dh->depconf.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
TALER_amount_hton (&dh->depconf.amount_without_fee,
&amount_without_fee);

View File

@ -148,7 +148,8 @@ handle_refund_finished (void *cls,
struct TALER_ExchangeSignatureP exchange_sig;
struct TALER_ExchangePublicKeyP *ep = NULL;
struct TALER_ExchangeSignatureP *es = NULL;
struct TALER_Amount *rf = NULL;
struct TALER_Amount ra;
const struct TALER_Amount *rf = NULL;
const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
@ -176,7 +177,9 @@ handle_refund_finished (void *cls,
{
ep = &exchange_pub;
es = &exchange_sig;
rf = &rh->depconf.refund_fee;
TALER_amount_ntoh (&ra,
&rh->depconf.refund_fee);
rf = &ra;
}
break;
case MHD_HTTP_BAD_REQUEST:

View File

@ -108,6 +108,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@ -126,6 +127,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@ -134,6 +136,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@ -153,6 +156,7 @@ run (void *cls,
&dbc,
"bob",
"4",
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@ -160,6 +164,7 @@ run (void *cls,
&dbc,
"bob",
"5",
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@ -167,6 +172,7 @@ run (void *cls,
&dbc,
"alice",
"4",
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@ -195,6 +201,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@ -204,6 +211,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@ -229,6 +237,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
10),
@ -239,6 +248,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@ -263,6 +273,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.102",
"EUR:0.1"),
@ -274,6 +285,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.102",
"EUR:0.1"),
@ -281,6 +293,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.102",
"EUR:0.1"),
@ -292,6 +305,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.102",
"EUR:0.1"),
@ -303,6 +317,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.112",
"EUR:0.1"),
@ -319,6 +334,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.109",
"EUR:0.1"),
@ -330,6 +346,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.119",
"EUR:0.1"),
@ -346,6 +363,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.122",
"EUR:0.1"),
@ -362,6 +380,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@ -375,6 +394,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@ -390,6 +410,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.122",
"EUR:0.1"),
@ -406,6 +427,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@ -419,6 +441,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@ -434,6 +457,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.112",
"EUR:0.1"),

View File

@ -203,6 +203,7 @@ deposit_confirmation_run (void *cls,
const struct TALER_TESTING_Command *deposit_cmd;
struct GNUNET_HashCode h_wire;
struct GNUNET_HashCode h_contract_terms;
const struct GNUNET_TIME_Absolute *exchange_timestamp = NULL;
struct GNUNET_TIME_Absolute timestamp;
struct GNUNET_TIME_Absolute refund_deadline;
struct TALER_Amount amount_without_fee;
@ -238,6 +239,11 @@ deposit_confirmation_run (void *cls,
TALER_TESTING_get_trait_exchange_sig (deposit_cmd,
dcs->coin_index,
&exchange_sig));
GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_absolute_time (deposit_cmd,
dcs->coin_index,
&exchange_timestamp));
GNUNET_assert (NULL != exchange_timestamp);
keys = TALER_EXCHANGE_get_keys (dcs->is->exchange);
GNUNET_assert (NULL != keys);
spk = TALER_EXCHANGE_get_signing_key_info (keys,
@ -309,7 +315,7 @@ deposit_confirmation_run (void *cls,
dcs->dc = TALER_AUDITOR_deposit_confirmation (dcs->auditor,
&h_wire,
&h_contract_terms,
timestamp,
*exchange_timestamp,
refund_deadline,
&amount_without_fee,
&coin_pub,

View File

@ -91,9 +91,9 @@ struct DepositState
struct TALER_EXCHANGE_DepositHandle *dh;
/**
* Timestamp of the /deposit operation.
* Timestamp of the /deposit operation in the wallet (contract signing time).
*/
struct GNUNET_TIME_Absolute timestamp;
struct GNUNET_TIME_Absolute wallet_timestamp;
/**
* Interpreter state.
@ -126,6 +126,11 @@ struct DepositState
*/
int deposit_succeeded;
/**
* When did the exchange receive the deposit?
*/
struct GNUNET_TIME_Absolute exchange_timestamp;
/**
* Signing key used by the exchange to sign the
* deposit confirmation.
@ -198,6 +203,7 @@ do_retry (void *cls)
*
* @param cls closure.
* @param hr HTTP response details
* @param exchange_timestamp when did the exchange receive the deposit permission
* @param exchange_sig signature provided by the exchange
* (NULL on errors)
* @param exchange_pub public key of the exchange,
@ -206,6 +212,7 @@ do_retry (void *cls)
static void
deposit_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct GNUNET_TIME_Absolute exchange_timestamp,
const struct TALER_ExchangeSignatureP *exchange_sig,
const struct TALER_ExchangePublicKeyP *exchange_pub)
{
@ -254,6 +261,7 @@ deposit_cb (void *cls,
if (MHD_HTTP_OK == hr->http_status)
{
ds->deposit_succeeded = GNUNET_YES;
ds->exchange_timestamp = exchange_timestamp;
ds->exchange_pub = *exchange_pub;
ds->exchange_sig = *exchange_sig;
}
@ -305,7 +313,7 @@ deposit_run (void *cls,
ds->coin_index = ods->coin_index;
ds->wire_details = json_incref (ods->wire_details);
ds->contract_terms = json_incref (ods->contract_terms);
ds->timestamp = ods->timestamp;
ds->wallet_timestamp = ods->wallet_timestamp;
ds->refund_deadline = ods->refund_deadline;
ds->amount = ods->amount;
ds->merchant_priv = ods->merchant_priv;
@ -379,7 +387,7 @@ deposit_run (void *cls,
}
else
{
ds->refund_deadline = ds->timestamp;
ds->refund_deadline = ds->wallet_timestamp;
wire_deadline = GNUNET_TIME_relative_to_absolute
(GNUNET_TIME_UNIT_ZERO);
}
@ -388,6 +396,7 @@ deposit_run (void *cls,
(void) GNUNET_TIME_round_abs (&wire_deadline);
// FIXME: This should be part of TALER_EXCHANGE_deposit()!
{
struct TALER_DepositRequestPS dr;
@ -400,7 +409,7 @@ deposit_run (void *cls,
GNUNET_assert (GNUNET_OK ==
TALER_JSON_merchant_wire_signature_hash (ds->wire_details,
&dr.h_wire));
dr.timestamp = GNUNET_TIME_absolute_hton (ds->timestamp);
dr.wallet_timestamp = GNUNET_TIME_absolute_hton (ds->wallet_timestamp);
dr.refund_deadline = GNUNET_TIME_absolute_hton
(ds->refund_deadline);
TALER_amount_hton (&dr.amount_with_fee,
@ -421,7 +430,7 @@ deposit_run (void *cls,
&coin_pub,
denom_pub_sig,
&denom_pub->key,
ds->timestamp,
ds->wallet_timestamp,
&merchant_pub,
ds->refund_deadline,
&coin_sig,
@ -534,6 +543,8 @@ deposit_traits (void *cls,
&ds->merchant_priv),
TALER_TESTING_make_trait_amount_obj (0,
&ds->amount),
TALER_TESTING_make_trait_absolute_time (0,
&ds->exchange_timestamp),
TALER_TESTING_trait_end ()
};
@ -599,12 +610,12 @@ TALER_TESTING_cmd_deposit (const char *label,
label);
GNUNET_assert (0);
}
ds->timestamp = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&ds->timestamp);
ds->wallet_timestamp = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&ds->wallet_timestamp);
json_object_set_new (ds->contract_terms,
"timestamp",
GNUNET_JSON_from_time_abs (ds->timestamp));
GNUNET_JSON_from_time_abs (ds->wallet_timestamp));
if (0 != refund_deadline.rel_value_us)
{
ds->refund_deadline = GNUNET_TIME_relative_to_absolute (refund_deadline);
@ -687,12 +698,12 @@ TALER_TESTING_cmd_deposit_with_ref (const char *label,
label);
GNUNET_assert (0);
}
ds->timestamp = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&ds->timestamp);
ds->wallet_timestamp = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&ds->wallet_timestamp);
json_object_set_new (ds->contract_terms,
"timestamp",
GNUNET_JSON_from_time_abs (ds->timestamp));
GNUNET_JSON_from_time_abs (ds->wallet_timestamp));
if (0 != refund_deadline.rel_value_us)
{
ds->refund_deadline = GNUNET_TIME_relative_to_absolute (refund_deadline);

View File

@ -57,6 +57,11 @@ struct InsertDepositState
*/
struct GNUNET_TIME_Relative wire_deadline;
/**
* When did the exchange receive the deposit?
*/
struct GNUNET_TIME_Absolute exchange_timestamp;
/**
* Amount to deposit, inclusive of deposit fee.
*/
@ -210,6 +215,7 @@ insert_deposit_run (void *cls,
(GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
ids->dbc->plugin->insert_deposit (ids->dbc->plugin->cls,
ids->dbc->session,
ids->exchange_timestamp,
&deposit)) ||
(GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
ids->dbc->plugin->commit (ids->dbc->plugin->cls,
@ -275,6 +281,7 @@ insert_deposit_traits (void *cls,
* @param dbc collects database plugin and session handles.
* @param merchant_name Human-readable name of the merchant.
* @param merchant_account merchant's account name (NOT a payto:// URI)
* @param exchange_timestamp when did the exchange receive the deposit
* @param wire_deadline point in time where the aggregator should have
* wired money to the merchant.
* @param amount_with_fee amount to deposit (inclusive of deposit fee)
@ -282,21 +289,24 @@ insert_deposit_traits (void *cls,
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_insert_deposit (const char *label,
const struct
TALER_TESTING_DatabaseConnection *dbc,
const char *merchant_name,
const char *merchant_account,
struct GNUNET_TIME_Relative wire_deadline,
const char *amount_with_fee,
const char *deposit_fee)
TALER_TESTING_cmd_insert_deposit (
const char *label,
const struct TALER_TESTING_DatabaseConnection *dbc,
const char *merchant_name,
const char *merchant_account,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Relative wire_deadline,
const char *amount_with_fee,
const char *deposit_fee)
{
struct InsertDepositState *ids;
GNUNET_TIME_round_abs (&exchange_timestamp);
ids = GNUNET_new (struct InsertDepositState);
ids->dbc = dbc;
ids->merchant_name = merchant_name;
ids->merchant_account = merchant_account;
ids->exchange_timestamp = exchange_timestamp;
ids->wire_deadline = wire_deadline;
ids->amount_with_fee = amount_with_fee;
ids->deposit_fee = deposit_fee;