diff options
Diffstat (limited to 'src')
25 files changed, 390 insertions, 189 deletions
diff --git a/src/auditor/taler-auditor-httpd_deposit-confirmation.c b/src/auditor/taler-auditor-httpd_deposit-confirmation.c index 5f84a7253..1039164c4 100644 --- a/src/auditor/taler-auditor-httpd_deposit-confirmation.c +++ b/src/auditor/taler-auditor-httpd_deposit-confirmation.c @@ -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), diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c index 2e32c5698..158baa8b3 100644 --- a/src/auditor/taler-helper-auditor-coins.c +++ b/src/auditor/taler-helper-auditor-coins.c @@ -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, diff --git a/src/auditor/taler-helper-auditor-deposits.c b/src/auditor/taler-helper-auditor-deposits.c index 291558590..ed23c6a52 100644 --- a/src/auditor/taler-helper-auditor-deposits.c +++ b/src/auditor/taler-helper-auditor-deposits.c @@ -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", diff --git a/src/auditordb/auditor-0001.sql b/src/auditordb/auditor-0001.sql index ff8867bee..b511a4d5b 100644 --- a/src/auditordb/auditor-0001.sql +++ b/src/auditordb/auditor-0001.sql @@ -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 diff --git a/src/auditordb/plugin_auditordb_postgres.c b/src/auditordb/plugin_auditordb_postgres.c index 467c4c6db..4f9101fdc 100644 --- a/src/auditordb/plugin_auditordb_postgres.c +++ b/src/auditordb/plugin_auditordb_postgres.c @@ -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", diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c index 21a29e506..69c73746c 100644 --- a/src/exchange/taler-exchange-aggregator.c +++ b/src/exchange/taler-exchange-aggregator.c @@ -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)); diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 65251863a..fe8fdf061 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -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)); } @@ -109,6 +112,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. */ struct TALER_Amount value; @@ -117,12 +125,11 @@ struct DepositContext /** - * Execute database transaction for /deposit. Runs the transaction - * logic; 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. IF - * it returns the soft error code, the function MAY be called again to - * retry and MUST not queue a MHD response. + * 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 @@ -131,20 +138,22 @@ struct DepositContext * @return transaction status */ static enum GNUNET_DB_QueryStatus -deposit_transaction (void *cls, - struct MHD_Connection *connection, - struct TALER_EXCHANGEDB_Session *session, - MHD_RESULT *mhd_ret) +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 spent; + 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 */); + GNUNET_YES /* check refund deadline */, + &deposit_fee, + &dc->exchange_timestamp); if (qs < 0) { if (GNUNET_DB_STATUS_HARD_ERROR == qs) @@ -166,12 +175,12 @@ deposit_transaction (void *cls, GNUNET_assert (0 <= TALER_amount_subtract (&amount_without_fee, &deposit->amount_with_fee, - &deposit->deposit_fee)); + &deposit_fee)); *mhd_ret = reply_deposit_success (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); @@ -179,6 +188,44 @@ deposit_transaction (void *cls, 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 + * NOT queue a MHD response. IF it returns an hard error, the + * transaction logic MUST queue a MHD response and set @a mhd_ret. IF + * it returns the soft error code, the function MAY be called again to + * retry and MUST not queue a MHD 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_transaction (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 spent; + enum GNUNET_DB_QueryStatus qs; + + /* 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) + return qs; /* 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) { @@ -252,45 +300,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 * further check the details of the operation specified. If everything checks @@ -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); diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index 7924ad54c..f65951614 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -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, diff --git a/src/exchangedb/exchange-0001.sql b/src/exchangedb/exchange-0001.sql index bec9af5ba..ad05e7797 100644 --- a/src/exchangedb/exchange-0001.sql +++ b/src/exchangedb/exchange-0001.sql @@ -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) diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 5bd674b2d..93577feb4 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -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, diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index eea484e94..fe3ed7854 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -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 != diff --git a/src/include/taler_auditordb_plugin.h b/src/include/taler_auditordb_plugin.h index 9a7f6ed7a..7c58e654e 100644 --- a/src/include/taler_auditordb_plugin.h +++ b/src/include/taler_auditordb_plugin.h @@ -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 diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h index 74660303d..eded23339 100644 --- a/src/include/taler_error_codes.h +++ b/src/include/taler_error_codes.h @@ -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 diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index 82b9b83df..38928dc18 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -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); diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 4fd580724..9fb932362 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -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); diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index c346a6cee..38b895d7f 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -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 diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h index 9abb0cca7..53a004c8c 100644 --- a/src/include/taler_testing_lib.h +++ b/src/include/taler_testing_lib.h @@ -1917,6 +1917,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) @@ -1924,14 +1925,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); /** diff --git a/src/lib/auditor_api_deposit_confirmation.c b/src/lib/auditor_api_deposit_confirmation.c index cddfe8b14..1856a89f4 100644 --- a/src/lib/auditor_api_deposit_confirmation.c +++ b/src/lib/auditor_api_deposit_confirmation.c @@ -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 coin’s 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 coin’s 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 (×tamp); + (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), diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c index dc44291d0..bf8eb5376 100644 --- a/src/lib/exchange_api_common.c +++ b/src/lib/exchange_api_common.c @@ -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", diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c index a5cf6c36a..276053658 100644 --- a/src/lib/exchange_api_deposit.c +++ b/src/lib/exchange_api_deposit.c @@ -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); diff --git a/src/lib/exchange_api_refund.c b/src/lib/exchange_api_refund.c index b1ea176bf..6f91389f1 100644 --- a/src/lib/exchange_api_refund.c +++ b/src/lib/exchange_api_refund.c @@ -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: diff --git a/src/testing/test_taler_exchange_aggregator.c b/src/testing/test_taler_exchange_aggregator.c index eaa621cfe..d5c392d3a 100644 --- a/src/testing/test_taler_exchange_aggregator.c +++ b/src/testing/test_taler_exchange_aggregator.c @@ -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"), diff --git a/src/testing/testing_api_cmd_auditor_deposit_confirmation.c b/src/testing/testing_api_cmd_auditor_deposit_confirmation.c index 247399a9d..1442380bf 100644 --- a/src/testing/testing_api_cmd_auditor_deposit_confirmation.c +++ b/src/testing/testing_api_cmd_auditor_deposit_confirmation.c @@ -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, diff --git a/src/testing/testing_api_cmd_deposit.c b/src/testing/testing_api_cmd_deposit.c index 9468e7acb..049f36f25 100644 --- a/src/testing/testing_api_cmd_deposit.c +++ b/src/testing/testing_api_cmd_deposit.c @@ -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. @@ -127,6 +127,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); diff --git a/src/testing/testing_api_cmd_insert_deposit.c b/src/testing/testing_api_cmd_insert_deposit.c index 356528009..cff2884aa 100644 --- a/src/testing/testing_api_cmd_insert_deposit.c +++ b/src/testing/testing_api_cmd_insert_deposit.c @@ -58,6 +58,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. */ const char *amount_with_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; |